Zeriq Teams API

Bring your AI teammates into your own systems: keep their knowledge in sync, ask them questions, run rooms, and track the action items that come out of them.

  • Base URL: https://api.zeriq.app/v1
  • Reference: every endpoint, parameter and field is in the API reference. The OpenAPI 3.1 spec is at https://api.zeriq.app/v1/openapi.json.
  • SDKs: official TypeScript and Python SDKs: npm install zeriq-team (npm) and pip install zeriq-team (PyPI). They handle retries, idempotency keys, paging, live room streams and webhook verification. Any HTTP client works too.

1. Get an API key

Owners and admins create keys in Settings → Developers (Growth plan and up). Choose:

  • Scopes, which say what the key may do (table below).
  • Tool access: what AI teammates may do with tools when this key asks:
    • none (default)
    • read_only (search and read only)
    • allowed (an explicit list of tools, which may change things; Business plan)
  • Optionally an IP allowlist and an expiry. A monthly credit cap can be set now; it will be enforced once per-key usage tracking ships.

The key (zqt_sk_live_…, or zqt_sk_test_… outside production) is shown once. Keep it on your server and never put it in a web page or mobile app: anyone who has it can act for your workspace within its scopes.

ScopeAllows
knowledge:read / knowledge:writeList, get and search documents / add, upsert and delete them
personas:readList AI teammates
chat:read / chat:writeRead this key's conversations / ask AI teammates
rooms:read / rooms:writeRead / run rooms this key created
rooms:read:allRead every room in the workspace (read only)
tasks:read / tasks:writeList / create and update action items
meetings:readMeeting bots, transcripts and reports
actions:executeNeeded with tools: "allowed" on ask
webhooks:manageCreate and manage webhook endpoints

2. First call

export ZERIQ_TEAM_API_KEY=zqt_sk_…
curl https://api.zeriq.app/v1/me -H "Authorization: Bearer $ZERIQ_TEAM_API_KEY"

It returns your workspace, the key's scopes and its tool access. The same call with the SDKs:

// npm install zeriq-team
import Zeriq from "zeriq-team";
const zq = new Zeriq(); // reads ZERIQ_TEAM_API_KEY
console.log(await zq.me());
# pip install zeriq-team
from zeriq_team import Zeriq
print(Zeriq().me())  # reads ZERIQ_TEAM_API_KEY

The SDKs use https://api.zeriq.app by default. Set ZERIQ_TEAM_BASE_URL to use another environment.

Ask an AI teammate next:

curl https://api.zeriq.app/v1/personas -H "Authorization: Bearer $ZERIQ_TEAM_API_KEY"

curl https://api.zeriq.app/v1/personas/prs_…/ask \
  -H "Authorization: Bearer $ZERIQ_TEAM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input": "What changed in our refund policy?"}'

3. Conventions

  • IDs are prefixed: doc_, room_, msg_, ai_ (action item), bot_, prs_ (persona), conv_, chk_ (search chunk).

  • Lists return {"object": "list", "data": [...], "next_cursor": ...}. Pass cursor for the next page; it's null on the last page.

  • Errors look like {"error": {"type", "code", "message", "param", "request_id"}}. Codes to handle:

    • invalid_parameter
    • invalid_api_key
    • insufficient_scope (param is the missing scope)
    • tool_not_permitted
    • credits_exhausted
    • plan_limit
    • not_found (also for other workspaces' objects)
    • rate_limited
    • not_an_org_member
    • invite_limit
  • Request IDs: every response has an X-Request-Id. Quote it when you contact support.

  • Idempotency: send an Idempotency-Key (any unique string) on POSTs. A retry with the same key within 24 h gets the original response instead of doing the work twice.

  • Rate limits are per key, per minute, by plan:

    PlanRequests per minute
    Free30
    Growth60
    Business300
    • Calls that use AI credits count 6×.
    • knowledge/search counts ½.
    • Every response carries RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset.
    • A 429 comes with Retry-After: wait that many seconds before retrying.
  • Credits: calls that use AI return usage: {credits_charged, model, downgraded} and a Zeriq-Credits-Remaining header. The API never quietly switches to a cheaper model. When credits run out you get credits_exhausted, unless you pass allow_downgrade: true.

4. What you can build

Keep knowledge in sync

Upsert each document by your own external_id. A new version replaces the old one only once it's processed, so searches never see a gap. POST /knowledge/search returns the best passages with no AI model and no credits.

Ask an AI teammate

POST /personas/{id}/ask {input, conversation_id?, use_knowledge?, tools?, model?, allow_downgrade?} returns:

  • the answer
  • citations
  • tools_used
  • conversation_id, to continue the thread
  • usage

Run rooms

POST /rooms with AI teammates (personas) and, optionally:

  • people from your workspace (members: [{email} | {member_id}]). Only current members can be added; anyone else gets 400 not_an_org_member.
  • a host, who can also end the room in the web app.
  • notify: "email" | "none". Invites are limited to 50 people per key per day.

Your key posts as itself and shows as "via " in the web app; it can never post as a person. Teammates reply in the background. The response to your message has a run_id: stream that run's events (section 6, Live room events), or poll GET /rooms/{id}/messages?after=<your message id>. POST /rooms/{id}/end generates the summary, action plan and action items.

A key sees only the rooms it created, unless it has rooms:read:all.

Track action items

GET /action-items?room_id&status&assignee&since lists them across every room you can read. PATCH /action-items/{id} {status?, external_ref?} links one to where it's tracked, e.g. a Linear issue or a PR.

Meetings

Read-only for now: bots, transcripts and reports under /meetings/bots.

5. Webhooks

Instead of polling, let Zeriq tell you when something happens. Add an https endpoint in Settings → Developers, or with POST /webhooks/endpoints (scope webhooks:manage). You can choose which events it gets; by default it gets all of them. The signing secret (whsec_…) is shown once.

Each delivery is a POST with a JSON body:

{"id": "evt_…", "type": "action_item.created", "created": 1767225600, "org_id": "…", "data": {"action_item": {…}}}

data uses the same shapes as the API: a room, message, action_item, document or bot.

Check the signature before trusting a delivery. The SDKs do it for you with verifyWebhook(rawBody, header, secret) (TypeScript) and zeriq_team.webhooks.verify(raw_body, header, secret) (Python), or you can write it yourself. The Zeriq-Signature header is t=<unix seconds>,v1=<hex>, where v1 is the HMAC-SHA256 of <t>.<raw body> keyed with your secret:

  • Compare the HMAC in constant time.
  • Reject a t older than 5 minutes.
  • Use the raw body exactly as received; parsed and re-serialized JSON won't match.
import crypto from "node:crypto";

function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const signatures = header.split(",").filter((p) => p.startsWith("v1=")).map((p) => p.slice(3));
  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex");
  return signatures.some((s) => s.length === expected.length && crypto.timingSafeEqual(Buffer.from(s), Buffer.from(expected)));
}
import hashlib, hmac, time

def verify(raw_body: bytes, header: str, secret: str) -> bool:
    parts = [p.split("=", 1) for p in header.split(",")]
    t = next(v for k, v in parts if k == "t")
    if abs(time.time() - int(t)) > 300:
        return False
    expected = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return any(hmac.compare_digest(expected, v) for k, v in parts if k == "v1")

Retries:

  • Answer with any 2xx within 10 seconds. Anything else, or no answer, is retried for about a day: after 1 minute, 5 minutes, 30 minutes, 2 hours, 5 hours, then 8 hours twice.
  • Deliveries are at least once, so use the event id to ignore repeats.
  • If deliveries keep failing for 3 days, the endpoint is turned off and your workspace's admins get an email. Fix it, then turn it back on.

Other tools:

  • Send test delivers a webhook.test event right away and shows the response.
  • The deliveries log (GET /webhooks/deliveries) shows each attempt's status code, timing and error, and can send again.
  • Rotate secret issues a new one. For 24 hours, deliveries carry a second v1= signed with the old secret, so you can switch without missing any.
EventWhen
room.created, room.endedA room starts or ends
room.message.createdA message is posted by a person, an AI teammate or an API key
room.summary.ready, room.report.readyA summary or report is generated
action_item.created, action_item.updatedAn action item is added, marked done or open, or linked
document.ready, document.failedA document finishes processing
meeting.bot.status_changed, meeting.report.readyA meeting bot's status changes; its report is ready
credits.lowCredits fall below 15% of the monthly allowance

6. Live room events

GET /rooms/{id}/events streams a room's events as server-sent events (scope rooms:read):

EventWhen
persona.thinkingAI teammates started on a reply (personas)
message.createdA message from a person, an AI teammate or an API key (message)
run.completedA reply run finished (replies: how many messages it posted)
run.failedA reply run stopped with an error

Each event's data has type, room_id and run_id (null for messages that aren't part of a run).

RUN=$(curl -s https://api.zeriq.app/v1/rooms/$ROOM/messages -H "Authorization: Bearer $ZERIQ_TEAM_API_KEY" \
  -H "Content-Type: application/json" -d '{"content":"Should we ship Friday?"}' | jq -r .run_id)
curl -N "https://api.zeriq.app/v1/rooms/$ROOM/events?run_id=$RUN" -H "Authorization: Bearer $ZERIQ_TEAM_API_KEY"
id: evt_…
event: persona.thinking
data: {"type":"persona.thinking","room_id":"room_…","run_id":"run_…","personas":[{"id":"prs_…","name":"Priya"}]}

id: evt_…
event: message.created
data: {"type":"message.created","room_id":"room_…","run_id":"run_…","message":{…}}

id: evt_…
event: run.completed
data: {"type":"run.completed","room_id":"room_…","run_id":"run_…","replies":1}

How the stream behaves:

  • With run_id: it replays that run from its start, so connecting a moment late misses nothing, and it ends when the run does.
  • Without run_id: it streams everything live.
  • Resuming: send the last id you received as the Last-Event-ID header to resume (browsers' EventSource does this for you).
  • Keep-alive and timeout: a : keep-alive comment comes every 15 seconds, and a stream closes after 10 minutes, so reconnect with Last-Event-ID.

7. AI tools (MCP)

Claude, VS Code, Cursor and other AI tools can use your workspace through its MCP server at https://api.zeriq.app/mcp (Streamable HTTP).

Connecting:

  • Add the URL in the tool, e.g. claude mcp add --transport http zeriq https://api.zeriq.app/mcp.
  • The tool opens a Zeriq page where you sign in, pick what it may do, and connect your current workspace. Actions are unchecked unless you tick them.
  • For tools that can't sign in (CI, scripts), create a personal access token (zqt_pat_…) in Settings → Developers and send it as Authorization: Bearer ….

What it can do: the tool acts as you, so it only sees rooms you're in, limited to what you allowed.

  • Read tools: search_knowledge, list_documents, get_document, list_personas, list_rooms, get_room, get_room_transcript, get_room_run, list_action_items, list_meetings, get_meeting_report, get_credits.
  • Write tools: add_to_knowledge, ask_persona, start_room, post_room_message, end_room, update_action_item. Ones that use AI spend credits as in the web app.
    • Room runs: start_room and post_room_message can run as tasks: the tool returns a task id at once, and the client follows it with tasks/get / tasks/result, even after a restart. Older clients poll get_room_run.
    • Confirmation: end_room, and ask_persona with tools: "allowed" (letting a teammate take actions in your connected tools), ask you to confirm in your AI tool first. Clients that can't show that confirmation can't do these at all.
    • Room runs and tools: room runs started from MCP use read-only tools at most.
  • Resources: team://rooms/{id}/summary, team://rooms/{id}/action-plan, team://documents/{id}, team://action-items/{id}.
  • Prompts: meeting_prep, implement_action_item, standup_digest.

Plans:

  • MCP works on every plan except guest workspaces, within the plan's rate limits.
  • Personal access tokens: 1 per person on Free, 5 on Growth, 20 on Business.
  • Letting teammates take actions in connected tools needs the Business plan.

Admin controls (Settings → Developers → MCP): owners and admins can:

  • turn MCP off for the workspace
  • limit which knowledge sources it returns
  • allow meeting transcripts. This is off by default, because transcripts contain what guests said and AI tools send what they read to their model provider.
  • choose which actions AI tools may let teammates take. The list is empty by default.

Every call is audited.

Coming next

  • Usage: per-key usage reporting.
You're back online