Exam Studio
API

REST & MCP. One credit wallet.

Ounie accounts hit the REST endpoints with a bearer token. AI assistants — including the Ounie AI Team — connect over MCP and get a native tool surface. Both run the same grounded-generation pipeline, and every generation draws your shared Ounie credits (1 credit = 1¢), never overdrawing. Because an exam is grounded in your own private brain, there is no keyless x402 rail — generation requires your Ounie master key.

Authentication
Two bearer rails — both draw the same shared Ounie wallet and can never overdraw.
exb_live_…— this app's key

Minted at Dashboard → API keys. Can list, read, export the PDF, and pull the grade sheet. It has no ounie.com credential, so it cannot reach your private brains to generate — generation returns a clear 403 telling you to use your master key.

ounie_live_… — the Ounie master key

Your ounie.com developer key (enable fleet access in ounie.com settings). Forwarded upstream to reach your brains, so it's what powers grounded generation across the whole Ounie app fleet.

# Header form:
Authorization: Bearer exb_live_…      # or ounie_live_… to generate

# Or, for clients that can't set headers, as a query param:
?api_key=exb_live_…
MCP · for AI assistants and the Ounie AI Team
Streamable HTTP at /api/mcp (legacy SSE at /api/sse).
Endpoint  https://exam.ounie.com/api/mcp
Header    Authorization: Bearer ounie_live_…   # to generate
          Authorization: Bearer exb_live_…     # to list / read / export

# If your MCP client can't set headers, append the key as a query param:
https://exam.ounie.com/api/mcp?api_key=exb_live_…
ToolWhat it doesCost
generate_examBuild one formal, cited exam from your brain(s). Needs the master key.10 credits
regenerate_examRe-compose an existing exam from fresh retrieval. Needs the master key.10 credits
list_examsList the exams you've created (with take links + attempt counts).free
get_examOne exam + full question list, answer key, citations, PDF + take URLs.free
list_attemptsThe grade list for an exam: student scores + needs-review flags.free
get_credit_balanceSpendable Ounie credits + monthly included.free
get_pricingPer-action pricing. No auth required.public
whoamiThe authenticated key's owner + whether it can ground generation.free

Connect the Ounie AI Team (TabTab)

Add an HTTP MCP server pointing at https://exam.ounie.com/api/mcp?api_key=ounie_live_…. The Team can't set custom headers, so the key rides the URL — and the master key grounds generation in your brains.

REST · the same endpoints the dashboard uses
Send Authorization: Bearer exb_live_… (or ?api_key=) on any of these. Cookie sessions work too — it's the same route.
GET/api/brainsList your Ounie brains

The brain picker. Needs the master key (an upstream read of your ounie.com account).

POST/api/examsGenerate an exam
{
  "brain_ids": ["<uuid>"],
  "subject": "Cellular Biology",
  "topic": "core concepts",
  "level": "Undergraduate",
  "duration_mins": 60,
  "sections": [
    { "type": "multiple_choice", "count": 6, "points": 2 },
    { "type": "true_false",      "count": 4, "points": 1 },
    { "type": "short_answer",    "count": 2, "points": 5 }
  ]
}

Bills 10 credits. Grounded + cited from your brains — needs the master key. Thin material → 422 + full refund.

GET/api/examsList your exams

Free. Works with any key.

GET/api/exams/{id}One exam + its questions (answer key included)

Free. Owner-scoped.

PATCH/api/exams/{id}Edit the exam header (title, instructions, …)
{ "title": "Midterm — Section 2" }

Free.

POST/api/exams/{id}/regenerateRe-compose from fresh retrieval
{ "sections": [ { "type": "essay", "count": 3, "points": 10 } ] }

Bills 10 credits. Needs the master key. Omit "sections" to keep the current shape.

POST/api/exams/{id}/openOpen or close the take link
{ "open": false }

Free.

GET/api/exams/{id}/attemptsThe grade list

Free. Student scores + needs-review flags.

GET/api/exams/{id}/pdfPrintable PDF

Free. Append ?key=1 for the answer-key pages. Returns application/pdf.

DELETE/api/exams/{id}Delete an exam

Free. Cascades questions + attempts; kills the take link.

Public, no auth: POST /api/t/{token}/submit — a student submits an attempt against a take link; closed questions auto-grade server-side. The answer key never crosses to the client.
Shape of a generated exam
{
  "ok": true,
  "exam_id": "…",
  "question_count": 12,
  "total_points": 30,
  "credits_spent": 10
}

# GET /api/exams/{id} → { exam, questions } where each question carries
# its answer key + a citation pointing back to the retrieved brain page:
{
  "qtype": "multiple_choice",
  "prompt": "…",
  "points": 2,
  "options": ["…","…","…","…"],
  "correct_answer": "…",     // never sent to students
  "explanation": "…",        // answer-key rationale
  "citation": { "brainId": "…", "slug": "…", "title": "…" }
}