Skip to content

IDs and timestamps

The public API uses one ID space for every resource and one timestamp format for every datetime field. The same siteId you see in a search response is the one you put into a URL or request body, and every datetime field on every endpoint follows the same wire format.

Public IDTypeOriginExample
siteIdintegerAware account / billing67890
personIdintegerMinted on person create24680
checkinIdUUID v4Minted by this API8f5b9a4d-3c2e-4b1f-9d8a-72e6c1f0a4b3
breakIdUUID v4Minted by this API1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d

Numeric IDs are signed 32-bit integers. UUIDs are always lowercase RFC 4122 v4.

Every numeric ID and numeric *Id field on the API (e.g. siteId, personId, cameraId, surveyId, version) is a signed 32-bit integer:

  • Range: Always a whole number. Decimals are rejected.
  • In practice you’ll only ever see positive values for IDs.

This is the same range your language’s native int / int32 will round-trip without loss.

Non-ID numeric fields document their own bounds where they have meaningful business meaning (e.g. temperature is constrained to -200 … 200, geographic coordinates to -90 … 90 and -180 … 180).

Why some IDs are integers and some are UUIDs

Section titled “Why some IDs are integers and some are UUIDs”
  • siteId and personId are stable integer identifiers. personId is assigned when you create a person; siteId comes from your account configuration.
  • checkinId and breakId are minted by the public API. They use UUIDs so they’re globally unique and don’t leak any sequencing about a customer’s check-in volume.
  • Path parameters and request bodies accept the public ID. There is no “alternate” form, and you can’t switch between forms via a header.
  • Every response uses the public ID. You will never see a different identifier for the same resource in a successful response.
  • Search and filter parameters use the public ID (e.g. siteId=67890, personIds=[24680]).

Every datetime field — entry.timestamp, exit.timestamp, breaks[].start.timestamp, the optional timestamp you can send on create, and so on — uses the same wire format:

  • ISO-8601 / RFC 3339, always with an explicit timezone offset.
  • UTC is recommended (suffix Z); fixed offsets like +10:00 are accepted on input.
  • Millisecond precision; the API normalises to millisecond precision on output.
2026-05-12T22:15:33.000Z
2026-05-12T08:15:33.000+10:00

Individual operations don’t repeat this format in their per-field documentation. If a request body or response shows a string field with the OpenAPI format: date-time, it follows the convention above.

The public API does not accept or return numeric epoch timestamps anywhere. If you have an epoch in your system, format it as ISO-8601 in UTC before sending.

Search endpoints use different pagination styles:

ResourceEndpointStyleHow to continue
Check-insPOST /checkins/people/searchCursorPass siteIds to scope (one site, many sites, or omit for all). Response may include cursor; pass it back as pagination.cursor on the next request. Treat the cursor as opaque.
PeoplePOST /profiles/people/searchOffsetResponse echoes total, limit, and offset; increment offset by limit until you have fetched all rows (or stop early).

Person search does not support cursor pagination. Check-in search does not expose offset pagination. Check-in search accepts up to 500 siteIds per request (same cap as other ID filter arrays).

A few payload-protection limits apply to request bodies. They’re documented here once instead of repeated as maxItems / maxLength on every field in the API reference.

LimitCapApplies to
Filter array length500personIds, labelIds, statuses in search filters
Camera-id filter array100entry.cameraIds, exit.cameraIds in search filters
Filters per search request5filters[] array on POST /checkins/people/search
Filter string field256source in search filters
Cursor token512pagination.cursor on check-in search (opaque — round-trip whatever the server returned)
List offset≥ 0pagination.offset on person search
Notes2000notes on a check-in
Page size1–1000pagination.limit on search (this one is shown on the field; recommended default is 50)

If you exceed any of these caps the API responds with 400 Bad Request and a BadRequestError envelope identifying the offending field.