Skip to content
DocsStart free

Call CDR & Export

Every call writes a CDR (call detail record): one row per call with its direction, numbers, timestamps, duration, and disposition. CDRs are stored in two tiers: a queryable recent window for dashboards and exports, and an unbounded archive for long-term retention.

CREATE TABLE call_cdr (
call_id TEXT PRIMARY KEY,
account_id TEXT,
direction TEXT, -- inbound | outbound | internal
from_num TEXT,
to_num TEXT,
start_ts INTEGER, -- epoch ms (call start = the routing decision)
answer_ts INTEGER, -- epoch ms (when answered)
end_ts INTEGER, -- epoch ms (call ended)
duration_sec INTEGER, -- wall-clock seconds
billsec INTEGER, -- billable (answered) seconds
answered INTEGER,
disposition TEXT, -- answered | no_answer | …
hangup_cause TEXT,
queue_id TEXT, -- if it went through a queue
agent_id TEXT, -- the connected agent
cost_micros INTEGER -- billing (micro-units)
);

A start row is written when the call is routed and upserted to completion when the call ends, so a row exists even if the call never completes cleanly.

  • Recent window (queryable): the call_cdr table keeps a rolling 30-day window for fast queries and export.
  • Archive (unbounded): every completed call is also written to a per-account archive in the object-storage data lake (Apache Iceberg), the canonical, long-term record for analytics and compliance.

GET /v1/calls returns CDRs for your account over a time range, as JSON or CSV (the cdr scope):

ParamPurpose
since / untilEpoch-ms range (defaults: all / now).
limitMax rows (default 1000, capped 10000).
cursorKeyset pagination: pass the previous response’s next_cursor for the next page.
formatcsv for a download, else JSON.
Terminal window
curl 'https://api.sip.io/v1/calls?since=1719600000000&format=csv' \
-H 'x-api-key: sk_…' -o cdr.csv

JSON returns { ok, count, rows }; CSV is RFC-4180 quoted for spreadsheets and BI tools.

cost_micros is computed at call end by a rate engine: an account’s rate_plan holds rate rows keyed by destination prefix (longest match wins), each with a per_min_micros, a per-call connection_fee_micros, and a billing increment_sec (e.g. 60/60 or 1/1). Answered seconds are rounded up to the increment and priced; unanswered calls cost 0. It’s a usage-rating layer, not a full billing system.

The queue_id and agent_id are stamped onto the record for queue calls, and the 30-day window is pruned daily.