Admin APIShort-lived tokens

Short-lived tokens

Tokens are small, time-boxed credentials you hand to the SDK instead of a permanent API key.

PropertyDescription
Formatsh_<32 hex chars>
CarryEverything the SDK needs - licence, limits, optional remote config
TTL60 - 86 400 seconds (default 3600 s)
ScopeOnly allows initializing the SDK

Why prefer tokens?

  • Leak resistance - a captured token dies quickly, your permanent key stays safe.
  • Granular limits - set max measurements or single-device lock.
  • Dynamic config - You can dynamically construct SDK configuration on-demand for each individual SDK usage.

End-points

MethodPathPurpose
POST/v1/tokenCreate one token
POST/v1/tokensCreate many (up to 1000) in one call

Both require the tokens:generate scope.

Request body (single-token)

FieldTypeRequiredNotes
license_idintNoOmit to use first active licence
expires_inintNo60 - 86 400 (seconds), default 3600
max_measurementsintNoHard-cap per token
single_deviceboolNoLock to first device
sdk_config_idintNoEmbed an existing Remote Config
sdk_config_inlineobjectNoFull JSON config (mutually exclusive with above)

See the OpenAPI reference for the exact schema.

Quick example - one-hour, single-device token

curl -X POST https://api.shen.ai/v1/token \
  -H "Authorization: Bearer $SHENAI_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"expires_in":3600,"single_device":true}'

Response

{
  "token": "sh_b71ef965c4c4468b9eab8c646f6f6d16",
  "expires_at": "2025-07-15T12:00:00Z"
}

Quick example - five tokens in bulk

curl -X POST https://api.shen.ai/v1/tokens \
  -H "Authorization: Bearer $SHENAI_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "count": 5, "expires_in": 1800 }'

Returns an array of five objects identical to the single-token response.

Using the token in the SDK

Any Shen.AI SDK constructor accepts a token exactly where you used to pass the permanent key.

// Web SDK
shenaiSDK.initialize("sh_b71ef965c4c4468b9eab8c646f6f6d16");
// Android
shenaiSDKHandler.initialize(this, "sh_b71ef965c4c4468b9eab8c646f6f6d16");

No other code changes are needed.

Best practices

DoWhy
Store the Admin Credential in an env variableNever check secrets into git
Use single_device: true whenever feasiblePrevents key-sharing across devices
Keep TTL short (≤ 1 h) for Web SDKLimits impact of a leak
Use longer TTL for mobile SDKs if you expect offline usageEnsures the SDK can continue working even if the device has no internet connection

Error catalogue

HTTP statusError codeTypical cause
400BAD_REQUESTMissing or malformed JSON
401UNAUTHORIZEDNo / bad Authorization header
403FORBIDDENAdmin Credential lacks tokens:generate
500SERVER_ERRORUnexpected backend issue
⚠️

Tokens cannot currently be revoked individually.
Design for short TTLs or rotate the Admin Credential if immediate revocation is needed.


FAQ

Can I refresh a token on the device?

No. The device must ask your backend for a fresh token.

Does using tokens change billing?

No - measurements count the same way they do with permanent keys.

What if max_measurements is reached before expires_at?

The SDK treats the token as expired and will refuse to initialise.

What happens when during an SDK session max_measurements is reached?

In the embedded SDK’s UI, the equivalent of enableStartAfterSuccess will be set to false, and the user won’t see the “Measure again” button on screens after completing the measurement. If you use your own UI, there will be no effect and you will still be able to start new measurements.

What if a token expires while the SDK is running?

The SDK will continue to work until it’s deinitialized.

Is it possible that more than one measurement is made with a token that set max_measurements = 1?

Yes, if multiple SDK instances are initialized with the same token before starting any measurements, they will not be prevented from starting the measurement. To prevent that scenario, use single_device: true to limit usage to a single device.

;