Skip to main content

ID format: int64 wire, int64 runtime

Every surrogate id on the TrakRF v1 API — primary keys (id), foreign-key references (parent_id, location_id, asset_id, tag_id, org_id), and the numeric path / query parameters that consume them — is declared format: int64 with maximum: 9007199254740991 on the OpenAPI spec. That declaration is uniform: response bodies, request bodies, _id query filters, and path parameters all carry the same type and the same ceiling, so there is no wire-vs-runtime width gap to reason about. The one bound worth knowing is 9007199254740991 — JavaScript's Number.MAX_SAFE_INTEGER (2⁵³−1) — the largest integer a browser SPA or any number-typed client can hold without precision loss. This page documents why the ceiling sits where it does and the error envelopes you'll see at the id boundaries.

The int64 contract covers surrogate ids only

Non-id integer fields keep their natural width — for example duration_seconds is int32 and is not a surrogate id. Don't generalize "ids are int64" to "every integer is int64."

The contract at a glance

LayerWidth / boundNote
Wire (spec)int64 (format: int64), maximum: 9007199254740991Generated SDKs surface ids as Long (Java/Kotlin), number (TS), int (Python), etc.
Runtimeint64The service accepts and stores the full declared range; no narrower runtime ceiling.
Storageint64 (Postgres int8)Underlying database column.

The declared maximum is the JS-safe-integer cap (2⁵³−1), not a storage limit — int8 reaches 2⁶³−1. It is declared because the TrakRF SPA, and any client that holds ids in a JavaScript number, loses precision above 2⁵³−1; pinning the ceiling there keeps every minted id exactly representable on every client. ID generation stays within that bound for v1.

Why int64, and why the 2⁵³−1 cap

The TrakRF id namespace is randomly distributed across a wide range, not monotonically assigned from 1. Declaring int64 from v1 launch means a future widening of the id space is a non-event for typed clients — they are already typed wide enough:

  • Java / Kotlin clients surface ids as Long.
  • C# clients surface long.
  • TypeScript clients hold ids in number, exact up to 2⁵³−1 — exactly the declared maximum, so a value the spec admits is always a value the client can represent.

The maximum: 9007199254740991 ceiling is the load-bearing half of that promise on the JS side: it guarantees the spec never admits an id a number-typed client would round. A client that synthesizes ids on its own side (uncommon — ids are server-assigned) should stay within the same bound.

Error envelopes at the id boundaries

Surrogate ids no longer carry a dedicated "too large" rejection. A syntactically valid id that doesn't resolve takes the ordinary lookup path for its surface:

SurfaceExampleResult
Path parameterGET /api/v1/assets/2147483648404 not_found — in range, simply doesn't resolve to a row
Query _id filterGET /api/v1/locations?parent_id=2147483648200 with an empty data[] page — a filter that matches nothing
Request-body FKPOST /api/v1/locations {"parent_id": 2147483648}400 validation_error / code: fk_not_found — the referenced row doesn't exist

The bounds controls are unchanged:

InputResult
Path 0 or -5400 validation_error / code: too_small
Non-numeric (abc) or an int64 overflow (20+ digits)400 validation_error / code: invalid_value
GET /api/v1/assets/2147483648
{
"error": {
"type": "not_found",
"title": "Not found",
"status": 404,
"detail": "asset not found",
"instance": "/api/v1/assets/2147483648",
"request_id": "01JXXXXXXXXXXXXXXXXXXXXXXX"
}
}

An id that overflows the int64 wire entirely (a 20-digit value that can't be parsed as int64) fails to decode and returns 400 validation_error / code: invalid_value, not 404. Zero and negative path ids fail the minimum: 1 bound with code: too_small. Branch on error.type and fields[].code rather than parsing the detail string — see Errors → Path- and query-parameter validation errors.

What this means for clients

  • Typed-client integrators — your generated client already represents ids at int64 width, and the maximum: 9007199254740991 on the spec keeps every admissible id inside the JS-safe range for number-typed targets. Treat the int64 type as the contract; there is no runtime ceiling narrower than the wire to plan around.
  • Pasting / URL construction — when an id reaches your code from a URL or a CSV row, a wrong value resolves to 404 not_found (path), an empty page (query filter), or fk_not_found (request-body FK) rather than a range error. Validate that the value parses as an integer; the envelopes above tell you when it doesn't.
  • No migration planning required for v1 — TrakRF's v1 stability commitment (Versioning) covers the wire type: it won't narrow. The id space stays within 2⁵³−1 for v1.

Cross-references