Filtering
List operations accept filters so you fetch only what you need. This page covers the common date filters, the filters of each list and how filters combine with pagination.
How filters work
- Filters are query parameters, for example
GET /v1/calls?status=ended&agent_id=agent_.... - Every filter narrows the result: several filters together return only objects that match all of them.
- Each filter may be given once. An unknown parameter, a repeated one or an invalid value answers
validation_error, with the parameter named indetails.errors; an invalid phone number (to,phone_number) answersinvalid_phone_number. - Values are matched exactly, with the formats below. There is no free-text search.
- URL-encode values. In particular, the
+of an E.164 number must be sent as%2B(to=%2B12025550100); a bare+in a query string means a space.URLSearchParamsin JavaScript,params=in Pythonrequestsandcurl -G --data-urlencodedo this for you.
Date filters
| Parameter | Meaning |
|---|---|
created_after | Only objects created at or after this time. |
created_before | Only objects created before this time. |
Both take an RFC 3339 timestamp, for example 2026-10-21T00:00:00.000Z; use UTC. Together they select a half-open window, so consecutive windows (created_after=2026-10-20T00:00:00.000Z&created_before=2026-10-21T00:00:00.000Z, then the next day) never overlap or miss an object. For calls, created_at is when the call was accepted.
Resource filters
- GET
/calls:created_after,created_before;agent_id;campaign_id;to(E.164);status(queued,ringing,in_progress,ended,unknown);outcome(completed,no_response,no_answer,busy,failed,unknown; matches ended calls only) - GET
/campaigns:created_after,created_before;status(draft,running,paused,stopped,completed,failed,unknown) - GET
/campaigns/{campaign_id}/recipients:status(pending,in_progress,completed,failed,suppressed,cancelled,unknown) - GET
/contacts:created_after,created_before;phone_number(E.164, matched the same way as the do-not-call check);consent_granted(trueorfalse);do_not_call(trueorfalse) - GET
/dnc-entries:phone_number(E.164): one entry if the number is on the list, none if it is not; formatting is ignored - GET
/webhook-endpoints/{webhook_endpoint_id}/deliveries:status(pending,retrying,succeeded,failed) - GET
/agents, GET/phone-numbers, GET/webhook-endpoints: None (onlylimitandcursor)
Every list also takes limit and cursor (Pagination). All lists only ever return objects of your key's workspace and mode.
Some useful combinations:
- A call you may have placed after a timeout:
GET /v1/calls?to=%2B12025550100&created_after=<just before the first attempt>and match yourmetadata - Yesterday's answered calls of one agent:
GET /v1/calls?agent_id=agent_...&outcome=completed&created_after=...&created_before=... - Whether a number is on the do-not-call list:
GET /v1/dnc-entries?phone_number=%2B12025550100 - Contacts that still need consent:
GET /v1/contacts?consent_granted=false - Recipients a campaign left out:
GET /v1/campaigns/cmp_.../recipients?status=suppressed - Failed webhook deliveries to retry:
GET /v1/webhook-endpoints/we_.../deliveries?status=failed
Example
Ended calls to +12025550100 created since 21 October 2026, 100 per page. The + is sent as %2B and the colons of the timestamp as %3A:
Filters and cursors
A cursor is bound to the filters of the request that produced it. Keep exactly the same filters on every page of one listing; a cursor sent with different filters answers invalid_cursor. To change filters, start again without a cursor.
Filtered lists can return pages with fewer objects than limit while has_more is still true, especially when filtering calls by status. Keep following next_cursor until has_more is false.
Status and outcome are refreshed as calls and campaigns progress, typically within seconds and occasionally a minute or more behind. A call filtered by status=ended today may not have matched a minute ago: for exports, filter on created_before a few minutes in the past, or wait for settled.