Authentication & Signing

Every UTMOS Open Platform endpoint requires an HMAC-SHA256 request signature. This page covers the credentials you need, how to compute the signature, and how to debug common errors.

Credentials

The platform issues each integrator:
  • API ID (public identifier)
  • API Key (private secret used for signing)
How to obtain them: request via the platform operations team. Provide your integrator name, intended use cases, and the scopes you need.
Keep your API Key strictly confidential. If it leaks, contact the platform immediately to rotate.

Relationship to Web Console Login

Open Platform API keys are only for server-side integration signing. They must not be placed in browsers, mobile local storage, or Web Console page state. Web Console uses a separate human-user auth model with server-set httpOnly session cookies and CSRF tokens for browser mutations. Console users may create, rotate, or disable Open Platform API credentials when their role and approval policy allow it. New secrets are disclosed exactly once; the platform does not store them in later Console pages, JavaScript-readable cookies, localStorage, or sessionStorage.
ScenarioIdentity
Server calls /api/v1/open/* or /api/v1/platform/*X-Api-Id + HMAC signature
Browser uses /console or /api/v1/console/*Console user session cookie + CSRF
Create or rotate an Open Platform API keyConsole approval flow or HMAC Platform Management API
Browser triggers device commandsDo not use an API key directly; a backend integration service should sign

Required Headers

HeaderRequiredDescription
X-Api-IdyesApplication identifier
X-Api-TimestampyesUnix-seconds timestamp (string)
X-Api-NonceyesReplay-protection nonce; unique per API ID within the replay window
X-Api-SignatureyesHMAC-SHA256 signature, lowercase hex, exactly 64 chars
X-Request-IdnoRequest correlation ID; generated by the platform when omitted

Signature Computation

Canonical String

A fixed 8-line layout joined by \n:
  1. UTMOS-HMAC-SHA256
  2. METHOD (uppercase)
  3. PATH (path only — no query, no host)
  4. Query string encoded with RFC 3986 rules and sorted by key (empty string when no query)
  5. SHA256_HEX(BODY) (hash the empty byte string when no body — yields e3b0c44...)
  6. The raw X-Api-Id value
  7. The raw X-Api-Timestamp value
  8. The raw X-Api-Nonce value
Example (POST /api/v1/open/downlink/commands):
UTMOS-HMAC-SHA256
POST
/api/v1/open/downlink/commands

<sha256_of_request_body>
client_abc
1745308800
nonce-001

Compute the Signature

Use the API Key as the HMAC-SHA256 secret over the canonical string and emit lowercase hex.
BODY='{"vendor":"dji","device_id":"drone-001","command_type":"camera_mode_switch","payload":{"payload_index":"52-0-0","camera_mode":0},"idempotency_key":"req-001","timeout_seconds":30}'
TS="$(date +%s)"
NONCE="nonce-$TS"
BODY_HASH="$(printf '%s' "$BODY" | shasum -a 256 | awk '{print $1}')"
CANONICAL="UTMOS-HMAC-SHA256
POST
/api/v1/open/downlink/commands

$BODY_HASH
$API_ID
$TS
$NONCE"
SIGNATURE="$(printf '%s' "$CANONICAL" | openssl dgst -sha256 -hmac "$API_KEY" -binary | xxd -p -c 256)"

curl -X POST "https://dev.utmos.dev/api/v1/open/downlink/commands" \
  -H "Content-Type: application/json" \
  -H "X-Api-Id: $API_ID" \
  -H "X-Api-Timestamp: $TS" \
  -H "X-Api-Nonce: $NONCE" \
  -H "X-Api-Signature: $SIGNATURE" \
  -d "$BODY"

Timestamp Skew Window

X-Api-Timestamp may differ from the server clock by the credential-configured skew window, defaulting to ±5 minutes. Outside that returns TIMESTAMP_EXPIRED. Keep your local clock in sync (NTP). If your system spans time zones, remember the value is Unix seconds — time-zone independent.

Nonce Replay Protection

X-Api-Nonce must be unique within the replay window for the current API ID. The platform records nonce usage facts; reuse returns NONCE_REPLAYED. Generate a new nonce for every request, even when the request body and idempotency key are intentionally replayed.

Secret Storage

The platform does not store plaintext API keys. Credential records store tenant binding, status, expiry, rotation timestamps, and signing-secret ciphertext protected with AES-256-GCM. The ciphertext envelope contains key ID, nonce, and ciphertext; decryption occurs only at the signature-verification boundary. Casbin stores authorization policy only and never stores credential material.

API Key Rotation

The platform rotates API keys through the credential update endpoint. After a successful rotation, the response returns the new secret exactly once and the platform does not expose the old secret again.
  1. Call the credential update/rotate endpoint with rotate_secret=true.
  2. Store the one-time secret returned in the response.
  3. Recompute signatures with the new secret.
  4. The old secret becomes invalid immediately after rotation.

Troubleshooting

SymptomLikely cause
UNAUTHORIZEDOne of X-Api-Id / X-Api-Timestamp / X-Api-Nonce / X-Api-Signature is missing
SIGNATURE_INVALIDWrong API Key; canonical string assembled incorrectly (sort the query, hash even an empty body); proxy mutated the body (compression, line-ending changes, etc.)
TIMESTAMP_EXPIREDLocal clock drift; you sent milliseconds; you sent an ISO string
NONCE_REPLAYEDNonce was reused within the replay window
FORBIDDENAPI Key lacks tenant-domain authorization for this endpoint (see Scope Catalog)
For the full code list see Error Model.