Build with SynthBoard
Platform reference
Version 0.1.0. Base URL https://www.synthboard.ai/api/v1, an organization key as a Bearer token. Generated from the same OpenAPI document the SDKs are built from.
POST /offices#
Create a managed office for one of your users (idempotent by external_user_id)
Scope offices:write · TypeScript sb.createOffice() · Python sb.create_office()
external_user_idrequired | string | Your own opaque id for this user (a database id or a random token — never an email address, phone number or name). Creating again with the same id returns the same office. Deleting the office removes it from usage rows. |
lang | string | null | The office language (e.g. en, he). |
timezone | string | null | An IANA time zone (e.g. Asia/Jerusalem). |
metadata | object | null | Your own data (up to 4 KB). Never sent to a model. |
idrequired | string | |
objectrequired | string | |
external_user_idrequired | string | |
environmentrequired | "live" | "sandbox" | |
langrequired | string | null | |
timezonerequired | string | null | |
metadatarequired | object | |
created_atrequired | string | |
last_call_atrequired | string | null | |
notice | string | The one line to show your user before their first ask in this office. |
Errors
400validation_error or not_available (a reserved or not-yet-served part; nothing ran)401unauthorized / invalid_credentials402insufficient_credits or monthly_budget_exceeded (nothing ran)403scope_missing / forbidden404not_found (any other organization’s or environment’s id is a 404)429rate_limited (Retry-After)503api_disabled / not_available
GET /offices#
List your managed offices (cursor-paged, newest first)
Scope offices:read · TypeScript sb.listOffices() · Python sb.list_offices()
limit (query) | integer | Page size (default 25). |
cursor (query) | string | next_cursor from the previous page. |
external_user_id (query) | string | Only the office for this user id. |
objectrequired | string | |
datarequired | object[] | |
next_cursorrequired | string | null |
Errors
400validation_error or not_available (a reserved or not-yet-served part; nothing ran)401unauthorized / invalid_credentials402insufficient_credits or monthly_budget_exceeded (nothing ran)403scope_missing / forbidden404not_found (any other organization’s or environment’s id is a 404)429rate_limited (Retry-After)503api_disabled / not_available
GET /offices/{officeId}#
Get a managed office
Scope offices:read · TypeScript sb.getOffice() · Python sb.get_office()
officeId (path)required | string |
idrequired | string | |
objectrequired | string | |
external_user_idrequired | string | |
environmentrequired | "live" | "sandbox" | |
langrequired | string | null | |
timezonerequired | string | null | |
metadatarequired | object | |
created_atrequired | string | |
last_call_atrequired | string | null | |
notice | string | The one line to show your user before their first ask in this office. |
Errors
400validation_error or not_available (a reserved or not-yet-served part; nothing ran)401unauthorized / invalid_credentials402insufficient_credits or monthly_budget_exceeded (nothing ran)403scope_missing / forbidden404not_found (any other organization’s or environment’s id is a 404)429rate_limited (Retry-After)503api_disabled / not_available
DELETE /offices/{officeId}#
Delete a managed office and erase everything in it
Scope offices:write · TypeScript sb.deleteOffice() · Python sb.delete_office()
officeId (path)required | string |
idrequired | string | |
objectrequired | string | |
deletedrequired | boolean |
Errors
400validation_error or not_available (a reserved or not-yet-served part; nothing ran)401unauthorized / invalid_credentials402insufficient_credits or monthly_budget_exceeded (nothing ran)403scope_missing / forbidden404not_found (any other organization’s or environment’s id is a 404)429rate_limited (Retry-After)503api_disabled / not_available
POST /offices/{officeId}/ask#
Ask in a managed office: her answer or an expert's (one turn per Idempotency-Key)
Scope ask · TypeScript sb.ask() · Python sb.ask()
officeId (path)required | string | |
wait (query) | integer | Seconds to wait for the answer (default 25). Past it: 202, status working, then GET the turn. |
Idempotency-Key (header) | string | The same key is the same turn: a retry returns that turn and never buys a second answer. The SDKs always send one. |
kind | "question" | "review" | "log" | |
textrequired | string | |
draft | string | |
proposed_action | object | |
matter_id | string | |
context_id | string | |
practice | string | |
experts | string[] | |
asked_in_words | string | |
supplied_facts | object[] | |
attachments | object[] | |
timezone | string | |
budget | object | |
needs_by | "now" | "today" | "whenever" | |
idempotency_key | string | |
lang | string |
schema_versionrequired | string | |
statusrequired | "ok" | "working" | "partial" | "failed" | "needs_input" | "needs_confirmation" | "upgrade_required" | |
turn_idrequired | string | |
langrequired | string | |
linkrequired | string | |
speakerrequired | "her" | "expert" | "board" | "job" | |
her | object | |
handoff | object | |
expert_turnsrequired | object[] | |
matterrequired | object | null | |
opinion | object | |
recordrequired | object | |
speedrequired | object | |
follow_offer | object | |
question | object | |
saved_factsrequired | object[] | |
surface | object | |
movesrequired | object[] | |
cardsrequired | object[] | |
follow_upsrequired | object[] | |
filesrequired | object[] | |
costrequired | object | |
refusal | object | |
stepsrequired | object[] | |
failed_reason | "no_words" | "stream_failed" | "speak_failed" | |
joined_to | string | null | |
acts | object[] | |
provenancerequired | object | |
board | object | |
reply | string | |
legacy_status | string | |
agent_cards | object[] | |
retry | boolean | |
disclosure | string | |
notice | string |
Errors
400validation_error or not_available (a reserved or not-yet-served part; nothing ran)401unauthorized / invalid_credentials402insufficient_credits or monthly_budget_exceeded (nothing ran)403scope_missing / forbidden404not_found (any other organization’s or environment’s id is a 404)429rate_limited (Retry-After)503api_disabled / not_available
GET /offices/{officeId}/turns/{turnId}#
A turn's answer (long poll with ?wait=)
Scope ask · TypeScript sb.getTurn() · Python sb.get_turn()
officeId (path)required | string | |
turnId (path)required | string | |
wait (query) | integer | Seconds to wait while the turn is working (default 0). |
schema_versionrequired | string | |
statusrequired | "ok" | "working" | "partial" | "failed" | "needs_input" | "needs_confirmation" | "upgrade_required" | |
turn_idrequired | string | |
langrequired | string | |
linkrequired | string | |
speakerrequired | "her" | "expert" | "board" | "job" | |
her | object | |
handoff | object | |
expert_turnsrequired | object[] | |
matterrequired | object | null | |
opinion | object | |
recordrequired | object | |
speedrequired | object | |
follow_offer | object | |
question | object | |
saved_factsrequired | object[] | |
surface | object | |
movesrequired | object[] | |
cardsrequired | object[] | |
follow_upsrequired | object[] | |
filesrequired | object[] | |
costrequired | object | |
refusal | object | |
stepsrequired | object[] | |
failed_reason | "no_words" | "stream_failed" | "speak_failed" | |
joined_to | string | null | |
acts | object[] | |
provenancerequired | object | |
board | object | |
reply | string | |
legacy_status | string | |
agent_cards | object[] | |
retry | boolean | |
disclosure | string | |
notice | string |
Errors
400validation_error or not_available (a reserved or not-yet-served part; nothing ran)401unauthorized / invalid_credentials402insufficient_credits or monthly_budget_exceeded (nothing ran)403scope_missing / forbidden404not_found (any other organization’s or environment’s id is a 404)429rate_limited (Retry-After)503api_disabled / not_available
GET /offices/{officeId}/matters#
The office's matters (rooms, one-offs or closed)
Scope record:read · TypeScript sb.listMatters() · Python sb.list_matters()
officeId (path)required | string | |
scope (query) | "rooms" | "one_offs" | "closed" | Which matters (default rooms). |
limit (query) | integer | Page size. |
cursor (query) | string | next_cursor from the previous page. |
objectrequired | string | |
datarequired | object[] | |
next_cursorrequired | string | null |
Errors
400validation_error or not_available (a reserved or not-yet-served part; nothing ran)401unauthorized / invalid_credentials402insufficient_credits or monthly_budget_exceeded (nothing ran)403scope_missing / forbidden404not_found (any other organization’s or environment’s id is a 404)429rate_limited (Retry-After)503api_disabled / not_available
GET /offices/{officeId}/record#
How each expert's calls in the office have turned out
Scope record:read · TypeScript sb.getRecord() · Python sb.get_record()
officeId (path)required | string |
rowsrequired | object[] |
Errors
400validation_error or not_available (a reserved or not-yet-served part; nothing ran)401unauthorized / invalid_credentials402insufficient_credits or monthly_budget_exceeded (nothing ran)403scope_missing / forbidden404not_found (any other organization’s or environment’s id is a 404)429rate_limited (Retry-After)503api_disabled / not_available
GET /offices/{officeId}/events#
What happened on the office's matters since a cursor
Scope record:read · TypeScript sb.listEvents() · Python sb.list_events()
officeId (path)required | string | |
cursor (query) | string | next_cursor from your last read: only what happened since. |
eventsrequired | object[] | |
upcoming | object[] | |
next_cursorrequired | string | null | |
more | boolean | |
delivery | string |
Errors
400validation_error or not_available (a reserved or not-yet-served part; nothing ran)401unauthorized / invalid_credentials402insufficient_credits or monthly_budget_exceeded (nothing ran)403scope_missing / forbidden404not_found (any other organization’s or environment’s id is a 404)429rate_limited (Retry-After)503api_disabled / not_available
GET /offices/{officeId}/files/{fileId}#
A file made in the office, as a signed short-lived link
Scope files:read · TypeScript sb.getFile() · Python sb.get_file()
officeId (path)required | string | |
fileId (path)required | string | |
ttl (query) | integer | Link lifetime in seconds (default 300). |
filerequired | object | |
urlrequired | string | |
expires_atrequired | string | |
ttl_secondsrequired | number |
Errors
400validation_error or not_available (a reserved or not-yet-served part; nothing ran)401unauthorized / invalid_credentials402insufficient_credits or monthly_budget_exceeded (nothing ran)403scope_missing / forbidden404not_found (any other organization’s or environment’s id is a 404)429rate_limited (Retry-After)503api_disabled / not_available
GET /usage#
This month's platform spend, calls, cap and balance, per office
Scope usage:read · TypeScript sb.getUsage() · Python sb.get_usage()
month (query) | string | YYYY-MM (default: this month, UTC). |
office_id (query) | string | One office only. |
objectrequired | string | |
environmentrequired | "live" | "sandbox" | |
monthrequired | string | YYYY-MM (UTC). |
creditsrequired | integer | Credits your offices consumed this month (1 credit = $0.01). |
callsrequired | integer | |
caprequired | integer | null | Your monthly cap in credits; null = none. |
balancerequired | integer | null | Your SynthBoard account's balance. |
officesrequired | object[] |
Errors
400validation_error or not_available (a reserved or not-yet-served part; nothing ran)401unauthorized / invalid_credentials402insufficient_credits or monthly_budget_exceeded (nothing ran)403scope_missing / forbidden404not_found (any other organization’s or environment’s id is a 404)429rate_limited (Retry-After)503api_disabled / not_available
GET /webhooks#
Your organization's webhook subscriptions
Scope webhooks:write · TypeScript sb.listWebhooks() · Python sb.list_webhooks()
okrequired | boolean | |
itemsrequired | object[] |
Errors
400validation_error or not_available (a reserved or not-yet-served part; nothing ran)401unauthorized / invalid_credentials402insufficient_credits or monthly_budget_exceeded (nothing ran)403scope_missing / forbidden404not_found (any other organization’s or environment’s id is a 404)429rate_limited (Retry-After)503api_disabled / not_available
POST /webhooks#
Subscribe to events from all your offices (signing secret returned once)
Scope webhooks:write · TypeScript sb.createWebhook() · Python sb.create_webhook()
labelrequired | string | |
urlrequired | string | |
eventsrequired | string[] |
okrequired | boolean | |
subscriptionrequired | object | |
signing_secretrequired | string | |
verify_instructionsrequired | string |
Errors
400validation_error or not_available (a reserved or not-yet-served part; nothing ran)401unauthorized / invalid_credentials402insufficient_credits or monthly_budget_exceeded (nothing ran)403scope_missing / forbidden404not_found (any other organization’s or environment’s id is a 404)429rate_limited (Retry-After)503api_disabled / not_available
DELETE /webhooks/{id}#
Delete a webhook subscription
Scope webhooks:write · TypeScript sb.deleteWebhook() · Python sb.delete_webhook()
id (path)required | string |
okrequired | boolean | |
deletedrequired | boolean |
Errors
400validation_error or not_available (a reserved or not-yet-served part; nothing ran)401unauthorized / invalid_credentials402insufficient_credits or monthly_budget_exceeded (nothing ran)403scope_missing / forbidden404not_found (any other organization’s or environment’s id is a 404)429rate_limited (Retry-After)503api_disabled / not_available
Your own SynthBoard (personal keys)#
A personal key (sb_live_…) acts on your own SynthBoard and spends your credits, within the allowance you set in Settings › Connections › AI apps.
meta
GET /api/v1/health— Unauthenticated health probeGET /api/v1/prices— The machine-readable price list: plans, what a credit is worth, the rate, the about-number per kind of work (unauthenticated)
agent
POST /api/v1/ask— Ask their Chief of Staff (Idempotency-Key: one turn, one charge; about 25 s, then working + turn_id)GET /api/v1/turns/{id}— A turn's answer (long poll with ?wait_seconds=)GET /api/v1/events— What happened on their matters since a cursorGET /api/v1/record— Their record with each expert: resolved calls per expert and domainGET /api/v1/contexts/{id}— One context the key's grant opens: what it is for, its own shape (`schema`: record types and their fields), members, files, kept records (each with its `type`, its `fields` by the schema's keys and the page each came from), decisions; ?query= adds the matching pagesPOST /api/v1/contexts/{id}/proposals— Propose records into a granted context in its own shape (`type`, `fields` by the schema's keys, sub-rows' `cells`); kept only when the person keeps them
matters
GET /api/v1/matters— Their matters (rooms, one-offs or closed), pagedGET /api/v1/matters/{id}— One matter: its record, its files, whether it is followedPOST /api/v1/matters/{id}/follow— Stop following (on: false); Keep following stays the person's own yes (409 with the quote)POST /api/v1/matters/{id}/watch— Stop watching for a reply (on: false); starting a watch stays the person's own yes (409 with the price and the link)
sessions
POST /api/v1/sessions— Start a session (plan_id or explicit setup; session_type boardroom | consult)GET /api/v1/sessions— List sessions with filter/sort/cursorPOST /api/v1/sessions/plan— Propose a session setup + credit estimate without startingGET /api/v1/sessions/{id}— Get session state + latest task (v4_phase, decision_brief, memo, board_artifact)PATCH /api/v1/sessions/{id}— Rename / retag a sessionDELETE /api/v1/sessions/{id}— Hard-delete a draft sessionPOST /api/v1/sessions/{id}/continue— Follow-up round (legacy-engine sessions)POST /api/v1/sessions/{id}/reconvene— Chain a new board round on a completed V4 board (returns new_session_id)POST /api/v1/sessions/{id}/messages— Send one Consult turn (expert reply + composed document)POST /api/v1/sessions/{id}/cancel— Cancel the in-flight taskPOST /api/v1/sessions/{id}/outcomes— Generate a deliverable (action plan / report / memo / bullets)POST /api/v1/sessions/{id}/export— Export as markdown / JSON / textPOST /api/v1/sessions/{id}/archive— Archive or unarchivePOST /api/v1/sessions/{id}/fork— Duplicate with altered context (rerun optional)POST /api/v1/sessions/{id}/update— Mid-session mutations (synths, mode, DNA tuning)GET /api/v1/sessions/{id}/live-summary— Live consensus snapshotGET /api/v1/sessions/{id}/cross-round— Cross-round position trendsPOST /api/v1/sessions/{id}/assistant— Ask the Session AssistantPOST /api/v1/sessions/{id}/bookmarks— Bookmark a moment or pin a threadPOST /api/v1/sessions/{id}/decisions— Capture a formal decision recordPOST /api/v1/sessions/{id}/promote-to-synth— Promote session documents into synth knowledge
calls
POST /api/v1/calls— Put a call on the record from her card (the person's yes; one start per card)GET /api/v1/calls— List 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 outcomePOST /api/v1/calls/{id}— Report a decision or an outcome (pending until the person confirms)
synths
POST /api/v1/synths/chat— 1-on-1 chat with a synth in a sessionGET /api/v1/synths— List synths (core + public + your own)POST /api/v1/synths— Create a custom synthGET /api/v1/synths/{id}— Get a synthPATCH /api/v1/synths/{id}— Update a custom synthDELETE /api/v1/synths/{id}— Delete a custom synthPATCH /api/v1/synths/{id}/preferences— Set per-user core-synth preferencesDELETE /api/v1/synths/{id}/preferences— Reset core-synth preferencesGET /api/v1/synths/{id}/knowledge— List a synth's knowledge filesPOST /api/v1/synths/{id}/knowledge— Add knowledge (URL or text)DELETE /api/v1/synths/{id}/knowledge/{fileId}— Remove a knowledge file
catalog
GET /api/v1/catalog/search— Search synths / modes / templates / strategies / models
shares
GET /api/v1/shares— List shares for a sessionPOST /api/v1/shares— Create a share linkDELETE /api/v1/shares/{id}— Revoke a share by share codePOST /api/v1/shares/verify-password— Verify a password-protected share
actions
POST /api/v1/actions/execute— Execute a Recommended Action via a connected toolPOST /api/v1/actions/undo— Undo an executed action (30 s window)GET /api/v1/integrations— List connected integration providers
webhooks
GET /api/v1/webhooks— List webhook subscriptionsPOST /api/v1/webhooks— Create a subscription (signing secret returned once)PATCH /api/v1/webhooks/{id}— Update / enable / disable a subscriptionDELETE /api/v1/webhooks/{id}— Delete a subscriptionGET /api/v1/webhooks/{id}/deliveries— Recent delivery attempts for a subscription
files
GET /api/v1/files/{id}— A file made for the person (Word, Excel, PDF, calendar, PNG) as a signed short-lived link