Paging and cursors
Every list answers one page at a time. Follow nextCursor until it is empty.
limit, cursor and nextCursor
limitis how many rows you want: any whole number of 1 or more. Leave it out for 100 rows.- An answer that does not hold everything ends with
nextCursor. Send it back ascursor, with the same filters, untilnextCursoris empty. - A page can hold fewer rows than
limit, even none, whilenextCursoris set. A short page is not the end. An emptynextCursoris. - One answer holds at most 10,000 rows. A larger
limitis not an error: you get 10,000 rows and anextCursor. There is no limit on the whole listing. - Keep every filter the same on every page of one listing. A cursor continues the listing it came from.
cursor=""
while :; do
page=$(curl -s "https://api.compudime.com/v1/products?limit=500&cursor=$cursor" \
-H "Authorization: Bearer $PUBLIC_API_KEY")
echo "$page" | jq -c '.products[]'
cursor=$(echo "$page" | jq -r '.nextCursor // empty | @uri')
[ -z "$cursor" ] && break
done
// JavaScript
let cursor = "";
do {
const url = new URL("https://api.compudime.com/v1/products");
url.searchParams.set("limit", "500");
if (cursor) url.searchParams.set("cursor", cursor);
const response = await fetch(url, { headers: { Authorization: "Bearer " + process.env.PUBLIC_API_KEY } });
const page = await response.json();
if (!response.ok) throw new Error(page.code + " (" + page.requestId + "): " + page.detail);
for (const product of page.products) handle(product);
cursor = page.nextCursor || "";
} while (cursor);
Long answers
Products and sales movement come from CompuDime's own copy of the store's data. The other lists are read live from the store's POS, a few hundred rows at a time. A larger limit is read in several reads, one after another, and answered at once.
- There is no time limit. An answer keeps reading until it holds
limitrows or the listing ends. - While it reads, the answer is already open. The body starts with spaces, sent every few seconds so no proxy drops the connection. Any JSON parser skips them.
- The cost is known only at the end. So
X-Credits-ChargedandX-Credits-Remainingcome as HTTP trailers, which HTTP/2 clients receive and HTTP/1.1 clients do not. Thebillingblock in the body always says what the call cost. - When the API or the store is busy with other long answers, an answer can stop after its first read, with a
nextCursor. - If the store stops answering partway, you get the rows read so far and a
nextCursorthat resumes right there. Only a store that does not answer the first read gets504 store_timeout, which is never charged. - If you hang up before the answer is written, the call is not charged.
Date ranges
Date ranges (from and to, as YYYY-MM-DD) have no maximum span. The daily sales and sales movement lists answer from the days CompuDime holds; coveredFrom and coveredTo on the answer say which. The ticket list reads a long range from the store a month at a time, so a page may be short or empty while nextCursor is set.
Sync only what changed
Lists that take modifiedSince return only the rows changed at or after that time, plus every row with no change time (it cannot be shown unchanged, so it is always sent). Rows are keyed, so reading one again is harmless.
- For the next sync, pass the largest change time you received, minus one hour. Do not use your own clock: the change time runs on the store's clock, and the hour covers the night the clocks go back.
- Keep
modifiedSincethe same on every page of one listing, and follownextCursoras usual. - A store whose POS keeps no change time for a list answers
422 modified_since_unsupported. List without it there.
Paged endpoints
- GET
/v1/accounting/journal-entriesList mapped journal entries by store-day live - GET
/v1/accounting/sales-summariesList register-log sales summaries by store-day live - GET
/v1/brandsList the store's brands live - GET
/v1/categoriesList the store's departments, categories and sub-categories live - GET
/v1/customersList the store's customers live - GET
/v1/inventory/onhandList on-hand quantities live - GET
/v1/invoicesList the store's POS invoices live - GET
/v1/productsList catalog products - GET
/v1/promotionsList the store's promotions live - GET
/v1/purchase-ordersList the store's vendor purchase orders live - GET
/v1/receivingList the store's receiving documents live - GET
/v1/sales/movementList sales movement - GET
/v1/tagsList the store's product tags live - GET
/v1/ticketsList the store's register tickets live