Authentication
Trainer and search endpoints require a JWT Bearer token for a company user (an end-user of your app):
1Authorization: Bearer <jwt_token>Obtaining a JWT token — call the verify-api-key endpoint from your backend (never embed your company API key in client code):
1POST https://data.kinestex.com/api/companies/me/verify-api-key/| Header / Field | Required | Description |
x-api-key header | Yes | Your company's API key |
user_id (JSON body) | Yes | A unique identifier for the end-user in your system (e.g. UUID or database ID) |
1curl -X POST "https://data.kinestex.com/api/companies/me/verify-api-key/" \
2 -H "x-api-key: your_api_key_here" \
3 -H "Content-Type: application/json" \
4 -d '{"user_id": "user-abc-123"}'The response includes a token field — use it as the Bearer token in all subsequent API requests. The user_id you provide should match the user_id used across other KinesteX endpoints and SDK launches so user data stays consistent.
Session tokens (recommended for client launches): instead of shipping a raw API key to the client, your backend can mint a short-lived session for SDK launches — see Session Auth & Managed Subscriptions.
A session also works for direct REST calls, without the SDK. Your backend mints one, the client exchanges it for a JWT:
1# 1. Your backend mints the session (API key never leaves your server)
2curl -X POST "https://data.kinestex.com/api/sessions" \
3 -H "x-api-key: your_api_key_here" -H "Content-Type: application/json" \
4 -d '{"user_id": "user-abc-123", "ttl_seconds": 3600}'
5# → { "session_id": "ksx_sess_…", "expires_at": "…" }
6
7# 2. The client exchanges the session for a Bearer JWT
8curl -X POST "https://data.kinestex.com/api/auth/session-verify" \
9 -H "x-session-id: ksx_sess_…"
10# → { "token": "<jwt>", "user_id": "user-abc-123", … }session-verify returns the same payload as verify-api-key, so the token is an ordinary Bearer JWT accepted by every endpoint on this page and by the Content API. The difference: its expiry is pinned to the session's, so a client can never outlive the session it was issued from.
| Detail | Value |
| Session lifetime | ttl_seconds if shorter, otherwise the 5-hour cap. Omit it to get 5 hours |
| Custom session ID | Pass session_id on the mint call, minimum 24 characters. Omit it and one is generated |
| Revoke early | DELETE /api/sessions/{id} with your API key, where {id} is the numeric id from GET /api/sessions, not the session token |
| Rejections | 401 with Session token missing, Invalid session, Session revoked, or Session expired. 403 with "code": "access_excluded" when the user's excluded_options block the view the SDK is launching (see Session Auth & Managed Subscriptions) |
Language: the trainer replies in the user's language. Set either header on any trainer request (defaults to English):
1Language: es # custom header, takes precedence
2Accept-Language: es-MX # standard header, used as fallbackLocale tags are normalized to their base code (es-MX → es).