Browse the docs

API reference

Ideas

The shelf of uncommitted bets, their evidence, critiques and the team's ranking.

List ideas

GET/v1/ideas

Up to 60 ideas, most recently updated first, with their thinking fields. critiquedAt is the date of the newest critique, not its content.

Requires ideas.read

Request
curl "https://atrix.dev/api/v1/ideas" \
  -H "Authorization: Bearer $ATRIX_TOKEN"
Response
{
  "items": [
    {
      "id": "cm9i0d1e20018gh45ij67kl89",
      "title": "After-hours booking agent for clinics",
      "note": null,
      "status": "EXPLORING",
      "problem": "Clinics lose bookings after hours.",
      "riskiestAssumption": "Owners will trust an agent with patients.",
      "cheapestTest": "Run a missed-call pilot with one clinic.",
      "tags": [
        "health",
        "voice"
      ],
      "promoted": false,
      "at": "2026-10-10T09:00:00.000Z",
      "discussion": 2,
      "critiquedAt": "2026-10-26T16:20:00.000Z",
      "author": {
        "id": "cm8q1z0a10001xy98wv76ut54",
        "name": "Moeid Saleem",
        "image": null
      }
    }
  ]
}

Get an idea

GET/v1/ideas/{id}

One idea with its 20 newest signals and newest critique. runs reports the workspace's critique allowance, and blocked gives the reason a run would be refused, if any.

Requires ideas.read

Path parameters

  • idstringrequired

    The idea id.

Request
curl "https://atrix.dev/api/v1/ideas/ID" \
  -H "Authorization: Bearer $ATRIX_TOKEN"
Response
{
  "id": "cm9i0d1e20018gh45ij67kl89",
  "title": "After-hours booking agent for clinics",
  "note": null,
  "status": "EXPLORING",
  "problem": "Clinics lose bookings after hours.",
  "riskiestAssumption": "Owners will trust an agent with patients.",
  "cheapestTest": "Run a missed-call pilot with one clinic.",
  "tags": [
    "health",
    "voice"
  ],
  "promoted": false,
  "at": "2026-10-10T09:00:00.000Z",
  "author": {
    "id": "cm8q1z0a10001xy98wv76ut54",
    "name": "Moeid Saleem",
    "image": null
  },
  "signals": [
    {
      "id": "cm9s0g1n20019mn67op89qr01",
      "kind": "CONVERSATION",
      "direction": "FOR",
      "body": "Two clinics said they miss evening calls.",
      "at": "2026-10-15T00:00:00.000Z"
    }
  ],
  "critique": {
    "id": "cm9c2r3t40017ab12cd34ef56",
    "model": "anthropic/claude-sonnet",
    "caseAgainst": "Clinics already pay for a receptionist and rarely switch mid-year.",
    "incumbents": "Weave, Podium.",
    "mustBeTrue": [
      "Clinics miss over 20% of calls",
      "An owner will pay before seeing ROI"
    ],
    "cheapestTest": "Call ten clinics after hours and count who answers.",
    "overlap": null,
    "createdAt": "2026-10-26T16:20:00.000Z"
  },
  "runs": {
    "used": 2,
    "limit": 10,
    "blocked": null
  }
}

Update an idea

PATCH/v1/ideas/{id}

Records a signal or moves the idea's status; a signal wins when both are sent. PROMOTED cannot be set here, a promoted idea cannot be moved, and KILLED or PARKED need a reason.

Requires ideas.write

Path parameters

  • idstringrequired

    The idea id.

Body

  • statusenum

    The new status.

    NEWEXPLORINGVALIDATEDPARKEDKILLED

  • reasonstring

    Why it moved, up to 2000 characters; required for PARKED and KILLED.

  • signalobject

    { kind, direction, body, source?, url?, occurredOn? }: kind is CONVERSATION, DEMAND, LINK, DATA, COMPETITOR or OBJECTION; direction is FOR, AGAINST or NEUTRAL; body is 3 to 2000 characters; occurredOn is YYYY-MM-DD.

Request
curl -X PATCH "https://atrix.dev/api/v1/ideas/ID" \
  -H "Authorization: Bearer $ATRIX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "status": "NEW", "reason": "…" }'
Response
{
  "ok": true
}

Critique an idea

POST/v1/ideas/{id}/critique

Runs the model's pressure test on an idea and returns the verdict in full. Spends one of the plan's runs and counts against the write limit.

Requires ideas.run

Path parameters

  • idstringrequired

    The idea id.

Request
curl -X POST "https://atrix.dev/api/v1/ideas/ID/critique" \
  -H "Authorization: Bearer $ATRIX_TOKEN"
Response
{
  "ok": true,
  "critique": {
    "id": "cm9c2r3t40017ab12cd34ef56",
    "model": "anthropic/claude-sonnet",
    "caseAgainst": "Clinics already pay for a receptionist and rarely switch mid-year.",
    "incumbents": "Weave, Podium.",
    "mustBeTrue": [
      "Clinics miss over 20% of calls",
      "An owner will pay before seeing ROI"
    ],
    "cheapestTest": "Call ten clinics after hours and count who answers.",
    "overlap": null,
    "createdAt": "2026-10-26T16:20:00.000Z"
  },
  "runs": {
    "used": 3,
    "limit": 10
  }
}

Get the next pair to rank

GET/v1/ideas/rank

The next two ideas for the caller to compare, chosen from their own judgements, plus progress, the team's standings (top 20) and the pairs people split on. Only NEW, EXPLORING and VALIDATED ideas are ranked; pair is null when there is nothing left.

Requires ideas.read

Request
curl "https://atrix.dev/api/v1/ideas/rank" \
  -H "Authorization: Bearer $ATRIX_TOKEN"
Response
{
  "pair": [
    {
      "id": "cm9i0d1e20018gh45ij67kl89",
      "title": "After-hours booking agent",
      "problem": "Clinics lose bookings after hours.",
      "status": "EXPLORING",
      "signals": 3,
      "author": {
        "id": "cm8q1z0a10001xy98wv76ut54",
        "name": "Moeid Saleem",
        "image": null
      }
    },
    {
      "id": "cm9i1d2e30020gh45ij67kl89",
      "title": "WhatsApp invoice reminders",
      "problem": "Clinics lose bookings after hours.",
      "status": "EXPLORING",
      "signals": 3,
      "author": {
        "id": "cm8q1z0a10001xy98wv76ut54",
        "name": "Moeid Saleem",
        "image": null
      }
    }
  ],
  "judged": 4,
  "target": 30,
  "total": 12,
  "voters": 2,
  "standings": [
    {
      "id": "cm9i0d1e20018gh45ij67kl89",
      "title": "After-hours booking agent",
      "problem": "Clinics lose bookings after hours.",
      "status": "EXPLORING",
      "signals": 3,
      "author": {
        "id": "cm8q1z0a10001xy98wv76ut54",
        "name": "Moeid Saleem",
        "image": null
      },
      "net": 3,
      "wins": 4,
      "played": 5
    }
  ],
  "contested": [
    [
      {
        "id": "cm9i0d1e20018gh45ij67kl89",
        "title": "After-hours booking agent",
        "problem": "Clinics lose bookings after hours.",
        "status": "EXPLORING",
        "signals": 3,
        "author": {
          "id": "cm8q1z0a10001xy98wv76ut54",
          "name": "Moeid Saleem",
          "image": null
        }
      },
      {
        "id": "cm9i1d2e30020gh45ij67kl89",
        "title": "WhatsApp invoice reminders",
        "problem": "Clinics lose bookings after hours.",
        "status": "EXPLORING",
        "signals": 3,
        "author": {
          "id": "cm8q1z0a10001xy98wv76ut54",
          "name": "Moeid Saleem",
          "image": null
        }
      }
    ]
  ]
}

Judge a pair

POST/v1/ideas/rank

Records that one idea beats another. A later judgement of the same pair by the same person replaces the earlier one.

Requires ideas.write

Body

  • winnerIdstringrequired

    The idea that wins.

  • loserIdstringrequired

    The idea it beats.

Request
curl -X POST "https://atrix.dev/api/v1/ideas/rank" \
  -H "Authorization: Bearer $ATRIX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "winnerId": "cm9x2k1a0000", "loserId": "cm9x2k1a0000" }'
Response
{
  "ok": true
}

Clear your ranking

DELETE/v1/ideas/rank

Deletes the caller's own judgements so they can rank again. Other people's are untouched.

Requires ideas.write

Request
curl -X DELETE "https://atrix.dev/api/v1/ideas/rank" \
  -H "Authorization: Bearer $ATRIX_TOKEN"
Response
{
  "ok": true
}