Skip to main content

Lists and paging

Reelwire has two kinds of list, and they behave differently on purpose.

Logs never stop growing: /v1/jobs, /v1/posts, /v1/render-jobs, /v1/ingest-events, /v1/approvals and /v1/deliveries. These are paged, searched and sorted by the server, over every row the workspace has. The syndication lists are paged by the server too, with a few differences of their own: see Other paged lists.

Configuration does not grow without bound: brands, channels, streams, post lists, the media library. These come back whole, and the client searches and sorts them itself. A library is hundreds of files, not millions, and paging it would buy nothing and cost a round trip.

The log parameters​

ParameterWhat it does
pageWhich page, from 1. Anything else is treated as 1.
perPageHow many to a page. 1 to 200; outside that, the route's own default.
limitThe older name for perPage, still honoured.
qWhat was typed, matched case-insensitively across the columns the row prints. At most 200 characters.
sortA column name the route offers. Anything else falls back to the route's default order.
ascending"true" or "false". Absent is the route's own default: newest first, except on /v1/approvals, which is a queue and is read oldest first.
since, untilThe window, as absolute instants.
curl "http://localhost:4000/v1/render-jobs?page=2&perPage=25&q=bund&sort=state&ascending=true" \
-H "Authorization: Bearer rw_your_key_here"

The columns each log can be sorted by:

Routesort
/v1/jobscreatedAt. Anything else is the default, when the job last changed.
/v1/postscreatedAt, state, platform, channelName
/v1/render-jobssubmittedAt, state, templateId
/v1/ingest-eventsreceivedAt, status, origin
/v1/approvalsrequestedAt, channelName
/v1/deliveriescreatedAt, updatedAt

Every log answers with the page and the counts around it:

{
"jobs": [],
"total": 7,
"all": 7,
"page": 1,
"perPage": 1,
"facets": { "state": ["COMPLETED"] }
}
FieldWhat it is
totalRows matching the filters. Divide by perPage for the last page.
allRows in the window asked for, ignoring the other filters and the search, so you can say "7 of 412".
page, perPageWhat you actually got, after clamping.
facetsThe values each filter can usefully take.

The default perPage differs per route, because the screens differ: 25 for /v1/jobs, 40 for /v1/posts and /v1/deliveries, 30 for /v1/render-jobs, 50 for /v1/ingest-events, 200 for /v1/approvals. Send perPage rather than relying on any of them.

/v1/jobs answers two counts more: stages, how many posts each stage holds, and unstaged, how many the search and filters leave before a stage is chosen.

Facets are read from the rows​

facets is computed from what the workspace actually holds, not from a fixed list. A filter value that appears there is one that can return something, and a state nothing is in does not appear. Some lists also carry labels, which maps ids in the facets to names, so a filter dropdown does not need a second request to say "Channel 4 de" instead of a ULID. The exceptions are the three fixed choices on /v1/jobs, stage, approval and archive, which list everything the filter takes.

An unparseable filter widens rather than refuses​

since and until that cannot be read are ignored, not rejected. This is a filter on a list, and the honest failure is to show more, not to show an error. The same goes for a sort column a route does not offer, and for a filter repeated in the query string: a key given twice arrives as an array, a filter is only ever one value, so it is treated as no filter at all.

A search longer than 200 characters is the one exception, and is a 400.

Windows mean different things​

On /v1/jobs, the window is when something happened to the job: it arrived, it rendered, or one of its posts changed. A job that arrived yesterday and published ten minutes ago is inside the last hour, because the rows sort by Updated and anything else would be a lie.

On /v1/posts, /v1/render-jobs and /v1/deliveries it is when the row was created, and on /v1/ingest-events when the event arrived. /v1/approvals takes no window: it is the queue of what waits now.

/v1/calendar is not a log and takes from and to instead, both required, both absolute instants, with a window of at most 367 days.

Paging safely while things are arriving​

A log is ordered newest first, so a row arriving between two requests shifts everything down a place and page 2 can repeat a row page 1 already showed. Two ways round it:

  • Pin the window. Pass until set to the moment you started, and page through a set that cannot grow underneath you.
  • Page from the oldest end, with ascending=true, where you are reading everything rather than the most recent.

Every row carries an id, so deduplicating on the way through works whatever you do.

Other paged lists​

/v1/syndication/partners and /v1/syndication/deliveries take q, page, perPage and ascending, and no sort and no window: they are always in the order the rows were made, newest first. perPage is 50 by default and at most 500 for the participants, 200 for the deliveries, and a larger number is cut to that most rather than ignored. The deliveries answer total, all (every line the workspace has) and facets; the participants answer total and room, the allowance they count against, and no facets. See Syndication.

The lists that are not paged​

/v1/brands, /v1/channels, /v1/streams, /v1/queues, /v1/media, /v1/media/renders, /v1/feeds, /v1/templates and /v1/syndication/groups return everything. page and perPage on them do nothing.

A few are in between: lists that take limit alone, with no page.

Routelimit
/v1/direct-export/videosDefaults to 24, at most 100.
/v1/direct-export/queueNot taken: every video still rendering or waiting, those that failed in the last two hours, and the 100 newest kept ones.

/v1/pipeline is a live view rather than a log: it takes since and until, and shows at most 12 jobs in each lane beside counts that cover them all. See Posts and jobs.