Device commands
6 operations at https://api.zaitrack.app. Request and response bodies are JSON with camelCase keys; ids are UUIDs; times are RFC 3339 in UTC.
Commands reach real devices: sending and approving one needs a recent step-up MFA, so an API key cannot do it. The organisation's approval policy may hold a command for another person.
Every operation needs an API key, a personal access token or an OAuth access token unless it says otherwise. An Idempotency-Key is replayed for 24 hours; see Idempotency. Errors are application/problem+json; see Errors.
Send a command to a device
POST /v1/commands
command-bus-service applies your organisation's approval policy: a command may wait for a person other than its issuer to approve or deny it. The same idempotencyKey for the same device and body within 24 hours returns the command already issued, with 200 instead of 201.
- Scope:
commands:writeorcommands:* - Rate class:
command(20 per second and 360,000 per hour) - Idempotency-Key: required
- Audited: high risk
- Step-up MFA: required (an OAuth session with a recent WebAuthn step-up; API keys never qualify)
Request
Fields the handler reads, taken from its source.
| Field | Type | Notes |
|---|---|---|
deviceId | string (UUID) | |
vehicleId | string (UUID) | optional |
kind | string | |
payload | any JSON | |
reason | string | optional |
ttlS | integer | optional |
maxAttempts | integer | optional |
idempotencyKey | string | |
channel | string | optional |
Response
201 or 200: fields the handler writes, taken from its source.
| Field | Type | Notes |
|---|---|---|
id | string (UUID) | |
tenantId | string (UUID) | |
deviceId | string (UUID) | |
vehicleId | string (UUID) | omitted when empty |
kind | string | |
payload | any JSON | |
risk | string | |
reason | string | omitted when empty |
issuer | object | |
issuer.id | string | |
issuer.role | string | omitted when empty |
issuedAt | string (date-time) | |
ttl | integer (ns) | |
idempotencyKey | string | |
bodySha256 | string | |
approvals | array of object | |
approvals[].by | object | |
approvals[].by.id | string | |
approvals[].by.role | string | omitted when empty |
approvals[].approved | boolean | |
approvals[].at | string (date-time) | |
approvals[].note | string | omitted when empty |
approvedAt | string (date-time) | omitted when empty |
state | string | |
nextAt | string (date-time) | |
attempts | integer | |
maxAttempts | integer | |
hold | string | omitted when empty |
ack | object | omitted when empty |
ack.state | string | |
ack.details | any JSON | |
ack.at | string (date-time) | |
failure | string | omitted when empty |
version | integer | |
approvalsRequired | integer | omitted when empty |
channel | string | omitted when empty |
smsTo | string | omitted when empty |
smsRef | string | omitted when empty |
Example
Every field is sent with a placeholder value: replace them with yours.
Set STEP_UP_ACCESS_TOKEN to an OAuth session access token with a recent WebAuthn step-up. An API key or personal access token does not satisfy this requirement.
curl -X POST "https://api.zaitrack.app/v1/commands" \
-H "Authorization: Bearer $STEP_UP_ACCESS_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"deviceId": "00000000-0000-0000-0000-000000000000", "vehicleId": "00000000-0000-0000-0000-000000000000", "kind": "…", "payload": null, "reason": "…", "ttlS": 0, "maxAttempts": 0, "idempotencyKey": "…", "channel": "…"}'
List commands
GET /v1/commands
- Scope:
commands:readorcommands:* - Rate class:
read(100 per second and 360,000 per hour) - Idempotency-Key: not used
- Audited: no
- Step-up MFA: no
| Query parameter | Type | Notes |
|---|---|---|
deviceId | string | |
vehicleId | string | |
limit | string | |
state | string |
Request
No body.
Response
200: fields the handler writes, taken from its source.
Keys: items. Their types are not described.
Example
curl "https://api.zaitrack.app/v1/commands" \
-H "Authorization: Bearer zk_test_…"
A command with its events
GET /v1/commands/{id}
- Scope:
commands:readorcommands:* - Rate class:
read(100 per second and 360,000 per hour) - Idempotency-Key: not used
- Audited: no
- Step-up MFA: no
Path parameters: id.
Request
No body.
Response
200: not described. The service's OpenAPI document has no schema for this response, and the handler's could not be read from its source.
Example
curl "https://api.zaitrack.app/v1/commands/$ID" \
-H "Authorization: Bearer zk_test_…"
Approve a pending command
POST /v1/commands/{id}:approve
- Scope:
commands:writeorcommands:* - Rate class:
command(20 per second and 360,000 per hour) - Idempotency-Key: optional
- Audited: high risk
- Step-up MFA: required (an OAuth session with a recent WebAuthn step-up; API keys never qualify)
Path parameters: id.
Request
Fields the handler reads, taken from its source. One handler serves several actions here, so a field may not apply to this one.
| Field | Type | Notes |
|---|---|---|
note | string |
Response
200: not described. The service's OpenAPI document has no schema for this response, and the handler's could not be read from its source.
Example
Every field is sent with a placeholder value: replace them with yours.
Set STEP_UP_ACCESS_TOKEN to an OAuth session access token with a recent WebAuthn step-up. An API key or personal access token does not satisfy this requirement.
curl -X POST "https://api.zaitrack.app/v1/commands/$ID:approve" \
-H "Authorization: Bearer $STEP_UP_ACCESS_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"note": "…"}'
Deny a pending command
POST /v1/commands/{id}:deny
- Scope:
commands:writeorcommands:* - Rate class:
command(20 per second and 360,000 per hour) - Idempotency-Key: optional
- Audited: medium risk
- Step-up MFA: no
Path parameters: id.
Request
Fields the handler reads, taken from its source. One handler serves several actions here, so a field may not apply to this one.
The same fields as the request of Approve a pending command.
Response
200: not described. The service's OpenAPI document has no schema for this response, and the handler's could not be read from its source.
Example
Every field is sent with a placeholder value: replace them with yours.
curl -X POST "https://api.zaitrack.app/v1/commands/$ID:deny" \
-H "Authorization: Bearer zk_test_…" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"note": "…"}'
Cancel a command not yet sent
POST /v1/commands/{id}:cancel
- Scope:
commands:writeorcommands:* - Rate class:
command(20 per second and 360,000 per hour) - Idempotency-Key: optional
- Audited: low risk
- Step-up MFA: no
Path parameters: id.
Request
Fields the handler reads, taken from its source. One handler serves several actions here, so a field may not apply to this one.
The same fields as the request of Approve a pending command.
Response
200: not described. The service's OpenAPI document has no schema for this response, and the handler's could not be read from its source.
Example
Every field is sent with a placeholder value: replace them with yours.
curl -X POST "https://api.zaitrack.app/v1/commands/$ID:cancel" \
-H "Authorization: Bearer zk_test_…" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"note": "…"}'