RTFC API

Pagination and list shapes

Every list endpoint answers the same way:

json
{"items": [...], "total": 458, "limit": 50, "offset": 0}

total is the number of rows matching your query, not the number returned - so you can size a pager without a second count request.

bash
curl -s "$RTFC/debates?limit=25&offset=50" -H "X-Auth-Token: $TOKEN"

limit is capped (typically 200–500 depending on the endpoint). Asking for more gives you the maximum rather than an error - a hard failure would be a hostile way to say "too big".

Iterate until you have total:

python
items, offset = [], 0
while True:
    page = get(f"/v1/debates?limit=100&offset={offset}").json()
    items += page["items"]
    if len(items) >= page["total"] or not page["items"]:
        break
    offset += 100

Every list endpoint answers with this same envelope - there is no endpoint that returns a bare JSON array instead.

GET /v1/debates accepts optional since, an ISO 8601 datetime with a timezone (for example 2026-10-11T12:00:00Z). It includes analyses whose created_at is at or after that instant, for both total and the returned page. It combines with q, origin, status, author, candidate_id, topic_qcode and sorting, within the existing owner/access-grant checks. Invalid datetimes or missing timezones return 422. Omit since to search all creation dates.

GET /v1/debates/{id}/transcript and GET /v1/session/transcript-db sort segments by media_offset_ms, then ts, then segment ID. Segments without a media offset come last and follow timestamp order. order=asc (default) follows playback order; order=desc reverses the ordering within timed and untimed segments. Sorting happens before limit / offset pagination. ts is a wall-clock timestamp, not a playback position. The text of the X post that carries a video (source_kind: "post", named after the account in speaker_name, no media_offset_ms) always comes first with order=asc and last with order=desc; every other segment has source_kind: null.