Manifst API Documentation
Welcome to the Manifst REST API v1 documentation. API access is included starting from the Portfolio plan, and is billed based on the plan of the account owning the key. Accounts subscribed prior to the current pricing model retain their access.
baseUrl and apiKey in the collection variables.Introduction
Base URL:
https://manifst.net/api/v1/
All responses are returned in JSON format with the following structure:
// Success
{
"data": { ... }, // object or array
"meta": { "total": 42 } // present on list responses
}
// Error
{
"error": {
"code": "INSUFFICIENT_SCOPE",
"message": "This API key does not have the required scope: 'projects:write'."
}
}
Authentication
All requests must include your API key in the Authorization HTTP header:
Authorization: Bearer mfst_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Generate a key
Navigate to Settings → API Keys in your Manifst dashboard. API keys are shown only once upon creation.
Request example
curl https://manifst.net/api/v1/projects \
-H "Authorization: Bearer mfst_live_xxxxx"
Rate limiting
| Window | Limit |
|---|---|
| Per hour | 1,000 requests |
| Per month | 10,000 requests |
Every response includes these HTTP headers:
X-RateLimit-Limit-Hour: 1000
X-RateLimit-Remaining-Hour: 847
X-RateLimit-Limit-Month: 10000
X-RateLimit-Remaining-Month: 9231
X-RateLimit-Reset-Hour: 1711234567
When quota is exceeded, the API returns HTTP 429 with a Retry-After header (seconds until reset).
Pagination & incremental refresh
Large collection endpoints — /tickets and /time-entries — support optional pagination and incremental filtering. Without these parameters, responses remain identical to legacy versions (backward compatible).
| Parameter | Description |
|---|---|
page | Page number (default 1). Enables pagination. |
per_page | Page size (default 100, max 500). Enables pagination. |
updated_since | Returns only items updated since this date (YYYY-MM-DD or ISO datetime). Ideal for Power BI incremental refresh. |
The meta object always returns the true total count before pagination:
GET /api/v1/tickets?project=abc-123&page=2&per_page=50&updated_since=2026-07-01
{
"data": [ ... ],
"meta": { "total": 320, "count": 50, "page": 2, "per_page": 50 }
}
Error codes
| Code | HTTP | Description |
|---|---|---|
| MISSING_API_KEY | 401 | Missing Authorization header |
| INVALID_API_KEY | 401 | Key not found |
| REVOKED_API_KEY | 401 | Key revoked |
| EXPIRED_API_KEY | 401 | Key expired |
| PLAN_REQUIRED | 403 | Portfolio plan required |
| ACCOUNT_INACTIVE | 403 | Account inactive |
| IP_NOT_ALLOWED | 403 | IP address not whitelisted |
| INSUFFICIENT_SCOPE | 403 | Missing scope on the API key |
| RATE_LIMIT_EXCEEDED | 429 | Quota limit reached |
| NOT_FOUND | 404 | Resource not found |
| FORBIDDEN | 403 | Access to resource forbidden |
| VALIDATION_ERROR | 422 | Missing or invalid parameter |
| METHOD_NOT_ALLOWED | 405 | HTTP method not supported |
Scopes
Each API key is assigned a set of scopes defining its permissions. Available scopes:
| Scope | Description |
|---|---|
| projects:read | Read projects and project members |
| projects:write | Create, edit, and delete projects |
| super-epics:read | Read super-epics |
| super-epics:write | Create, edit, and delete super-epics |
| epics:read | Read epics |
| epics:write | Create, edit, and delete epics |
| sprints:read | Read sprints |
| sprints:write | Create and edit sprints |
| tickets:read | Read tickets |
| tickets:write | Create, edit, and delete tickets |
| comments:read | Read ticket comments |
| comments:write | Create, edit, and delete comments |
| team:read | Read project team members |
| time:read | Read time entries |
| time:write | Log time entries |
| statuses:read | Read project statuses |
| finance:read | Read finance / EVM indicators (project & portfolio) |
| roadmap:read | Read roadmap dependencies and milestones |
Projects
Required scope: projects:read
curl /api/v1/projects -H "Authorization: Bearer mfst_live_xxx"
// Response 200
{
"data": [
{
"uuid": "abc-123",
"name": "My Project",
"description": "Description",
"color": "#6366f1",
"default_dod": ["Code review done", "Tests passing"],
"contingency_pct": 10.0,
"budget": 350000.00,
"user_role": "owner",
"member_count": 5,
"created_at": "2026-01-15 10:00:00",
"updated_at": "2026-03-01 14:22:00"
}
],
"meta": { "total": 1 }
}
Required scope: projects:read
curl /api/v1/projects/abc-123 -H "Authorization: Bearer mfst_live_xxx"
Required scope: team:read
Required scope: projects:write
Project creation automatically initializes the 6 default statuses (Backlog, To Do, In Progress, In Review, Done, Blocked) and 2 default ticket types (Story, Bug).
Body
{
"name": "My Project", // required, 1–80 chars
"description": "...", // optional
"color": "#6366f1", // optional, hex #rrggbb
"default_dod": ["Tests OK", "Code review"], // optional — Definition of Done (array)
"contingency_pct": 10.00, // optional — financial reserve, 0–100% (default: 10)
"budget": 350000.00 // optional — BAC / budget at completion (≥ 0, null to clear)
}
Response 201
{
"data": {
"uuid": "...",
"name": "My Project",
"description": null,
"color": "#6366f1",
"default_dod": null,
"contingency_pct": 10.0,
"budget": 350000.00,
"user_role": "owner",
"created_at": "2026-03-24 20:00:00",
"updated_at": "2026-03-24 20:00:00"
}
}
Required scope: projects:write — owner only
Body
{
"name": "New name", // optional
"description": "...", // optional
"color": "#f59e0b", // optional
"default_dod": ["item 1", "item 2"], // optional — null or [] to clear
"contingency_pct": 15.00, // optional — 0–100%
"budget": 420000.00 // optional — BAC (≥ 0, null to clear)
}
Response 200
{
"data": {
"uuid": "...",
"name": "New name",
"description": null,
"color": "#f59e0b",
"default_dod": ["item 1", "item 2"],
"contingency_pct": 15.0,
"budget": 420000.00,
"user_role": "owner",
"created_at": "2026-03-24 20:00:00",
"updated_at": "2026-03-24 20:00:00"
}
}
Required scope: projects:write — owner only
// Response 200
{ "data": { "deleted": true } }
Super-epics
Required scope: super-epics:read
Required scope: super-epics:read
Required scope: super-epics:write
Body
{
"project_uuid": "abc-123",
"title": "Title",
"description": "...", // optional
"status": "backlog", // optional — backlog | in_progress | done (default: backlog)
"tags": ["tag-uuid-1"] // optional — array of tag UUIDs
}
Response 201
{
"data": {
"uuid": "...",
"project_id": 1,
"title": "Title",
"description": null,
"status": "backlog",
"created_at": "2026-03-24 20:00:00",
"updated_at": "2026-03-24 20:00:00",
"tags": [{ "uuid": "tag-uuid", "name": "bug" }]
}
}
Required scope: super-epics:write
Body
{
"title": "New title", // optional
"description": "...", // optional
"status": "in_progress", // optional — backlog | in_progress | done
"tags": ["tag-uuid-1"] // optional — replaces all tags
}
Response 200
{
"data": {
"uuid": "...",
"project_id": 1,
"title": "New title",
"description": null,
"status": "in_progress",
"created_at": "2026-03-24 20:00:00",
"updated_at": "2026-03-24 20:00:00",
"tags": [{ "uuid": "tag-uuid", "name": "bug" }]
}
}
Required scope: super-epics:write — linked epics are unlinked, not deleted.
Epics
Required scope: epics:read
Required scope: epics:read
Required scope: epics:write
Body
{
"project_uuid": "abc-123",
"title": "Title",
"description": "...", // optional
"super_epic_uuid": "se-uuid", // optional
"status": "backlog", // optional — backlog | todo | in_progress | in_review | done | blocked (default: backlog)
"tags": ["tag-uuid-1"] // optional — array of tag UUIDs
}
Response 201
{
"data": {
"uuid": "...",
"project_id": 1,
"super_epic_id": null,
"super_epic_uuid": null,
"title": "Title",
"description": null,
"status": "backlog",
"created_at": "2026-03-24 20:00:00",
"updated_at": "2026-03-24 20:00:00",
"tags": [{ "uuid": "tag-uuid", "name": "bug" }]
}
}
Required scope: epics:write
Body
{
"title": "...", // optional
"description": "...", // optional
"super_epic_uuid": null, // optional — uuid or null to unlink
"status": "done", // optional — backlog | todo | in_progress | in_review | done | blocked
"tags": ["tag-uuid-1"] // optional — replaces all tags
}
Response 200
{
"data": {
"uuid": "...",
"project_id": 1,
"super_epic_id": null,
"super_epic_uuid": null,
"title": "...",
"description": null,
"status": "done",
"created_at": "2026-03-24 20:00:00",
"updated_at": "2026-03-24 20:00:00",
"tags": [{ "uuid": "tag-uuid", "name": "bug" }]
}
}
Required scope: epics:write — linked tickets are unlinked.
Sprints
Required scope: sprints:read
Required scope: sprints:read
Required scope: sprints:write
Body
{
"project_uuid": "abc-123",
"title": "Sprint 1",
"goal": "...", // optional
"status": "planning", // optional — planning | active | completed (default: planning)
"start_date": "2026-04-01", // optional
"end_date": "2026-04-14", // optional
"dod": ["item 1", "item 2"] // optional — Sprint Definition of Done (array)
}
Response 201
{
"data": {
"uuid": "...",
"project_id": 1,
"title": "Sprint 1",
"goal": null,
"status": "planning",
"start_date": "2026-04-01",
"end_date": "2026-04-14",
"dod": null,
"created_at": "2026-03-24 20:00:00"
}
}
Required scope: sprints:write
Body
{
"title": "Sprint 1", // optional
"status": "active", // optional — planning | active | completed
"goal": "...", // optional
"start_date": "2026-04-01", // optional
"end_date": "2026-04-14", // optional
"dod": ["item 1"] // optional — null or [] to clear
}
Response 200
{
"data": {
"uuid": "...",
"project_id": 1,
"title": "Sprint 1",
"goal": null,
"status": "active",
"start_date": "2026-04-01",
"end_date": "2026-04-14",
"dod": ["item 1"],
"created_at": "2026-03-24 20:00:00"
}
}
Tickets
Required scope: tickets:read
Optional query filters: ?sprint={uuid} and ?epic={uuid}
Required scope: tickets:read
{
"data": {
"uuid": "...", "title": "...", "description": "...",
"priority": "haute", "status": "todo", "story_points": 5,
"epic_id": 1, "sprint_id": 2, "assignee": "Alice Martin",
"acceptance_criteria": ["Criteria 1", "Criteria 2"],
"dependencies": [{ "uuid": "...", "title": "Other story" }],
"tags": [{ "uuid": "tag-uuid", "name": "bug" }],
"subtasks": [
{ "uuid": "...", "title": "Technical task", "status": "todo",
"sort_order": 1, "assignee_id": 3, "assignee_name": "Alice Martin",
"created_at": "2026-03-25 10:00:00", "updated_at": "2026-03-25 10:00:00" }
],
"subtasks_total": 1,
"subtasks_done": 0
}
}
Required scope: tickets:write
Body
{
"project_uuid": "abc-123",
"title": "As a user...",
"description": "...",
"priority": "haute", // critique | haute | normale | faible
"status": "backlog", // backlog | todo | in_progress | in_review | done | blocked
"story_points": 5, // optional
"epic_uuid": "epic-uuid", // optional
"sprint_uuid": "sprint-uuid",// optional
"assignee_id": 3, // optional
"acceptance_criteria": ["Criteria 1"], // optional
"dependencies": ["us-uuid-1"], // optional
"tags": ["tag-uuid-1"] // optional — array of tag UUIDs
}
Response 201
{
"data": {
"uuid": "...",
"project_id": 1,
"epic_id": null,
"sprint_id": null,
"assignee_id": null,
"assignee": null,
"title": "As a user...",
"description": null,
"priority": "haute",
"status": "backlog",
"story_points": 5,
"created_at": "2026-03-24 20:00:00",
"updated_at": "2026-03-24 20:00:00",
"acceptance_criteria": ["Criteria 1"],
"dependencies": [],
"tags": [{ "uuid": "tag-uuid", "name": "bug" }]
}
}
Required scope: tickets:write
Body
{
"title": "...", // optional
"description": "...", // optional
"priority": "haute", // optional — critique | haute | normale | faible
"status": "in_progress", // optional — backlog | todo | in_progress | in_review | done | blocked
"story_points": 8, // optional
"epic_uuid": "epic-uuid", // optional — uuid or null to unlink
"sprint_uuid": "sprint-uuid", // optional — uuid or null to unlink
"assignee_id": 3, // optional — id or null
"acceptance_criteria": ["Criteria 1"], // optional — replaces existing criteria
"dependencies": ["us-uuid-1"], // optional — replaces existing dependencies
"tags": ["tag-uuid-1"] // optional — replaces all tags
}
Response 200
{
"data": {
"uuid": "...",
"project_id": 1,
"epic_id": null,
"sprint_id": null,
"assignee_id": null,
"assignee": null,
"title": "...",
"description": null,
"priority": "haute",
"status": "in_progress",
"story_points": 8,
"created_at": "2026-03-24 20:00:00",
"updated_at": "2026-03-24 20:00:00",
"acceptance_criteria": ["Criteria 1"],
"dependencies": [],
"tags": [{ "uuid": "tag-uuid", "name": "bug" }]
}
}
Required scope: tickets:write
Subtasks
Subtasks have fixed statuses (todo, in_progress, done), independent of project custom statuses. They serve as a technical checklist linked to a ticket.
Required scope: tickets:read
{
"data": [
{
"uuid": "...",
"title": "Technical task",
"status": "todo", // todo | in_progress | done
"sort_order": 1,
"assignee_id": 3,
"assignee_name": "Alice Martin",
"created_at": "2026-03-25 10:00:00",
"updated_at": "2026-03-25 10:00:00"
}
],
"meta": { "total": 1 }
}
Required scope: tickets:write
Body
{
"ticket_uuid": "us-uuid", // required
"title": "Technical task", // required
"status": "todo", // optional — todo | in_progress | done (default: todo)
"assignee_id": 3 // optional
}
Response 201
{
"data": {
"uuid": "...", "title": "Technical task", "status": "todo",
"sort_order": 1, "assignee_id": null, "assignee_name": null,
"created_at": "...", "updated_at": "..."
}
}
Required scope: tickets:write
Body
{
"title": "...", // optional
"status": "in_progress", // optional — todo | in_progress | done
"assignee_id": 3, // optional — id or null to unassign
"sort_order": 2 // optional
}
Response 200
{
"data": {
"uuid": "...", "title": "...", "status": "in_progress",
"sort_order": 2, "assignee_id": 3, "assignee_name": "Alice Martin",
"created_at": "...", "updated_at": "..."
}
}
Required scope: tickets:write
Comments
Comments are attached to a ticket. Only the author (or an administrator) can edit or delete their own comments. Content is sanitized HTML (scripts and JS event handlers removed).
Required scope: comments:read
| Parameter | Type | Description |
|---|---|---|
us | string | Ticket UUID — required |
Response 200
{
"data": [
{
"uuid": "...",
"author_id": 3,
"author_name": "Alice Martin",
"author_initials": "AM",
"content": "<p>Comment content</p>",
"mentions": [4, 7],
"ticket_uuid": "...",
"created_at": "2026-04-02 10:00:00",
"updated_at": "2026-04-02 10:00:00"
}
],
"meta": { "total": 1 }
}
Required scope: comments:read
Required scope: comments:write
Body
{
"ticket_uuid": "...", // required — Ticket UUID
"content": "<p>My comment</p>", // required — Sanitized HTML
"mentions": [4, 7] // optional — Mentioned user IDs
}
Response 201
{
"data": {
"uuid": "...",
"author_id": 3,
"author_name": "Alice Martin",
"author_initials": "AM",
"content": "<p>My comment</p>",
"mentions": [4],
"ticket_uuid": "...",
"created_at": "2026-04-02 10:00:00",
"updated_at": "2026-04-02 10:00:00"
}
}
Required scope: comments:write — author or admin only.
Body
{
"content": "<p>Updated content</p>", // optional
"mentions": [4, 7] // optional — replaces full mention list
}
Required scope: comments:write — author or admin only.
{ "data": { "deleted": true } }
Team
Required scope: team:read
{
"data": [
{
"uuid": "...", "firstname": "Alice", "lastname": "Martin",
"email": "alice@example.com", "scrum_role": "dev",
"project_role": "member", "status": "active",
"tjm": 550.00, "service": "Delivery"
}
],
"meta": { "total": 4 }
}
tjm = average daily rate (cost/day) of the member on this project, used as the basis for financial indicators; null if unspecified.
Time entries
Required scope: time:read
Optional filter: ?story={uuid} for a specific story.
Required scope: time:write
Body
{
"ticket_uuid": "story-uuid", // required
"duration_minutes": 90, // required
"logged_at": "2026-03-24", // required, format YYYY-MM-DD
"comment": "Code review" // optional
}
Response 201
{
"data": {
"uuid": "...",
"ticket_id": 12,
"user_id": 3,
"user_name": "Alice Martin",
"ticket_uuid": "...",
"ticket_title": "As a user...",
"duration_minutes": 90,
"comment": "Code review",
"logged_at": "2026-03-24 00:00:00",
"created_at": "2026-03-24 20:00:00"
}
}
Statuses
Required scope: statuses:read
Returns all project statuses (default and custom), sorted by sort_order.
Response 200
[
{
"key": "backlog",
"label": "Backlog",
"color": "#64748b",
"bg_color": "#f1f5f9",
"sort_order": 1,
"is_done": false,
"is_default": true
},
{
"key": "in_validation",
"label": "In Validation",
"color": "#7c3aed",
"bg_color": "#f5f3ff",
"sort_order": 7,
"is_done": false,
"is_default": false
}
]
Dependencies
Finish-to-start links between roadmap items (epic or super-epic). Each node is exposed by its UUID (resolvable via /epics and /super-epics) to reconstruct the graph and compute the critical path client-side.
Required scope: roadmap:read
{
"data": [
{
"uuid": "dep-uuid",
"type": "FS", // finish-to-start
"pred_type": "epic", // epic | super_epic
"pred_uuid": "epic-uuid-1",
"succ_type": "epic",
"succ_uuid": "epic-uuid-2"
}
],
"meta": { "total": 1 }
}
Milestones
Required scope: roadmap:read
{
"data": [
{ "uuid": "...", "name": "Go-live", "date": "2026-09-30", "color": "#e11d48" }
],
"meta": { "total": 1 }
}
Finance / EVM
Project Earned Value Management (EVM) performance indicators, computed server-side from story points, logged time (× TJM), and the declared BAC (projects.budget).
bac, pv, ev, cpi, cv, sv, eac, etc, vac, tcpi) evaluate to null as long as no BAC is declared for the project. Progress and cost metrics (ac, engaged_charge, spi, progress_pct, planned_pct) remain calculated.Required scope: finance:read
{
"data": {
"project_uuid": "abc-123",
"bac": 350000.00, // budget at completion (declared)
"base_budget": 315000.00, // BAC − contingency reserve
"reserve": 35000.00, // contingency reserve (included in BAC)
"contingency_pct": 10.00,
"pv": 326341.95, // planned value = % planned SP to date × BAC
"ev": 257455.27, // earned value = % completed SP × BAC
"ac": 186573.75, // actual cost = Σ (time ÷ 480) × TJM
"engaged_charge": 137253.75, // actual cost of unfinished epics
"cpi": 1.38, // EV ÷ AC (> 1 = under budget)
"spi": 0.79, // % completed ÷ % planned (> 1 = ahead of schedule)
"tcpi": 0.57, // (BAC − EV) ÷ (BAC − AC)
"eac": 253639.45, // estimate at completion = BAC ÷ CPI
"etc": 67065.70, // estimate to complete = EAC − AC
"vac": 96360.55, // variance at completion = BAC − EAC
"cv": 70881.52, // cost variance = EV − AC
"sv": -68886.68, // schedule variance = (% completed − % planned) × BAC
"total_sp": 503,
"done_sp": 370,
"planned_sp": 469.10,
"progress_pct": 73.56, // % completed SP
"planned_pct": 93.24 // % planned SP to date
}
}
Portfolio
EVM roll-up across all projects accessible to the API key holder — a single request replacing project-by-project polling. Consolidated indexes are calculated on the sum of values (EV, PV, AC), not an average of ratios.
Required scope: finance:read
Optional query filter: ?projects=uuid1,uuid2 to target a specific team / program.
{
"data": {
"totals": {
"projects": 12, "with_bac": 4, "without_bac": 8,
"bac": 1250000.00, "pv": 910000.00, "ev": 742000.00, "ac": 690000.00,
"engaged_charge": 305000.00,
"cpi": 1.08, "spi": 0.82,
"eac": 1157407.41, "vac": 92592.59,
"cv": 52000.00, "sv": -168000.00,
"ac_all": 812000.00, // AC across ALL projects (BAC declared or not)
"engaged_all": 410000.00 // committed charge across all projects
},
"projects": [
{ "project_uuid": "abc-123", "project_name": "CMA-CGM", "bac": 350000.00, "ev": 257455.27, "ac": 186573.75, "cpi": 1.38, "spi": 0.79, "vac": 96360.55, "engaged_charge": 137253.75, "...": "..." }
]
},
"meta": { "total": 12 }
}
Manifst API v1 Documentation · Back to site