Skip to content

Developers

Calls API

Put a person’s question on the record from your own product. Each expert answers before seeing what the person thinks or what the others said, says how sure they are and what would change their mind, and names the day you will know. When it is settled, the person says how it went and every answer is scored.

Authentication#

Every request carries a Bearer key (sb_live_…) made at /mcp/console, or an OAuth token. Starting and reporting need the session:write scope; reading needs session:read. Open the console.

The flow#

  1. Ask her. Send the person’s situation to their Chief of Staff with the MCP tool synthboard.ask (one JSON-RPC POST to /api/mcp with the same key). She answers, or returns a card that sizes it — one expert or a board — with the card’s number and a next_action naming synthboard.call.start.
  2. Show the card and get the person’s yes. Nothing spends without it.
  3. Start it: POST /api/v1/calls with the card_id. One start per card; a repeat returns the same call.
  4. Read it: GET /api/v1/calls/{id}?wait_seconds=40 until status is done. The answers stay sealed until every expert has answered.
  5. Report it: when the person tells you what they did, or how it went, POST /api/v1/calls/{id}. The report waits for the person to confirm it on SynthBoard; only then does the record move.
1 · Ask her (MCP)
bash
curl https://www.synthboard.ai/api/mcp \
  -H "Authorization: Bearer sb_live_…" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"synthboard.ask","arguments":{"message":"Should we raise our price from $29 to $39 a month?"}}}'
# The reply may arrive as a server-sent event: the JSON is on its data: line.
# Its card (next_actions → synthboard.call.start) carries the card_id.
2 · Start it, on the person’s yes
bash
curl -X POST https://www.synthboard.ai/api/v1/calls \
  -H "Authorization: Bearer sb_live_…" \
  -H "Content-Type: application/json" \
  -d '{"card_id":"5b0c2f8e-1d4a-4e8b-9a61-2f3c7d9e4a10"}'
3 · Read the answers
bash
curl "https://www.synthboard.ai/api/v1/calls/9d2e41c7-6b3f-4a58-8c1e-0f7a2b5d6e93?wait_seconds=40" \
  -H "Authorization: Bearer sb_live_…"
4 · Report how it went
bash
curl -X POST https://www.synthboard.ai/api/v1/calls/9d2e41c7-6b3f-4a58-8c1e-0f7a2b5d6e93 \
  -H "Authorization: Bearer sb_live_…" \
  -H "Content-Type: application/json" \
  -d '{"stage":"outcome","outcome":{"result":"well"},"idempotency_key":"outcome-9d2e41c7"}'

Endpoints#

MethodPathWhat it does
POST/api/v1/callsPut a call on the record from her card (the person's yes; one start per card)
GET/api/v1/callsList the person's calls on the record (status, paged)
GET/api/v1/calls/{id}A call: each expert's take, the chair, the dates, the decision and the outcome
POST/api/v1/calls/{id}Report a decision or an outcome (pending until the person confirms)

POST /api/v1/calls

FieldTypeWhat it is
card_iduuidThe card from synthboard.ask whose next_action names synthboard.call.start.
gutobject, optionalA decision only, and only if the person said it before any answer: {choice: take | pass | unsure | other, p?: 0..1, text?}.
idempotency_keystring, optionalAccepted for symmetry; the card already starts once.

POST /api/v1/calls/{id}

FieldTypeWhat it is
stagedecision | outcomeWhat the person is telling you.
decisionobject{choice: followed | didnt | still_open | other, followed_take_id?, text?} — with stage decision.
outcomeobject{result: well | badly | mixed | cant_tell, text?} — with stage outcome.
idempotency_keystring, optionalThe same key returns the same report for a day.

GET /api/v1/calls

QueryTypeWhat it is
statusopen | decided | resolved | on | allDefault on (open, decided and resolved).
beforetimestamp, optionalThe page before this created_at (next_before from the last page).
limit1–50Default 20.
bash
curl "https://www.synthboard.ai/api/v1/calls?status=open&limit=20" \
  -H "Authorization: Bearer sb_live_…"

The envelope#

Every call endpoint answers with the same envelope the MCP tools return: what to tell the person (message), the lead answer (take), what to do next (next_actions, each with the tool and arguments to run), and the call block with every expert’s answer. No trace, correlation or account ids leave it — only the call id, the room id and their links.

GET /api/v1/calls/{id} — 200
json
{
  "status": "done",
  "ref": {
    "kind": "call",
    "id": "9d2e41c7-6b3f-4a58-8c1e-0f7a2b5d6e93",
    "url": "https://synthboard.ai/session/3f6a9b21-7c4d-4e15-a8b2-c9d0e1f2a3b4"
  },
  "take": {
    "call": "Raise to $39 for new customers now; keep existing customers at $29 for 90 days.",
    "why": [
      "Churn is low and the price is under the market."
    ],
    "would_change": "If new-customer conversion at $39 drops by more than a fifth in 30 days.",
    "confidence": 0.8,
    "floor": "If new-customer conversion at $39 drops by more than a fifth in 30 days.",
    "resolve_by": "2026-11-20T12:00:00.000Z",
    "record": {
      "resolved": 3,
      "held": 2,
      "partly": 1,
      "missed": 0
    }
  },
  "objects": [],
  "next_actions": [
    {
      "id": "decide:9d2e41c7-6b3f-4a58-8c1e-0f7a2b5d6e93",
      "kind": "resolve",
      "label": "When the person tells you what they did, report it (flagged until they confirm)",
      "tool": "synthboard.call.resolve",
      "args": {
        "call_id": "9d2e41c7-6b3f-4a58-8c1e-0f7a2b5d6e93",
        "stage": "decision",
        "decision": {
          "choice": "followed",
          "followed_take_id": "a1c3e5f7-0b2d-4f6a-8c9e-1a3b5c7d9e0f"
        }
      },
      "due": "2026-10-23T12:00:00.000Z"
    },
    {
      "id": "do:a1c3e5f7-0b2d-4f6a-8c9e-1a3b5c7d9e0f",
      "kind": "start",
      "label": "Have The CFO do the move: \"Raise to $39 for new customers now; keep existing customers at $29 for 90 days.\" — about 130 credits, billed at actual cost (the person said yes)",
      "tool": "synthboard.job.start",
      "args": {
        "title": "Raise to $39 for new customers now; keep existing customers at $29 for 90 days.",
        "brief": "The CFO's answer on \"Should we raise our price from $29 to $39 a month?\": Raise to $39 for new customers now; keep existing customers at $29 for 90 days. What would change their mind: If new-customer conversion at $39 drops by more than a fifth in 30 days. The person wants the move done: lay out the first steps with dates, and draft anything that has to be written or sent. Keep to the answer; if something on file contradicts it, say so first.",
        "lead_expert": "6255b274-75e8-456c-884b-db200bc15fbb",
        "gets": [
          {
            "kind": "plan",
            "noun": "plan",
            "count": 1
          },
          {
            "kind": "drafts",
            "noun": "drafts",
            "count": null
          }
        ],
        "steps": [
          "Read the answer and what would change it",
          "Lay out the first steps, with dates",
          "Draft what has to be written or sent"
        ],
        "language": "en",
        "call_id": "9d2e41c7-6b3f-4a58-8c1e-0f7a2b5d6e93",
        "idempotency_key": "do-this-a1c3e5f7-0b2d-4f6a-8c9e-1a3b5c7d9e0f"
      },
      "due": null
    },
    {
      "id": "record:6255b274-75e8-456c-884b-db200bc15fbb",
      "kind": "record",
      "label": "The CFO's record with this person",
      "tool": "synthboard.record",
      "args": {
        "synth_id": "6255b274-75e8-456c-884b-db200bc15fbb"
      },
      "due": null
    },
    {
      "id": "record:47bdcabc-89fa-4475-adfc-19be5e9be94c",
      "kind": "record",
      "label": "The Skeptic's record with this person",
      "tool": "synthboard.record",
      "args": {
        "synth_id": "47bdcabc-89fa-4475-adfc-19be5e9be94c"
      },
      "due": null
    },
    {
      "id": "open:9d2e41c7-6b3f-4a58-8c1e-0f7a2b5d6e93",
      "kind": "open",
      "label": "Open the room on SynthBoard",
      "tool": null,
      "args": null,
      "due": null
    }
  ],
  "cost": {
    "estimate": null,
    "charged": null
  },
  "check_back_seconds": null,
  "message": "On the record: 2 answers. Show the person each expert's answer, how sure, and what would change their mind — as they are. When they decide, report it with synthboard.call.resolve.",
  "call": {
    "id": "9d2e41c7-6b3f-4a58-8c1e-0f7a2b5d6e93",
    "question": "Should we raise our price from $29 to $39 a month?",
    "shape": "decision",
    "domain": "money",
    "room": {
      "kind": "board",
      "id": "3f6a9b21-7c4d-4e15-a8b2-c9d0e1f2a3b4",
      "url": "https://synthboard.ai/session/3f6a9b21-7c4d-4e15-a8b2-c9d0e1f2a3b4"
    },
    "status": "open",
    "decide_by": "2026-10-23T12:00:00.000Z",
    "resolve_by": "2026-11-20T12:00:00.000Z",
    "created_at": "2026-10-18T08:52:00.000Z",
    "takes": [
      {
        "take_id": "a1c3e5f7-0b2d-4f6a-8c9e-1a3b5c7d9e0f",
        "synth_id": "6255b274-75e8-456c-884b-db200bc15fbb",
        "expert": "The CFO",
        "position_kind": "decision",
        "call": "Raise to $39 for new customers now; keep existing customers at $29 for 90 days.",
        "stance": "for",
        "confidence": 0.8,
        "floor": "If new-customer conversion at $39 drops by more than a fifth in 30 days.",
        "check_back": {
          "days": 30,
          "what": "New-customer conversion at $39 against the last 30 days at $29."
        },
        "resolve_by": "2026-11-20T12:00:00.000Z",
        "far_seat": false,
        "dissent": false,
        "joined_later": false,
        "record_badge": {
          "resolved": 3,
          "held": 2,
          "partly": 1,
          "missed": 0
        }
      },
      {
        "take_id": "b2d4f6a8-1c3e-4a7b-9d0f-2b4c6d8e0a1b",
        "synth_id": "47bdcabc-89fa-4475-adfc-19be5e9be94c",
        "expert": "The Skeptic",
        "position_kind": "decision",
        "call": "Don’t raise the whole base yet; run a 20-customer test first.",
        "stance": "against",
        "confidence": 0.7,
        "floor": "If the test cohort keeps more than 95% of its revenue after 60 days.",
        "check_back": {
          "days": 60,
          "what": "Revenue kept by the test cohort."
        },
        "resolve_by": "2026-11-20T12:00:00.000Z",
        "far_seat": false,
        "dissent": false,
        "joined_later": false,
        "record_badge": null
      }
    ],
    "waiting_on": [],
    "chair": {
      "agree": [
        "Both want the price change tested on new customers before existing ones."
      ],
      "split": [
        {
          "who": [
            "The CFO",
            "The Skeptic"
          ],
          "on": "Whether to raise now or after a 20-customer test."
        }
      ],
      "line": "They agree on testing first; they split on timing."
    },
    "flips": [],
    "gut": null,
    "decision": null,
    "outcome": null,
    "pending_report": null,
    "asked": null
  },
  "do_this": {
    "title": "Raise to $39 for new customers now; keep existing customers at $29 for 90 days.",
    "expert": "The CFO",
    "synth_id": "6255b274-75e8-456c-884b-db200bc15fbb",
    "take_id": "a1c3e5f7-0b2d-4f6a-8c9e-1a3b5c7d9e0f",
    "tool": "synthboard.job.start",
    "args": {
      "title": "Raise to $39 for new customers now; keep existing customers at $29 for 90 days.",
      "brief": "The CFO's answer on \"Should we raise our price from $29 to $39 a month?\": Raise to $39 for new customers now; keep existing customers at $29 for 90 days. What would change their mind: If new-customer conversion at $39 drops by more than a fifth in 30 days. The person wants the move done: lay out the first steps with dates, and draft anything that has to be written or sent. Keep to the answer; if something on file contradicts it, say so first.",
      "lead_expert": "6255b274-75e8-456c-884b-db200bc15fbb",
      "gets": [
        {
          "kind": "plan",
          "noun": "plan",
          "count": 1
        },
        {
          "kind": "drafts",
          "noun": "drafts",
          "count": null
        }
      ],
      "steps": [
        "Read the answer and what would change it",
        "Lay out the first steps, with dates",
        "Draft what has to be written or sent"
      ],
      "language": "en",
      "call_id": "9d2e41c7-6b3f-4a58-8c1e-0f7a2b5d6e93",
      "idempotency_key": "do-this-a1c3e5f7-0b2d-4f6a-8c9e-1a3b5c7d9e0f"
    },
    "estimate": 130
  },
  "disclosure": "The experts are AI — named roles, not people."
}
FieldWhat it is
statusrunning while the experts answer, done once the answers are in, needs_input when an expert asked first, failed for a void call.
refThe call: kind "call", its id, and the room’s link on SynthBoard.
takeThe lead answer in one line, with why, what would change it and how sure.
objectsAlways empty for a call (jobs fill it).
next_actionsWhat to do next, in order: each with a label to say, the tool and the arguments to run it, and a due date when there is one.
costestimate is the card’s number on a start; charged stays null (the room bills at actual cost).
check_back_secondsWhile running, when to read again.
messageOne line to tell the person, or to act on.
callThe call block (below).
do_thisThe next move as one job: an expert does it end to end after the person’s yes. Null while it runs, or when there is nothing to do.
cardThe sealed answers as a card a host can render (MCP Apps). Set by the server read.
disclosureThe one line to show the first time you relay an expert: the experts are AI.

call

FieldWhat it is
idThe call id.
questionThe question as it was put on the record.
shapedecision, plan, build, draft, question, work or other.
domainmoney, people, product, career, family, legal, health, study or other.
roomconsult (one expert) or board (several), with the room’s id and link.
statusopen, decided, resolved, lapsed or void.
decide_byWhen the person said they would decide.
resolve_byWhen we will know how it went.
created_atWhen it went on the record.
takesEach expert’s first answer (below).
waiting_onExperts still answering, by name.
chairWhere they agree, where they split, and one line on both.
flipsWho changed their mind after reading the others, from what to what, and whether new evidence moved them.
gutThe person’s own first answer, when they gave one.
decisionWhat the person did, once reported.
outcomeHow it went, once reported.
pending_reportA report waiting for the person to confirm it.
askedAn expert’s question before answering; reply with synthboard.consult.message.

call.takes[]

FieldWhat it is
take_idThe answer’s id (a decision report can name it as followed_take_id).
synth_idThe expert’s id.
expertThe expert’s name.
position_kinddecision, recommendation, estimate, draft or answer.
callThe answer, in one line.
stanceA decision only: for, against, conditional or unsure.
confidenceHow sure, 0 to 1, or null when they would not put a number on it.
floorWhat would change their mind.
check_backWhen to look again, and at what.
resolve_byWhen we will know.
far_seatAn outside view: an expert from outside the field.
dissentSeated because everyone else agreed, to argue the other side.
joined_laterAnswered after the room had spoken.
record_badgeThe person’s record with this expert, or null before anything resolved.

Each answer carries the person’s record with that expert (record_badge: resolved, held, partly, missed), or null before anything resolved. Counts only, never a percentage.

Money#

Starting costs the room it runs, quoted on her card: about 45 credits for one expert, about 95 credits for a board on Free. Each card shows what a room like it typically costs; you pay for what it really used. Each key’s daily credit limit applies. Reading, listing and reporting are free.

Errors#

json
{
  "error": {
    "code": "not_found",
    "message": "No call with that id on this account.",
    "correlation_id": "c0ffee12",
    "http_status": 404
  }
}
CodeTypeWhat it is
unauthorized401No key, or a key that is not valid.
scope_missing403The key lacks session:read or session:write.
not_found404No card or call with that id on this account.
validation_error400A field is missing or malformed, or the card has nothing to put on the record.
invalid_session_state400The card is already starting, or opened a room that is not on the record.
insufficient_credits402The balance cannot cover the card’s number.
failed_precondition412This is off on SynthBoard right now; run the card’s other next_action.
rate_limited429Too many requests; wait retry_after_s.

Webhooks#

Subscribe to call.decision_due, call.outcome_due, call.floor_crossed, call.answers_sealed to hear when something happens on a person’s matter. Signing, retries and payloads: Webhooks.

The Ask the board button#

Not ready for the API? Drop in the button. It opens SynthBoard in a new tab with the question already in the composer — /try for someone signed out (free, three experts answering sealed), Home for someone signed in. Nothing is sent until they press send.

Two lines on any page
html
<div data-synthboard-ask data-question-from="#question"></div>
<script src="https://www.synthboard.ai/embed/board.js" async></script>
AttributeTypeWhat it is
data-synthboard-ask—Marks where the button goes. Elements added later are picked up too.
data-questiontextThe question to carry (500 characters at most).
data-question-fromCSS selectorRead the question from this field when the button is pressed (an input, a textarea, or any element’s text).
data-langauto · en · heThe label’s language. auto reads the page’s lang.
data-variantfilled · outlinefilled is the brand action; outline sits beside your own primary button.
data-themelight · dark · autoauto follows the visitor’s system setting.
data-labeltextYour own label (40 characters at most).
js
// Or from your own code:
SynthBoard.mount(document.querySelector('#ask'), { question: () => form.question.value, lang: 'he' });
SynthBoard.open('Should we raise our price from $29 to $39?'); // from a click handler

The question rides in the URL fragment (#q=), which browsers never send to a server, so it stays out of logs. The script makes no network requests, sets no cookies, frames nothing and runs no eval; it works under a strict Content-Security-Policy that allows the script’s origin (or its nonce).