API
DecideNext exposes a token-authenticated HTTP API so an external AI agent or script can manage a single prioritization table — reading and updating initiatives, voters, and results without going through the dashboard UI by hand.
Authentication
Every request is authenticated with a bearer token. The token identifies the table, so there is no key or ID in the URL.
Authorization: Bearer dnx_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxBase URL:
https://decidenext.app/api/v1Getting a token
- Open your manager dashboard and go to the API Access tab.
- Click Generate token and re-enter your manager password. The token (
dnx_live_…) is shown only once — copy it immediately. - Each table has one token at a time. It expires after 90 days; generate a new one from the dashboard when it does.
Rate limit
Each token is limited to 10 requests per minute. Exceeding it returns a 429 status with a Retry-After header indicating how many seconds to wait before retrying.
Errors
Errors return the matching HTTP status and a JSON body with an error code and a human-readable message:
{ "error": "not_found", "message": "Initiative not found" }400 validation_error— the request body failed validation.401 unauthorized/401 token_expired— missing/invalid token, or a token past its 90-day expiry.404 not_found— the resource does not exist in this table.429 rate_limited— rate limit exceeded; see Retry-After.
Endpoints
All paths are relative to the base URL above (e.g. GET /api/v1/table).
Table
| GET | /table | Table details |
| PUT | /table | Update name, description, or budget |
Criteria
| GET | /criteria | Weighted Decision Matrix criteria |
Initiatives
| GET | /initiatives | List initiatives |
| POST | /initiatives | Create an initiative |
| GET | /initiatives/{id} | Get a single initiative |
| PUT | /initiatives/{id} | Update an initiative |
| DELETE | /initiatives/{id} | Delete an initiative |
| PUT | /initiatives/reorder | Reorder initiatives |
| POST | /initiatives/bulk | Bulk import initiatives |
Comments
| GET | /initiatives/{id}/comments | List comments on an initiative |
| POST | /initiatives/{id}/comments | Add a comment to an initiative |
Voters
| GET | /users | List voters |
| POST | /users | Add a voter |
| DELETE | /users/{id} | Remove a voter |
| PUT | /voter-password | Set or update the voter password |
Results & progress
| GET | /results | Calculated results |
| GET | /voter-rankings | Per-voter rankings |
| GET | /progress | Voting progress |
Sharing & backup
| PUT | /public-share | Toggle the public results URL |
| GET | /backup | Full table export |
Not available to tokens: deleting the table and managing tokens. Those actions stay dashboard-only, so a leaked or misbehaving token can never destroy the table or mint/revoke other tokens.
Quick start with curl
Read the table
curl https://decidenext.app/api/v1/table \
-H "Authorization: Bearer dnx_live_xxx"Create an initiative
curl -X POST https://decidenext.app/api/v1/initiatives \
-H "Authorization: Bearer dnx_live_xxx" \
-H "Content-Type: application/json" \
-d '{"title": "Launch onboarding revamp", "description": "Q4 priority"}'Bulk import
curl -X POST https://decidenext.app/api/v1/initiatives/bulk \
-H "Authorization: Bearer dnx_live_xxx" \
-H "Content-Type: application/json" \
-d '{"initiatives": [{"title": "A"}, {"title": "B"}]}'Request & response examples
Payloads below are accurate to the API's data model. Optional fields are omitted when empty. For the complete schema of every endpoint, see the OpenAPI spec.
/tableGet table details
Response (200 OK)
{
"id": "2c9d1e7a-1f3b-4a2c-9f1e-8b7a6c5d4e3f",
"name": "Q4 Roadmap",
"description": "Candidate initiatives for next quarter",
"methodology": "ICE",
"created_at": "2026-01-15T09:30:00Z",
"updated_at": "2026-01-20T14:05:00Z",
"is_active": true,
"has_voter_password": false,
"public_share_enabled": false
}/initiativesList initiatives
Returns an array of initiatives, each with a live comment count.
Response (200 OK)
[
{
"id": "7f1e2d3c-4b5a-6978-8c7d-6e5f4a3b2c1d",
"title": "Launch onboarding revamp",
"description": "Q4 priority",
"tags": ["growth", "onboarding"],
"display_order": 1,
"status": "active",
"created_at": "2026-01-16T08:00:00Z",
"updated_at": "2026-01-16T08:00:00Z",
"comment_count": 2
}
]/initiativesCreate an initiative
Only title is required. Tags are optional; Buy a Feature tables also accept buyafeature_cost.
Request body
{
"title": "Launch onboarding revamp",
"description": "Q4 priority",
"tags": ["growth", "onboarding"]
}Response (201 Created)
{
"id": "7f1e2d3c-4b5a-6978-8c7d-6e5f4a3b2c1d",
"title": "Launch onboarding revamp",
"description": "Q4 priority",
"tags": ["growth", "onboarding"],
"display_order": 1,
"status": "active",
"created_at": "2026-01-16T08:00:00Z",
"updated_at": "2026-01-16T08:00:00Z",
"comment_count": 0
}/initiatives/{id}Update an initiative
Send only the fields you want to change. status is "active" or "archived".
Request body
{
"title": "Launch onboarding revamp v2",
"status": "active"
}Response (200 OK)
{
"id": "7f1e2d3c-4b5a-6978-8c7d-6e5f4a3b2c1d",
"title": "Launch onboarding revamp v2",
"description": "Q4 priority",
"tags": ["growth", "onboarding"],
"display_order": 1,
"status": "active",
"created_at": "2026-01-16T08:00:00Z",
"updated_at": "2026-01-21T11:15:00Z",
"comment_count": 0
}/initiatives/bulkBulk import initiatives
Up to 50 at once. Titles that already exist (case-insensitive) are skipped.
Request body
{
"initiatives": [
{ "title": "Improve search relevance", "tags": ["search"] },
{ "title": "Dark mode" }
]
}Response (201 Created)
{
"imported": 1,
"skipped": 1,
"skipped_titles": ["Dark mode"]
}/usersAdd a voter
name is required; email is optional. The response includes the voter’s unique voting URL.
Request body
{
"name": "Alex",
"email": "alex@example.com"
}Response (201 Created)
{
"id": "11111111-2222-4333-8444-555555555555",
"name": "Alex",
"email": "alex@example.com",
"access_token": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
"voter_url": "https://decidenext.app/vote/aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
"has_voted": false,
"created_at": "2026-01-16T09:00:00Z"
}/voter-passwordSet or update the voter password
A single table-wide password (minimum 6 characters) shared by all voters.
Request body
{
"password": "team-secret-2026"
}Response (200 OK)
{
"message": "Voter password set successfully"
}/resultsGet calculated results
Ranked results with aggregated scores. Which optional fields appear depends on the table’s methodology (ICE shown here).
Response (200 OK)
{
"table_name": "Q4 Roadmap",
"methodology": "ICE",
"total_voters": 3,
"voted_count": 2,
"initiatives": [
{
"id": "7f1e2d3c-4b5a-6978-8c7d-6e5f4a3b2c1d",
"title": "Launch onboarding revamp",
"tags": ["growth"],
"rank": 1,
"calculated_score": 72.5,
"vote_count": 2,
"average_scores": {
"ice_impact": 8,
"ice_confidence": 90,
"ice_ease": 7
}
}
]
}/public-shareToggle the public results URL
When enabled, the response includes a public_share_key for the read-only results page.
Request body
{
"enabled": true
}Response (200 OK)
{
"id": "2c9d1e7a-1f3b-4a2c-9f1e-8b7a6c5d4e3f",
"name": "Q4 Roadmap",
"methodology": "ICE",
"created_at": "2026-01-15T09:30:00Z",
"updated_at": "2026-01-21T10:00:00Z",
"is_active": true,
"has_voter_password": false,
"public_share_enabled": true,
"public_share_key": "dddddddd-eeee-4fff-8aaa-bbbbbbbbbbbb"
}/initiatives/{id}/commentsAdd a comment to an initiative
content is 1–180 characters. Comments created through the API are attributed to "Manager".
Request body
{
"content": "Let's prioritize this."
}Response (201 Created)
{
"id": "c0ffee00-0000-4000-8000-000000000001",
"initiative_id": "7f1e2d3c-4b5a-6978-8c7d-6e5f4a3b2c1d",
"author_name": "Manager",
"is_manager": true,
"content": "Let's prioritize this.",
"created_at": "2026-01-18T12:00:00Z"
}Retrospective API
Retro boards (the Basic / Starfish / 4Ls / Custom retrospective tool) are a separate resource from prioritization tables and are managed with their own token type. A retro token only reads and writes the single board it was generated for.
Authentication
Retro requests are authenticated the same way — a bearer token — but with a distinct prefix and base path:
Authorization: Bearer dnx_retro_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxBase URL:
https://decidenext.app/api/v1/retroThe two token types are not interchangeable. A dnx_retro_… token only works against /api/v1/retro/*, and a dnx_live_… prioritization token (above) only works against the rest of /api/v1. Each is rejected with 401 unauthorized on the other base path.
Getting a token
- Open the retro board's dashboard and go to the API Access tab.
- Click Generate token and re-enter the board's manager password. The token (
dnx_retro_…) is shown only once — copy it immediately. - Each board has one token at a time. It expires after 90 days; generate a new one from the dashboard when it does.
Rate limit & errors
Same rules as the prioritization API above: each token is limited to 10 requests per minute (429 rate_limited with a Retry-After header), and errors use the same { "error", "message" } shape.
Endpoints
All paths are relative to the retro base URL above (e.g. GET /api/v1/retro/board).
Board
| GET | /retro/board | Board details |
| PUT | /retro/board | Update board settings |
| PUT | /retro/voter-password | Set the participant password |
Participants
| GET | /retro/users | List participants |
| POST | /retro/users | Add a participant |
| DELETE | /retro/users/{id} | Remove a participant |
Cards
| GET | /retro/cards | List cards |
| POST | /retro/cards/{id}/merge | Merge one card into another |
Results & export
| GET | /retro/results | Grouped, vote-ranked results |
| POST | /retro/export | Export cards to a new prioritization table |
| POST | /retro/export-to-existing | Export cards into an existing table |
Not available to tokens: deleting the board (DELETE /board) and managing tokens. Those actions stay dashboard-only, so a leaked or misbehaving retro token can never destroy the board or mint/revoke other tokens.
Request & response examples
Payloads below are accurate to the retro API's data model. For the complete schema of every retro endpoint, see the OpenAPI spec.
/retro/boardGet board details
Response (200 OK)
{
"id": "b1a2c3d4-0000-4000-8000-000000000001",
"name": "Sprint 24 Retro",
"description": "What went well, what didn't",
"board_type": "STARFISH",
"votes_per_user": 5,
"is_active": true,
"has_voter_password": true,
"created_at": "2026-02-10T09:00:00Z",
"updated_at": "2026-02-10T09:00:00Z",
"columns": [
{
"id": "c1a2c3d4-0000-4000-8000-000000000001",
"name": "Keep doing",
"display_order": 1,
"color": "#22C55E"
},
{
"id": "c1a2c3d4-0000-4000-8000-000000000002",
"name": "Stop doing",
"display_order": 2,
"color": "#EF4444"
}
]
}/retro/exportExport cards to a new prioritization table
Creates a brand-new prioritization table (secured by manager_password) with one initiative per card. edits optionally rewrites a card's title; include_users copies retro participants in as voters.
Request body
{
"card_ids": [
"d1a2c3d4-0000-4000-8000-000000000001",
"d1a2c3d4-0000-4000-8000-000000000002"
],
"methodology": "ICE",
"table_name": "Sprint 24 Action Items",
"manager_password": "new-table-secret",
"include_users": true
}Response (201 Created)
{
"table_id": "e1a2c3d4-0000-4000-8000-000000000001",
"manager_key": "f1a2c3d4-0000-4000-8000-000000000001",
"manager_url": "https://decidenext.app/manager/f1a2c3d4-0000-4000-8000-000000000001"
}