Authentication
RabbitQA issues a signed JWT access token and an opaque refresh token. Every service behind the gateway validates the same access token locally.
Sign in
curl -X POST https://api.rabbitqa.com/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{ "username": "[email protected]", "password": "••••••••" }'
username accepts an email address, and email is accepted as an alias for the same field.
{
"token": "eyJhbGciOiJIUzI1NiJ9...",
"expiresIn": "2026-09-07T22:14:03",
"refreshToken": "b0a1c4f2-..."
}
expiresIn is the absolute expiry timestamp of the access token, not a duration.
Access tokens are valid for 8 hours by default.
Send the access token on every subsequent request:
curl https://api.rabbitqa.com/api/v1/users/me \
-H "Authorization: Bearer $TOKEN"
Refresh
curl -X POST https://api.rabbitqa.com/api/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{ "refreshToken": "b0a1c4f2-..." }'
Returns a new token, expiresIn and refreshToken.
Refresh tokens are stored server-side and can be revoked.
Sign out
curl -X POST https://api.rabbitqa.com/api/v1/auth/logout \
-H "Authorization: Bearer $TOKEN"
The access token is added to a blocklist and is rejected by the gateway for the remainder of its lifetime.
Other auth endpoints
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/auth/signup | Self-service registration |
POST | /api/v1/auth/forgot-password | Send a reset link |
POST | /api/v1/auth/reset-password | Complete a reset |
POST | /api/v1/auth/switch-workspace/{workspaceId} | Re-issue the token with a different active workspace |
All of these are also reachable under the /tmt/api/v1/auth/** prefix, which the gateway rewrites to the same Organization endpoints.
The workspace header
Authentication identifies who you are; X-Workspace-Id selects where you are working.
curl https://api.rabbitqa.com/tmt/company/api/v1/projects \
-H "Authorization: Bearer $TOKEN" \
-H "X-Workspace-Id: 91"
The gateway rejects a workspace your account cannot reach with 403 Invalid X-Workspace-Id header.
GET /api/v1/workspaces/accessible lists the workspaces available to the signed-in user.
Authorization model
RabbitQA does not use OAuth scopes. Access is decided by two independent checks:
- Module entitlement — the gateway asks the Organization service whether the active workspace has the module that owns the requested prefix. Without the entitlement the call is rejected before it reaches the service.
- Permissions — the owning service enforces granular permission keys such as
TESTPILOT_READ,analyzer:analysis:createorautorunner:testdata:reveal, granted through roles.
GET /api/v1/users/me/permissions and GET /api/v1/permissions/me return the keys held by the current user.
Non-user credentials
Some integrations authenticate as something other than a signed-in person.
| Credential | Header | Used by |
|---|---|---|
| HealthCheck API key | X-API-Key | External callers of the HealthCheck endpoints. Managed with POST/GET /healthcheck/api/v1/api-keys and DELETE /healthcheck/api/v1/api-keys/{id}. |
| Device Farm API key | X-Api-Key | Device Farm file presign and confirm calls under /df/api/files/**. Generated in MobileHub and BrowserHub settings. |
| Engine token | X-Engine-Token | AutoRunner test engines reporting back to the platform. |
There is no general-purpose, user-generated platform API key. Programmatic access to the product APIs uses the same JWT login flow described above.
Public endpoints
A small number of paths are reachable without a token:
POST /api/v1/auth/login,/refresh,/signup,/forgot-password,/reset-password/tmt/api/v1/public/download/**— pre-authorized file downloadsPOST /healthcheck/api/v1/heartbeat/{token}andPOST /healthcheck/api/v1/metrics/{token}— push endpoints authenticated by the token in the path- The DataCrate public mock service dispatch under
/tmt/api/v1/public/dataCrate/mock-services/{publicId}
CORS
The gateway accepts browser requests from https://*.rabbitqa.com and from localhost during development, allowing the authorization, content-type, x-auth-token and x-workspace-id headers.