Pagination and search
Paging through calls, filtering by date, and full-text search.
Pagination
List endpoints take page (1-based, default 1) and pageSize (default 25):
curl "$BASE/v1/projects/$PROJECT_ID/calls?page=2&pageSize=50" \
-H "X-API-Key: $AFTERTALK_KEY"Every paged response has the same envelope:
{
"data": [{ "id": "..." }],
"total": 137,
"page": 2,
"pageSize": 50,
"totalPages": 3
}Loop until page reaches totalPages:
async function* allCalls(projectId) {
let page = 1;
let totalPages = 1;
do {
const url = `${BASE}/v1/projects/${projectId}/calls?page=${page}&pageSize=100`;
const result = await fetch(url, { headers }).then((r) => r.json());
totalPages = result.totalPages;
yield* result.data;
page += 1;
} while (page <= totalPages);
}Filtering by date
from and to accept ISO-8601 timestamps and filter on creation time. Omit either side for an
open-ended range; omit both and no date filter is applied.
curl "$BASE/v1/projects/$PROJECT_ID/calls?from=2026-07-01T00:00:00Z&to=2026-08-01T00:00:00Z" \
-H "X-API-Key: $AFTERTALK_KEY"For incremental syncs, keep the timestamp of your last run and pass it as from.
Full-text search
GET /calls/search searches transcript content, ranked by relevance, with matching fragments
highlighted:
curl -G "$BASE/v1/projects/$PROJECT_ID/calls/search" \
-H "X-API-Key: $AFTERTALK_KEY" \
--data-urlencode 'q=refund policy'Results are the paged envelope above, and each item carries a highlighted snippet with matches
wrapped in <mark> tags — render it as HTML or strip the tags.
Query syntax
| Syntax | Example | Matches |
|---|---|---|
| Words | refund policy | calls containing both words |
| Quoted phrase | "payment failed" | that exact phrase |
OR | refund OR chargeback | either word |
- | refund -chargeback | "refund" but not "chargeback" |
Search accepts the same page, pageSize, from, and to parameters as the list endpoint.
Matching is literal, without language-specific stemming — "refund" won't match "refunds". Search for the shorter stem,
or use OR for the variants that matter.