Skip to content

Build with SynthBoard

Quickstart

Each of your users gets their own office: the same experts, their own file and record, isolated per user and billed to your organization. A plain question gets a plain answer — every structured field is optional and empty unless the matter calls for it.

1. Get a test key#

In the developer console, create an organization and a test key (sbk_test_…). Test keys return sample answers from fixtures and never call a model or spend. Keep the key in your server's environment as SYNTHBOARD_KEY — never in a browser or an app bundle.

Install an SDK, or use plain HTTP:

bash
npm install @synthboard/sdk
# or
pip install synthboard

2. Create an office for one of your users#

curl

bash
curl -X POST https://www.synthboard.ai/api/v1/offices \
  -H "Authorization: Bearer $SYNTHBOARD_KEY" \
  -H "Content-Type: application/json" \
  -d '{"external_user_id":"user_123","lang":"en"}'

TypeScript

typescript
import { SynthBoard } from '@synthboard/sdk';

const sb = new SynthBoard({ apiKey: process.env.SYNTHBOARD_KEY! });
const office = await sb.createOffice({ external_user_id: 'user_123', lang: 'en' });
// Show office.notice to your user before their first ask.

Python

python
import os
from synthboard import SynthBoard

sb = SynthBoard(os.environ["SYNTHBOARD_KEY"])
office = sb.create_office({"external_user_id": "user_123", "lang": "en"})
# Show office["notice"] to your user before their first ask.

The office is keyed by your own external_user_id: creating it again returns the same office. Show its notice to your user once, before their first ask.

3. Ask it something#

curl

bash
curl -X POST https://www.synthboard.ai/api/v1/offices/$OFFICE_ID/ask \
  -H "Authorization: Bearer $SYNTHBOARD_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"kind":"question","text":"Should I take the offer?"}'

TypeScript

typescript
let turn = await sb.ask(office.id, { kind: 'question', text: 'Should I take the offer?' });

Python

python
turn = sb.ask(office["id"], {"kind": "question", "text": "Should I take the offer?"})

Every ask carries an Idempotency-Key (the SDKs send one for you): a retry returns the same turn and never buys a second answer. Within about 25 seconds you get the answer; past that, status: "working" and a turn_id.

4. Read the answer#

curl

bash
curl https://www.synthboard.ai/api/v1/offices/$OFFICE_ID/turns/$TURN_ID?wait=25 \
  -H "Authorization: Bearer $SYNTHBOARD_KEY"

TypeScript

typescript
if (turn.status === 'working') turn = await sb.waitForTurn(office.id, turn.turn_id);
console.log(turn.reply);

Python

python
if turn["status"] == "working":
    turn = sb.wait_for_turn(office["id"], turn["turn_id"])
print(turn["reply"])

Read what came back#

The JSON and the same answer rendered, side by side — the sandbox's own response. The first answer in an office carries notice; an ordinary question carries no call.

What your app sends, and what comes back

POST /v1/offices/eb692f9c-a278-4445-9548-acd8af9a1dde/ask
Idempotency-Key: panes-demo-1

{
  "text": "My landlord wants to raise the rent 9% mid-lease. Can he? (expert)"
}

{
  "schema_version": "0.8.0",
  "status": "ok",
  "turn_id": "1742fbd1-f65b-4f02-a92e-50b48dce45bd",
  "lang": "en",
  "link": "https://www.synthboard.ai/developers/sandbox",
  "speaker": "expert",
  "handoff": {
    "expert": {
      "id": "22222222-2222-4222-8222-222222222222",
      "name": "The Career Coach",
      "role": "Career Coach",
      "face": null,
      "hue": "#5b5bd6",
      "runnable": true
    },
    "brought": {
      "their_words": true,
      "fact_count": 0,
      "reads": 0
    },
    "swap_options": []
  },
  "expert_turns": [
    {
      "turn_id": "1742fbd1-f65b-4f02-a92e-50b48dce45bd",
      "session_id": "d50b092b-5f42-473f-873e-63aba1188f75",
      "matter_id": "",
      "lane_synth_id": "22222222-2222-4222-8222-222222222222",
      "expert": {
        "id": "22222222-2222-4222-8222-222222222222",
        "name": "The Career Coach",
        "role": "Career Coach",
        "face": null,
        "hue": "#5b5bd6",
        "runnable": true
      },
      "via": "route",
      "state": "delivered",
      "weight": "full",
      "body_md": "**The strongest route: lecturing at a teaching college.** A sandbox expert answer.",
      "doc": {
        "segments": [
          {
            "t": "md",
            "md": "**The strongest route: lecturing at a teaching college.** A sandbox expert answer."
          }
        ],
        "frame": {
          "call": null,
          "ask": null,
          "meta": null
        },
        "issues": [],
        "budget": {
          "components": 0,
          "interactive": 0,
          "calcs": 0,
          "by_kind": {},
          "longest_prose_words": 12,
          "limits": null
        },
        "complete": true
      },
      "call": {
        "line": "Apply to the teaching college first.",
        "would_change_it": "If another opening appears before December.",
        "when_we_know": "2026-11-15"
      },
      "split_signal": null,
      "used_from_you": [],
      "sources": [],
      "computed": [],
      "second_opinion": null,
      "checked": null,
      "follow_offer": null,
      "cost": {
        "used": null
      },
      "timing": {
        "strip_ms": null,
        "first_content_ms": null,
        "first_word_ms": null,
        "done_ms": null
      },
      "made_with": {
        "model": "sandbox",
        "lab": "sandbox",
        "recipe": "sandbox",
        "effort": "none"
      },
      "answer": {
        "shape": null,
        "reply_md": "**The strongest route: lecturing at a teaching college.** A sandbox expert answer.\n\n**My call: Apply to the teaching college first.**\nWhat would change it: If another opening appears before December.\nWhen we'll know: Sunday 15 November 2026",
        "reply_text": "The strongest route: lecturing at a teaching college. A sandbox expert answer.\n\nMy call: Apply to the teaching college first.\nWhat would change it: If another opening appears before December.\nWhen we'll know: Sunday 15 November 2026",
        "blocks": [
          {
            "type": "markdown",
            "md": "**The strongest route: lecturing at a teaching college.** A sandbox expert answer."
          }
        ],
        "drafts": [],
        "call": {
          "line": "Apply to the teaching college first.",
          "would_change_it": "If another opening appears before December.",
          "when_we_know": "2026-11-15"
        },
        "question": null
      }
    }
  ],
  "matter": null,
  "record": {},
  "speed": {
    "class": "answer",
    "expected_by": "2026-10-25T09:00:56.000Z",
    "basis": {
      "source": "static",
      "stat": "p50",
      "seconds": 56,
      "n": null,
      "measured_at": null
    }
  },
  "follow_offer": null,
  "saved_facts": [],
  "moves": [],
  "cards": [],
  "follow_ups": [],
  "files": [],
  "cost": {
    "used": 0,
    "balance_after": 0
  },
  "steps": [],
  "provenance": {
    "ai_generated": true,
    "models": [
      {
        "model": "sandbox",
        "lab": "sandbox"
      }
    ]
  },
  "opinion": {
    "who": [
      {
        "practice": "22222222-2222-4222-8222-222222222222",
        "lead": {
          "id": "22222222-2222-4222-8222-222222222222",
          "name": "The Career Coach",
          "role": "Career Coach",
          "face": null,
          "hue": "#5b5bd6",
          "runnable": true
        }
      }
    ],
    "call": {
      "line": "Apply to the teaching college first.",
      "would_change_it": "If another opening appears before December.",
      "when_we_know": "2026-11-15"
    },
    "grade": null,
    "scope_limits": [],
    "evidence": [],
    "computed": [],
    "unchecked": [],
    "method": {
      "practice_id": "22222222-2222-4222-8222-222222222222",
      "method_version": null,
      "contract_version": "0.8.0",
      "model": "sandbox",
      "lab": "sandbox",
      "recipe": "sandbox"
    }
  },
  "legacy_status": "done",
  "reply": "**The strongest route: lecturing at a teaching college.** A sandbox expert answer.",
  "agent_cards": [],
  "disclosure": "Experts and answers here are AI.",
  "notice": "Answers here come from SynthBoard's AI experts. What you send here is shared with SynthBoard to answer you."
}
See how it renders ↓
The Career Coachvia SynthBoard

The strongest route: lecturing at a teaching college. A sandbox expert answer.

The experts are AI — named roles, not people.

5. Go live#

Add credits, set a monthly cap (a live key can only be made once a cap is set), then make a live key (sbk_live_…). Live calls bill your organization's balance at actual cost after they run; nothing new starts at or below zero, and work already running always finishes. The machine-readable price list is GET /api/v1/prices.

Every endpoint, field and error: the platform reference. Agents and MCP clients: MCP tools.

The experts are AI — named roles, not people. How this works