JWT Token
Some scenarios do not allow using the API key directly. That is the case of the liveness SDKs, which run inside the end user's app or browser — embedding the API key there would expose it to anyone who inspected the application.
For these cases, your backend calls this endpoint with the API key and gets back a short-lived JWT token, which can safely be handed to the user's device. The token carries the same permissions as the key that issued it and expires on its own.
This endpoint performs no analysis: it only issues the token.
🚧 Attention!
Calls to this endpoint must always come from your backend. Never put the API key in the app, in the front end, or anywhere the end user could inspect it.
Request
POST/auth-jwtThis endpoint is not versioned: the call is always /auth-jwt, with no version in the path.
Headers
Content-Type: application/json
Authorization: ApiKey <your-api-key>This is the only endpoint in this documentation that does not accept the JWT token in place of the API key — it is the endpoint that issues the token.
Parameters
Every field in the body is optional. The body can be an empty object, or it can be omitted altogether.
| Parameter | Description | Required |
|---|---|---|
| federalRevenueNumber | CPF (the Brazilian individual taxpayer number) to bind to the token. When sent, it is validated; an invalid CPF makes the request fail. It can be sent with or without a mask. | No |
| ttl | The token's lifetime. A string carrying the time unit: "15m", "1h", "30s", "7d". Without it, our token issuer's default applies — today, 15 minutes. | No |
‼️ ttl must be a string carrying the unit
Sending "ttl": 900 (a number) makes the token issuance fail with 500. Send "ttl": "15m" instead. And even as a string, the value must carry the unit: "900" without a unit is read as 900 milliseconds, not 900 seconds.
Any other field sent in the body is accepted and travels inside the token, but it does not change the permissions granted: those are always the ones of the API key used in the call.
Example request
curl -i -X POST 'https://api-homolog.nxcd.app/auth-jwt' \
--header 'Content-Type: application/json' \
--header 'Authorization: ApiKey YOUR_API_KEY' \
--data '{ "federalRevenueNumber": "12345678909", "ttl": "15m" }'Response
| Field | Description | Type |
|---|---|---|
| accessToken | The signed JWT token, to be used by the SDK. | String |
The response of this endpoint does not use the id / version / data / metadata envelope of the analysis endpoints. The request identifier remains available in the Nextid-ReqId header.
JSON examples
Status Code: 200{
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY1MGUxZDJiM2M0ZDVlNmY3ODkwYWJjZCJ9.SIGNATURE_HERE"
}How to use the token
Wherever the documentation asks for Authorization: ApiKey <key>, the JWT token goes in like this:
Authorization: Bearer <accessToken>The API decides which form to use from the content of the Authorization header: if it contains Bearer, the token is validated as a JWT; otherwise, the value is treated as an API key.
Every endpoint in this documentation accepts both forms — API key or JWT token. The only exception is POST /auth-jwt itself, which requires the API key.
TIP
The token's permissions are those of the key that issued it. If the key has no access to a product, neither will the token, and the response will be 401.
Errors
| Code | When it happens |
|---|---|
| 401 Unauthorized | API key missing or invalid, or without permission to issue tokens. |
| 422 Unprocessable Entity | federalRevenueNumber was sent, but it does not pass check-digit validation. |
| 500 Internal Server Error | Token issuance failed. The most common avoidable cause here is ttl sent as a number instead of a string. |
Example response with an invalid CPF:
Status Code: 422{
"id": "13cfec7c-b238-4820-a4d1-5173e4c1418e",
"error": {
"statusCode": 422,
"error": "Unprocessable Entity",
"message": "Invalid Federal Revenue Number"
}
}The format of error responses is described in HTTP response codes.
Next step
With the token in hand, move on to the Liveness flow.