List Campaign Dispatches
V1 Developer API
List Campaign Dispatches
Read one outbound campaign’s call detail with cursor pagination and incremental pulls
GET
List Campaign Dispatches
Read every dispatch result for a single outbound campaign — the same data the dashboard’s CSV export produces, returned as JSON. Intended for scheduled jobs that pull the day’s results after dialing finishes.
This endpoint is read-only. It performs no writes.
The content depends on the evaluation criteria configured for the project:
Dynamic fields whose keys come from each project’s variable settings — whatever the call extracted is what appears here. Adding a variable to a project is reflected automatically, with no API change.
When a record has no extraction result at all,
The cursor is an opaque string; pass it back verbatim. Its internal format is not part of the public contract and may change without breaking compatibility.
Prefer carrying forward the largest
Request
Headers
string
required
Bearer token authentication with your Developer Key (
dk_...).Query parameters
string
Filter by dispatch status, comma-separated (e.g.
completed,failed). Omit for no filtering. An unrecognized value returns 400 rather than silently matching nothing.string
ISO 8601 timestamp with offset. Returns only records updated strictly after this instant — use it for incremental pulls.
string
Pagination cursor. Echo back the previous page’s
next_cursor verbatim; do not parse or construct its contents.integer
Maximum records per page. Defaults to
1000, capped at 5000.Example
Response
Fields
dispatch_status values
evaluation
The content depends on the evaluation criteria configured for the project:
- Pass/fail:
"Pass","Fail", or"Unknown"when undecidable - Numeric: the score as a string, e.g.
"4.5" - Enum: the project’s own enum value as a string
null when the call has not been evaluated or the project defines no criteria.
variables
Dynamic fields whose keys come from each project’s variable settings — whatever the call extracted is what appears here. Adding a variable to a project is reflected automatically, with no API change.
When a record has no extraction result at all, variables falls back to the seed fields the contact was imported with. That covers two cases, not one: contacts never dialed, and contacts that were dialed but produced no variables (no answer, immediate hangup).
This fallback is a deliberate difference from the CSV export, which builds its header from extracted variables plus the seed fields of never-dialed contacts only — so a dialed-but-no-extraction contact shows blank cells there while this API returns its seed fields.The two cases are distinguishable only at the extremes:
session_id: null means never dialed, so those variables are always seed fields. For a record with a session_id, the API does not flag whether the values came from the call or from the import — treat them as “the best values we have for this contact”.Pagination
Page with the cursor untilhas_more is false:
A page may return fewer records than
limit: when variables payloads are large, the response is cut short to bound its size. This is reported the same way, with has_more: true and a next_cursor to continue from — so decide whether to keep paging from has_more, never from whether the page is full.While a campaign is still dialing, a record can come back on more than one page. Pages are ordered by
updated_at, which the dialer rewrites as a call progresses, so a record you already read can be pushed past your cursor and returned again later. Nothing is ever skipped — only repeated. Deduplicate by dispatch_id when paging through a running campaign; a pull that starts after dialing finishes is unaffected.Daily incremental pull
The recommended scheduled usage: run once after dialing finishes, passing the last successful pull’s timestamp asupdated_after to fetch only what changed.
+ must be encoded as %2B in a query string; otherwise it is parsed as a space and the offset is misread.updated_at you saw on the previous run over using local midnight as the boundary — post-call evaluation writes can land after the day rolls over.
Subtract a small safety margin from that watermark — a few seconds is plenty — and deduplicate by dispatch_id. updated_after is a strict > comparison, so a record written in the very millisecond your previous run read up to would otherwise never be picked up by any later run.
Errors
Notes
- Scope: a Developer Key can only read campaigns under projects it has access to. Cross-project access returns
403. - Differences from the CSV export: same source and same fields, but the API returns raw values rather than display formatting —
dispatch_statusiscompleted, notCompleted;duration_secondsis96, not1m 36s. Timestamps are always ISO 8601 in UTC. - Network allowlisting: allowlist the hostname
api.pathors.com. The domain sits behind Cloudflare, so the resolved addresses are anycast and rotate — do not pin specific IPs. If your policy requires IP-based rules, use Cloudflare’s published IP ranges.
