Product AI notes Pricing For teams Developers & API Security Standards & compliance
Start free Sign in
Developers · API

Put the meeting inside your own system.

A REST API for creating meetings, admitting participants and pulling back the transcript, the summary, the decisions and the action items — so the meeting ends where your work already lives, not in a tab someone has to remember to check.

Base URL
/api/v1
meet.codexal.co, HTTPS only.
Format
REST · JSON
Predictable resources, standard verbs.
Authentication
Bearer API key
Scoped per environment, rotatable.
Webhooks
HMAC-SHA256
Signed and timestamped on every delivery.
Rate limit
600 req / min
Per key. Raised on request.
Getting a key
Self-service
A developer account, then an app.
Quickstart

One call creates a meeting.

Post a title, a start time and a host. You get back a meeting id, a join link you can put straight into your own interface, and a code for anyone joining by phone or from the home page.

Invitations, waiting rooms and AI notes are fields on the same request. There is nothing to install on anyone's machine — the join link opens in a browser, which is the whole reason this API is short.

  • Idempotency keys, so a retry never creates a second meeting.
  • UTC timestamps in, UTC timestamps out. No local-time surprises.
  • Errors name the field that was wrong, with a request id to quote at us.
curl -X POST https://meet.codexal.co/api/v1/meetings \
  -H "Authorization: Bearer $CODEXAL_API_KEY" \
  -H "Idempotency-Key: crm-deal-4821-kickoff" \
  -H "Content-Type: application/json" \
  -d '{
        "title": "Quarterly review - Sales",
        "starts_at": "2026-10-02T10:00:00Z",
        "duration_minutes": 60,
        "host_email": "lina@acme.com",
        "waiting_room": true,
        "ai_notes": { "enabled": true, "language": "auto" }
      }'
{
  "id": "mtg_8f2c41a9",
  "code": "K7M-2QX-9PD",
  "join_url": "https://meet.codexal.co/lobby.php?id=mtg_8f2c41a9",
  "status": "scheduled",
  "starts_at": "2026-10-02T10:00:00Z",
  "duration_minutes": 60,
  "waiting_room": true,
  "host": { "name": "Lina Haddad", "email": "lina@acme.com" },
  "ai_notes": { "enabled": true, "language": "auto" },
  "created_at": "2026-09-13T08:41:22Z"
}
Authentication

One key, scoped to what it is for.

Keys are issued per organisation and per environment. Sandbox keys are obviously sandbox keys, and a key that only needs to read summaries cannot create meetings.

Bearer keys

Send the key in an Authorization header. Never in a query string — a URL ends up in browser history, proxy logs and screenshots, and a key in any of those is a key you have to rotate.

Scopes

meetings:read, meetings:write, participants:write, records:read, users:write. Ask for the ones your integration actually uses; we issue exactly those.

Rotation & allowlists

Two keys can be live at once so a rotation is a deploy, not an outage. Enterprise keys can be pinned to your egress IP ranges, which makes a leaked key useless off your network.

GET /api/v1/meetings?status=ended&limit=20 HTTP/1.1
Host: meet.codexal.co
Authorization: Bearer cxl_live_9f4a21c8e7b3d05a
Accept: application/json

# Sandbox keys carry their own prefix and never touch live data:
# Authorization: Bearer cxl_test_3b81d0fa54c9e762

Keys are self-service, and a developer account is separate from a meeting account. Even if you already sign in to Codexal Meet to hold meetings, the thing that signs API calls is an organisation with its own wallet, its own allowed domains and its own revocation switch — so it gets its own account. Create one, make an app, and the public and secret keys are on screen in about a minute, with sandbox credit already in the wallet.

Reference

The whole surface, on one screen.

Five groups. Everything is a normal resource with normal verbs, paginated with limit and cursor, and everything returns JSON.

Meetings

scope: meetings:read · meetings:write
POST/v1/meetings
Create a meeting. Returns the id, the join link and the join code.
GET/v1/meetings
List meetings, filtered by status, host or date range.
GET/v1/meetings/{id}
One meeting: its state, host, settings and attendance so far.
PATCH/v1/meetings/{id}
Move the time, rename it, change the agenda or turn AI notes on.
DELETE/v1/meetings/{id}
Cancel a meeting. Invitees are notified; the record is kept.
POST/v1/meetings/{id}/invitations
Invite people by email, in Arabic or English, with the calendar file attached.

Participants

scope: participants:write
GET/v1/meetings/{id}/participants
Who is in the room, who is waiting, and who has left.
POST/v1/meetings/{id}/participants/{participant_id}/admit
Admit someone from the waiting room — the same decision the host makes in the UI.
POST/v1/meetings/{id}/participants/{participant_id}/deny
Refuse entry, with an optional reason shown to the visitor.
POST/v1/meetings/{id}/tokens
Mint a single-use join token so your own app can sign a person straight in.

Records

scope: records:read
GET/v1/meetings/{id}/transcript
The transcript, with speaker labels and timestamps. Plain text or JSON segments.
GET/v1/meetings/{id}/summary
The AI recap: summary, decisions, action items and owners, in the meeting language.
GET/v1/meetings/{id}/attendance
Join and leave times per participant, for a register or a timesheet.
DELETE/v1/meetings/{id}/records
Delete the transcript and summary now, ahead of the retention window.

Users

scope: users:write
GET/v1/users
Everyone in your organisation, with their plan and last activity.
POST/v1/users
Provision an account from your own joiner process.
DELETE/v1/users/{id}
Deprovision on a leaver, and reassign their meetings in the same call.

Webhooks

scope: meetings:read
POST/v1/webhooks
Register an endpoint and the events you want. Returns the signing secret once.
GET/v1/webhooks
List your endpoints, their events and their recent delivery health.
DELETE/v1/webhooks/{id}
Stop deliveries to an endpoint.
POST/v1/webhooks/{id}/test
Send a sample event, so you can build against it before a real meeting runs.
Webhooks

You do not have to poll for the recap.

A meeting ends, the notes are written, and your endpoint hears about it. Deliveries are signed, timestamped and retried with a backoff for 24 hours.

meeting.started

The first participant was admitted and the room is live.

meeting.ended

The room closed, with the final duration and attendance.

participant.waiting

Someone is in the waiting room — admit or deny them from your own screen.

participant.joined

Someone was admitted, with their name and join time.

transcript.ready

The transcript has been written and can be fetched.

summary.ready

The AI recap is done: summary, decisions and action items.

POST /hooks/codexal HTTP/1.1
Codexal-Signature: t=1790592259,v1=8d61a0...c47f

{
  "id": "evt_5c1d90ab",
  "type": "summary.ready",
  "created_at": "2026-10-02T11:04:19Z",
  "data": {
    "meeting_id": "mtg_8f2c41a9",
    "language": "ar",
    "decisions": 3,
    "action_items": 5,
    "summary_url": "https://meet.codexal.co/api/v1/meetings/mtg_8f2c41a9/summary"
  }
}
$payload = file_get_contents("php://input");
$header  = $_SERVER["HTTP_CODEXAL_SIGNATURE"] ?? "";
parse_str(strtr($header, ",", "&"), $sig);

$expected = hash_hmac("sha256", $sig["t"] . "." . $payload, $secret);

// Constant-time, or the comparison itself leaks the signature.
if (!hash_equals($expected, $sig["v1"] ?? "")) {
    http_response_code(400);
    exit;
}

// A valid signature on an old event is still a replay.
if (abs(time() - (int) $sig["t"]) > 300) {
    http_response_code(400);
    exit;
}

$event = json_decode($payload, true);
What teams build with it

The meeting belongs in the system you already use.

Every one of these is the same three moves: create a meeting from a record, put the join link in front of the right person, and write the recap back where it will actually be read.

LMS & student portals

A class on the timetable becomes a room with a waiting room and a lesson agenda. The recap and the attendance register go back to the course record, and captions are on for every student.

Codexal Meet for education →

CRM & sales tools

Create the call from the deal, and post the summary, the decisions and the next steps onto the deal timeline before the rep has opened their laptop again.

Clinic & booking systems

An appointment produces a single-use join link for the patient and a waiting room for the clinician. No patient identifiers in the URL, and records deleted on your schedule.

Safeguards for telehealth →

Helpdesk & field support

Escalate a ticket into a video call in one click, then attach the transcript to the ticket so the next agent reads what happened instead of asking again.

Internal portals

Provision and deprovision accounts from your own joiner-mover-leaver process, mint join tokens for staff already signed in, and keep one meeting list in your intranet.

SSO & admin controls →

Automation platforms

Webhooks are plain signed JSON, so Zapier, Make, n8n or a twelve-line script can route a recap into Slack, Notion, a spreadsheet or a database with nothing else in between.

Limits & errors

Predictable when things go wrong.

Every error carries a machine-readable type, the field that caused it, and a request id. Quote the id at us and we can find the exact call in the logs.

400 invalid_request

A field is missing or the wrong shape. The response names it.

401 unauthorized

The key is missing, revoked, or a sandbox key sent at live data.

403 forbidden_scope

A valid key without the scope for this call.

404 not_found

No such resource, or it belongs to another organisation.

409 conflict

An idempotency key was reused with a different body.

429 rate_limited

Over the limit. Retry-After says how long to wait.

5xx server_error

Ours. Safe to retry with the same idempotency key.

HTTP/1.1 422 Unprocessable Entity
X-Request-Id: req_0a93f1c7
X-RateLimit-Remaining: 587

{
  "error": {
    "type": "invalid_request",
    "message": "starts_at must be an ISO 8601 timestamp in UTC.",
    "param": "starts_at",
    "request_id": "req_0a93f1c7"
  }
}

Versioning

The version is in the path. Inside v1 we only add — new fields and new endpoints, never a changed meaning for one you already read. If a breaking change ever becomes unavoidable it ships as v2, with six months of overlap and an email to every key holder, not a changelog entry you were supposed to notice.

There is no endpoint for audio or video, and there never will be. Media is encrypted between browsers with keys our servers do not hold, so there is nothing for an API to hand you — no live stream, no server-side recording, no back door with a scope name on it. Transcripts and summaries exist because they are produced with the meeting's consent and stored under your retention settings. That boundary is described in full on the security architecture page.

Media access
None
End-to-end between participants.
Server-side recording
None
A recording exists only if a participant makes one.
Data residency
Middle East
Dedicated regions for Enterprise.
Record retention
14 days
Default; set per organisation, or delete on demand.
Questions

From the people who would integrate it.

How do we get a key?
From the developer console, in about a minute. You create a developer account — separate from any meeting account you already have — add an app, and the public and secret keys are on screen. Sandbox credit is in the wallet from the moment the account exists, so the first request in the guide actually runs.
Why a second account? We already have one.
Because the two answer different questions. A meeting account is a person who attends calls; a developer account is an organisation that owns keys, a token balance and a list of domains allowed to embed the room. Keeping them apart means a key can be revoked without locking anybody out of their own meetings, and a personal account can be deleted without quietly killing a production integration.
Is there a sandbox?
Yes, and it is a separate environment rather than a flag on your live account. Sandbox keys carry a cxl_test_ prefix, meetings are capped at fifteen minutes, nothing is billed, and no sandbox call can reach live data — so you can leave a broken integration running over a weekend without consequences.
Are there official SDKs?
Not yet. The API is plain HTTP with JSON, which is a few lines in any language, and we would rather ship a stable surface than four half-maintained clients. If a thin wrapper for your stack would genuinely save you time, ask — we have written them for customers before.
Can the API read our meetings?
It can read the transcript and the summary of a meeting in your own organisation, with a key you issued and a scope you chose. It cannot reach audio or video at all, because that media never exists in readable form on our servers. Deleting the records through the API deletes them for us too.
What about SSO and user provisioning?
Enterprise accounts sign in through your identity provider today, and the /v1/users endpoints cover provisioning from your own joiner-leaver process. SCIM is on the roadmap rather than shipped, and we will say so plainly until it is. See Enterprise for what is live now.
What does it cost?
API access is included with the Business and Enterprise plans at no extra charge, and the calls your integration makes are not metered separately — you are billed for the meetings, as usual. Rate limits above 600 requests a minute are agreed with us rather than bought.
Where is the data when we call the API?
On the same servers in the region as everything else: accounts, transcripts and summaries stay in the Middle East, and Enterprise customers can have a dedicated instance in a named region. The GDPR page lists the sub-processors and the transfer basis, and the DPA is signed on any plan.

Your keys are a minute away.

Create a developer account, add an app, and the console gives you the keys, the step-by-step guide, the embed generator and a running total of what every meeting, recap and question costs. Sandbox credit is included.