Create an export job
Queues an asynchronous export and returns the job right away with status: pending and HTTP
202. Poll GET /api/exports/{id} until status is completed, then stream the file from
GET /api/exports/{id}/download. The file can be downloaded for 72 hours after completion.
Each type accepts only some filters. A filter the type cannot apply is rejected with 400, never
silently ignored:
calls:date_from,date_to(onstarted_at),campaign_id,agent_id,status,outcomecontacts:date_from,date_to,campaign_id,agent_id(through the contact’s campaign),statusconversations:date_from,date_to,agent_id,statusanalytics:date_from,date_to,campaign_id,agent_id,statusagent_actions:date_from,date_to,agent_id,status(the action outcome:success,error,denied,timeoutorindeterminate)audit_log:date_from,date_to
A file holds at most 100,000 rows, newest first. A larger result completes anyway, with error
set to Results truncated to 100000 rows. Phone numbers and PII in call summaries are masked. In
CSV files, cells starting with =, +, -, @, tab or CR are prefixed with ' so spreadsheets
do not run them as formulas.
Side effects. Inserts a job and enqueues it for a background worker. Up to 3 jobs per
workspace can be pending or processing at once. When the job finishes, the requesting user
gets an in-app notification (export ready, or export failed). Written to the audit log as
export.create.
Idempotency. Not idempotent. Retrying after a timeout creates a second job, which also takes one
of the 3 in-progress slots. Before retrying, check GET /api/exports for a job created a moment ago
with the same type.
Webhook events. Emits audit.log_recorded to webhooks subscribed to it. No event is sent when
the export completes. See Webhooks.
Access
- Required scope:
write.audit_logandagent_actionsneedfull, and human users need the owner or admin role for those two types. - Rate limit: General API (120–600 requests/min per workspace, by plan) plus the configuration-mutations limit — 10 requests/min per workspace, shared with other configuration changes. See Rate limits.
- Plan: Every type except
analyticsis available on every plan and also without an active subscription, so a workspace can always take its data out.type: analyticsrequires an active subscription (active,trialingorpast_due) and is otherwise refused with403 BILLING_ERROR(metadata.kind: subscription_required).
Authentication
Workspace API key: jl_ followed by 64 lowercase hex characters, created by the workspace owner in the
dashboard (Settings → API Keys) and sent as Authorization: Bearer jl_.... The plaintext is shown once,
at creation; Jelliu stores only a SHA-256 hash. A workspace can hold up to 25 active keys.
Operations restricted to admins or owners reject keys without the full scope with 403, and say so in
their description. No key, whatever its scope, can mint or revoke API keys or rotate a webhook secret —
that requires a signed-in owner session. A revoked key stops authenticating within about 10 seconds.
See Authentication.
Request
Unknown top-level keys and unknown filter keys are ignored.
The data set to export. calls: one row per call. contacts: campaign contacts.
conversations: WhatsApp and webchat threads. analytics: daily aggregates per campaign.
agent_actions: one row per tool an agent invoked, including the agent’s own in-call
hand-offs transfer_to_number and transfer_to_agent since 2026-09-15 (owner/admin
only). audit_log: the audit trail, including changes (owner/admin only).
File format. csv with a header row, json as a single pretty-printed array, or jsonl with one JSON object per line (best for very large files and SIEM ingestion).
Optional filters, combined with AND. Only the filters listed for the chosen type are allowed; empty strings count as not sent.
Response
The job was queued. It starts pending.
An asynchronous export job, as stored (snake_case). Created by POST /api/exports.

