Conventions
The response envelope and result-class conventions.
Every Tekmerion API response is a JSON object with one fixed top-level envelope. The envelope is the same shape for success and failure; the value of ok and the result class tell you how to read it. Request bodies follow a matching posture: a top-level JSON object with no wrapper.
Response envelope
All responses — success and error alike — MUST be a JSON object with exactly these four top-level keys:
{
"ok": true,
"data": {},
"error": null,
"meta": {
"result_type": "singleton"
}
}Envelope rules:
okMUST betrueon success andfalseon failure.- A response MUST NOT carry both a non-
nulldataand a non-nullerror. The two are mutually exclusive. metaMUST be present, andmeta.result_typeMUST always be set.- On success,
errorMUST benull. On failure,dataMUST benull.
Content-Type: application/json is set whenever a body is present.
Result classes
meta.result_type declares the shape of data. There are four classes:
result_type | ok | data | When used |
|---|---|---|---|
singleton | true | one JSON object | A read or command that returns exactly one resource. |
collection | true | a JSON array | A list read. data is always an array, even when empty. Carries meta.pagination when the surface is paginated. |
ack | true | null | A command that succeeds but returns no resource body. |
error | false | null | Any failure. Carries a populated error object. |
A surface MUST NOT return ack when it has a resource to return — that case is singleton. A surface MUST NOT collapse an empty list into an error — that case is collection with data: [].
Singleton
{
"ok": true,
"data": { "...": "..." },
"error": null,
"meta": { "result_type": "singleton" }
}data is one JSON object representing the resource.
Collection
{
"ok": true,
"data": [ {} ],
"error": null,
"meta": {
"result_type": "collection",
"pagination": {
"next_cursor": "opaque-token-or-null",
"has_more": true
}
}
}data is always an array. meta.pagination is present only for paginated collection surfaces; an unpaginated list still returns data as an array. See Pagination and filtering.
Ack
{
"ok": true,
"data": null,
"error": null,
"meta": { "result_type": "ack" }
}Error
{
"ok": false,
"data": null,
"error": {
"code": "VALIDATION_ERROR",
"message": "human-readable summary",
"details": {}
},
"meta": { "result_type": "error" }
}The error envelope shape, the semantic codes, and their HTTP mapping are documented in Errors.
Success status mapping
| Outcome | HTTP status |
|---|---|
| Singleton read | 200 |
| Collection read (including an empty collection) | 200 |
| Command that creates a new resource in this call | 201 |
| Command that updates or returns an existing resource without creating new identity | 200 |
| Ack — command succeeds with no resource body | 200 |
Empty results
Collection absence and singleton absence are distinct outcomes:
- A singleton selector that resolves to nothing MUST return
404withok: falseanderror.code: NOT_FOUND. - A collection query that matches no rows MUST return
200withok: trueanddata: []. - An empty collection MUST NOT be returned as
404.
Request body posture
When an endpoint takes a request body, that body MUST be a top-level JSON object whose keys are the exact field names documented for that endpoint.
- The body MUST NOT be wrapped in an envelope such as
payload,input, orattributes. Send the fields at the root. - A body-bearing request whose JSON root is not an object (an array, a string, a number) MUST be rejected as
VALIDATION_ERROR(400).
Unknown fields
Unknown body fields and unknown query parameters MUST be treated as a validation failure (VALIDATION_ERROR, 400). Do not send fields that are not part of the documented contract for the endpoint.
Null versus omission
- An optional field MAY be omitted.
- A field MUST NOT be sent as
nullunless it is explicitly documented as nullable for that endpoint. - Sending
nullfor a field that is not documented as nullable MUST be rejected asVALIDATION_ERROR(400).
Omission and null are not interchangeable: omit a field you are not setting; send null only where null is a documented value.
Field names
Selector parameters, filter parameters, and request-body fields MUST use the exact canonical names documented for the endpoint. The API does not accept aliases or abbreviations for canonical fields.