Back
DecideNext LogoDecideNext

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_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Base URL:

https://decidenext.app/api/v1

Getting 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/tableTable details
PUT/tableUpdate name, description, or budget

Criteria

GET/criteriaWeighted Decision Matrix criteria

Initiatives

GET/initiativesList initiatives
POST/initiativesCreate an initiative
GET/initiatives/{id}Get a single initiative
PUT/initiatives/{id}Update an initiative
DELETE/initiatives/{id}Delete an initiative
PUT/initiatives/reorderReorder initiatives
POST/initiatives/bulkBulk import initiatives

Comments

GET/initiatives/{id}/commentsList comments on an initiative
POST/initiatives/{id}/commentsAdd a comment to an initiative

Voters

GET/usersList voters
POST/usersAdd a voter
DELETE/users/{id}Remove a voter
PUT/voter-passwordSet or update the voter password

Results & progress

GET/resultsCalculated results
GET/voter-rankingsPer-voter rankings
GET/progressVoting progress

Sharing & backup

PUT/public-shareToggle the public results URL
GET/backupFull 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.

GET/table

Get 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
}
GET/initiatives

List 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
  }
]
POST/initiatives

Create 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
}
PUT/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
}
POST/initiatives/bulk

Bulk 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"]
}
POST/users

Add 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"
}
PUT/voter-password

Set 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"
}
GET/results

Get 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
      }
    }
  ]
}
PUT/public-share

Toggle 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"
}
POST/initiatives/{id}/comments

Add 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_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Base URL:

https://decidenext.app/api/v1/retro

The 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/boardBoard details
PUT/retro/boardUpdate board settings
PUT/retro/voter-passwordSet the participant password

Participants

GET/retro/usersList participants
POST/retro/usersAdd a participant
DELETE/retro/users/{id}Remove a participant

Cards

GET/retro/cardsList cards
POST/retro/cards/{id}/mergeMerge one card into another

Results & export

GET/retro/resultsGrouped, vote-ranked results
POST/retro/exportExport cards to a new prioritization table
POST/retro/export-to-existingExport 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.

GET/retro/board

Get 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"
    }
  ]
}
POST/retro/export

Export 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"
}