Skip to content

Developers

qbrin API reference

Ask your company brain over HTTP. Authenticate with an API key, push in your knowledge, then POST a question and get a source-cited answer — or a clear abstain. This reference covers every endpoint, field and status code.

https://app.qbrin.com/apiCited, or it abstainsScoped keys
POST/api/askcited or abstains
curl https://app.qbrin.com/api/ask \
  -H "Authorization: Bearer qbrin_3f9a…c1d7" \
  -H "Content-Type: application/json" \
  -d '{ "question": "What is our refund window?", "k": 8 }'

Overview

The qbrin REST API turns everything your team has connected into cited, grounded answers. Every response either links to the exact source it came from, or tells you it does not know — it is built to cite or abstain rather than guess. All requests are made over HTTPS to a single base URL.

Base URLhttps://app.qbrin.com/api
Cited or it abstains

Answers carry citations to the source, or return a plain "not in your records". Designed for zero false accepts.

Permission-aware

Answers respect the source permissions of the key's owner.

JSON or streaming

Get the whole answer as JSON, or stream tokens over Server-Sent Events for a live UI.

Scoped keys

Issue read-only, read-write or admin keys per integration, and revoke any of them in one click.

Authentication

Every request authenticates with an API key sent as a Bearer token. Create one in the console under Settings → API keys. The key is shown once at creation and always starts with qbrin_ — store it somewhere safe, because it can never be retrieved again.

Authorization: Bearer qbrin_3f9a…c1d7

Key scopes

Give each integration the least privilege it needs. Scope is enforced per HTTP method, so a read-only key that leaks can never write.

ScopeCan do
readGET requests only — search and read-only lookups. Note: asking a question is a POST, so it needs write.
writeEverything read can, plus POST / PUT / PATCH / DELETE — asking questions, adding content, feedback.
adminFull access. Note: ZIP upload additionally requires the key's owner to be a workspace admin.

Add content

Two ways to push knowledge in over the API. Both feed the same pipeline — text is chunked, embedded into the vector index and entity-extracted automatically. There is no separate "embed" call; you watch it complete (next section) and then it is answerable.

POST/api/documentsscope: write

Send text or markdown directly. Best for programmatic, per-document ingestion.

FieldTypeDescription
contentstringrequiredThe document body (plain text or markdown). Up to ~800,000 characters.
titlestringoptionalA title for the document. Defaults to "Untitled document".
curl https://app.qbrin.com/api/documents \
  -H "Authorization: Bearer qbrin_3f9a…c1d7" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Refund Policy", "content": "Customers may request a full refund within 30 days…" }'
POST/api/uploads/zipadmin only

Bulk-ingest a folder of files by uploading a single .zip. qbrin streams the archive to disk (never buffering it in memory), verifies it is a real ZIP by its magic bytes, extracts the text from supported files, and ingests each one. The request returns immediately with a job id; a worker does the heavy lifting.

RequirementDetail
Content-Typemultipart/form-data, exactly one file field.
FormatA genuine .zip archive (checked by header, not extension).
Max size100 MB compressed.
AvailabilityThe key's owner must be a workspace admin, and file upload must be enabled for your workspace.
curl https://app.qbrin.com/api/uploads/zip \
  -H "Authorization: Bearer qbrin_3f9a…c1d7" \
  -F "file=@handbook.zip"

Embedding & status

You never call an embed endpoint directly. Everything you ingest flows through one pipeline — extract text, chunk, embed into the vector index, extract entities — and only becomes answerable once the embedding step finishes. These endpoints let you watch that happen.

  1. queued
  2. extract
  3. embedding
  4. done

Track a ZIP upload

GET/api/uploads/{jobId}/status

Poll with the jobId from the upload response until phase is "done".

{
  "jobId": "upload-7c1e9a4b2f0d",
  "phase": "embedding",        // queued | extract | embedding | done | error
  "state": "done",
  "ingested": 42,              // files turned into documents
  "skipped": 3,                // unsupported / empty files
  "embed": { "total": 380, "embedded": 294 },   // chunks embedded — progress bar
  "files": [ "handbook/onboarding.md", "handbook/pto.pdf" ],
  "error": null
}

Track a single document

GET/api/documents/{id}

For content added via POST /api/documents, fetch the document and read chunkCounts — it moves from pending to embedded as the vector index fills in.

{
  "document": { "id": "doc_a91f22e0", "title": "Refund Policy", "extractStatus": "done" },
  "chunkCounts": { "pending": 0, "embedded": 6, "extracted": 6 }
}

Use GET /api/documents?limit=50 to list recently ingested documents. Embedding is fully managed — the model, dimensions and hardware are a server-side detail you do not configure per request.

Ask

POST/api/askscope: write

The core endpoint. Send a question; qbrin retrieves across the connected sources, composes an answer grounded in what it found, verifies it, and returns the answer with its citations. If the answer is not supported, it abstains instead of guessing. Asking logs a query, so it is a POST and needs a write (or admin) key.

Request body

FieldTypeDescription
questionstringrequiredThe question to answer. Up to 4,000 characters.
kintegeroptionalHow many source excerpts to retrieve. 1–20, default 12.

Example request

curl https://app.qbrin.com/api/ask \
  -H "Authorization: Bearer qbrin_3f9a…c1d7" \
  -H "Content-Type: application/json" \
  -d '{ "question": "What is our refund window?", "k": 8 }'

Response 200

{
  "answer": "Customers may request a full refund within 30 days of purchase. [1]",
  "queryId": "qy_8fb2a1c0",
  "citations": [
    {
      "n": 1,
      "documentId": "doc_a91f",
      "source": "gdrive",
      "title": "Refund Policy.pdf",
      "snippet": "…a full refund within 30 days of purchase…",
      "authorEmail": "ops@acme.com",
      "occurredAt": "2026-03-11T00:00:00Z"
    }
  ],
  "trust": {
    "decision": "allow",
    "level": "verified",
    "axes": { "provenance": "cited", "entailment": "passed" },
    "certificateId": "a1b2c3d4e5f6"
  },
  "usage": { "prompt_tokens": 1840, "completion_tokens": 42 },
  "timings": { "retrieveMs": 210, "totalMs": 640 }
}

The trust object

When present, an answer also carries a trust certificate so you can decide programmatically whether to show, flag or withhold it. Use it as an additional signal on top of the citation check above.

FieldValuesMeaning
decisionallow abstain blockShip it, it did not know, or it was withheld as unsupported.
levelverified · cited_unverified · abstained · blockedHow strongly the answer was checked.
axesprovenance, entailment, …Per-check results; unmeasured checks read not_assessed rather than a fake pass.
certificateIdstringA stable id for auditing or logging the exact verdict.

Streaming (Server-Sent Events)

Send Accept: text/event-stream to stream the answer token-by-token. Read named events until done.

EventPayload
tokenAn answer fragment. A reset marks a verified replacement — discard what streamed and take the next stream.
citationsThe sources, so you can render them alongside the text.
doneFinal envelope: queryId, trust (when present), usage, timings.
followups2–3 suggested next questions (may arrive after done).
errorA failure occurred mid-stream; payload is { message }. Stop consuming and surface or retry — a done will not arrive.

You may also see informational qwsec and fallback events. Ignore any event name you do not recognise so the stream stays forward-compatible.

curl -N https://app.qbrin.com/api/ask \
  -H "Authorization: Bearer qbrin_3f9a…c1d7" \
  -H "Accept: text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{ "question": "Summarize last quarter wins" }'

event: token
data: {"text":"We closed 12 enterprise "}
event: citations
data: {"citations":[…]}
event: done
data: {"queryId":"qy_8fb2","trust":{"decision":"allow"}}

Answer feedback

POST/api/{queryId}/feedbackscope: write

Tell qbrin whether an answer was useful, using the queryId returned by /api/ask. This tunes future answers.

FieldDescription
helpfulrequired1 helpful · 0 neutral · -1 not helpful.
curl https://app.qbrin.com/api/qy_8fb2a1c0/feedback \
  -H "Authorization: Bearer qbrin_3f9a…c1d7" \
  -H "Content-Type: application/json" \
  -d '{ "helpful": 1 }'

Action authorization

POST/v1/authorizepublic sandbox / zero-auth

Verify before AI acts. Qbrin is an evidence-backed authorization layer for AI agents. Before an agent takes an important action, Qbrin checks whether the action is actually justified by current evidence, permissions, and company policy. It then returns ALLOW, HOLD, or ESCALATE.

Even simpler: Qbrin is a safety layer between AI agents and the tools they use. It checks whether an action has enough proof and permission before letting it happen.

FieldDescription
actionrequiredAction or tool name (e.g. browser_action, refund_payment, deploy_production, merge).
argsoptionalKey-value map of action parameters and targets.
evidenceoptionalArray of evidence objects (human approval, CI status, customer ticket) verifying the action. Evidence you attach yourself is untrusted until it is attested by a system of record.
curl -X POST https://app.qbrin.com/v1/authorize \
  -H "Content-Type: application/json" \
  -d '{
    "action": "browser_action",
    "args": {
      "action": "click",
      "target": "#confirm-order",
      "url": "https://internal.portal.net/orders/409"
    }
  }'

When the evidence is not trusted

browser_action above needs no evidence, so it is decided on access and policy alone. A gated action such as refund_payment needs evidence, and evidence the caller supplies is untrusted (authority: "caller"). The gate therefore answers escalate with reason evidence_untrusted; the proof shows exactly which authorities it would have accepted. Allowing it takes evidence attested by a system of record, which is what keeps an agent from vouching for its own action.

curl -X POST https://app.qbrin.com/v1/authorize \
  -H "Content-Type: application/json" \
  -d '{
    "action": "refund_payment",
    "args": { "paymentId": "PAY_123", "amount": 48500, "currency": "INR" },
    "evidence": [
      { "kind": "customer_request",
        "value": "Customer refund request of INR 48500 for PAY_123 approved by Finance" },
      { "kind": "refund_policy",
        "value": "Policy 2026: full refunds allowed within 30 days" }
    ]
  }'

Manage API keys

You will normally create and revoke keys in the console (Settings → API keys), but the same operations are available programmatically. These run in your signed-in session, not with a Bearer key.

MethodPathPurpose
GET/api/auth/tokensList your keys (name, prefix, last used) — never the secret.
POST/api/auth/tokensCreate a key: name, optional scopes and expiresInDays. Returns the raw token once.
DELETE/api/auth/tokens/{id}Revoke a key immediately.
// 201 Created — the raw secret is returned exactly once, at token.token
{
  "token": {
    "id": "tok_a1b2c3",
    "name": "ci-pipeline",
    "prefix": "qbrin_3f9a",
    "scopes": ["read"],
    "expiresAt": null,
    "createdAt": "2026-07-12T00:00:00Z",
    "token": "qbrin_3f9a2b7c8d1e…c1d7"
  }
}

Errors & limits

Errors return a JSON body { "error": "…" } with a standard HTTP status.

StatusMeaning & fix
400Bad request — e.g. missing question/content, or over the character limit. Fix the payload.
401Missing or invalid API key. Check the Authorization header.
403The key's scope does not permit this action (e.g. a read key doing a POST, or ZIP upload without admin). Issue a wider-scoped key.
404Resource not found — e.g. an unknown queryId, document or job id.
413Payload too large — a document over ~800k characters, or a ZIP over 100 MB.
429Rate limited. Back off and retry with exponential backoff.
503A required model or embedder is not configured server-side. Transient — retry or contact support.

Rate limits

Requests are rate-limited per key to protect the service — comfortable for normal interactive and batch use. If you expect sustained high volume, reach out at hello@qbrin.com and we will raise your ceiling.

See it answer

See it answer your hardest question.

Bring one real question your team keeps re-asking. We’ll connect a source, read-only, and show you the answer, sourced, in seconds, in a 20-minute walkthrough. Nothing changes in your tools.

  • One source connected, read-only
  • Your real question answered, with sources
  • Nothing changes in your tools