Latency spikes are appearing when fetching conversation details via /api/v2/analytics/conversations/details/query. The notification stream is pushing a batch of IDs and the backfill job needs to grab the full details, but the current pagination approach is choking on larger date ranges.
We’ve got a Tokio task spooling requests using reqwest, and as the page parameter climbs, the response time degrades significantly. Looks like the API is doing a deep scan on the backend for high page numbers.
let res = client
.get(url.join("/api/v2/analytics/conversations/details/query")?)
.query(&[
("page", current_page.to_string()),
("pageSize", "50"),
("dateFrom", start_iso),
("dateTo", end_iso),
])
.send()
.await?;
The response payload includes a nextPageUri field occasionally, but it’s inconsistent. Sometimes it’s just null even when more data exists. The documentation mentions cursor-based pagination for analytics endpoints, yet no clear examples exist for passing a cursor to this specific details query endpoint.
A manual attempt to send a cursor query param based on a value from the nextPageUri of a previous response results in a 400 Bad Request.
{
"errors": [
{
"code": "invalid.request",
"message": "Query parameter 'cursor' is not supported for this resource"
}
]
}
This suggests cursor isn’t supported here, but the nextPageUri behavior is confusing. If the client sticks to page-based logic, how should nextPageUri be handled when it appears? Ignoring it and just incrementing the page counter seems wrong if the API is hinting at a different mechanism.
The pageSize max seems to be 100, and anything higher gets capped silently by the API. Rate limits are being hit pretty fast when iterating through pages sequentially in a single async task. Parallelizing the page fetches seems necessary, but that feels risky with the pagination order.
Current workaround is splitting the date range into smaller chunks, but that adds complexity to the serde deserialization logic for merging results.
The nextPageUri sometimes includes a fragment that looks like a cursor hash. Appending that directly to the base URL fails with a 403.