> For the complete documentation index, see [llms.txt](https://api.qvalia.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://api.qvalia.io/api-documentation/apis/authentication.md).

# Authentication

Obtain a JWT for use as a Bearer token on any Qvalia API

## Create access token (JWT) for accountRegNo

> Exchange an API key for a short-lived JWT access token, authenticating\
> as \`accountRegNo\` (a Partner uses its own \`partnerRegNo\` here). The\
> returned token can be used as a Bearer token\
> (\`Authorization: Bearer \<token>\`) on any Qvalia API endpoint as an\
> alternative to the API key.\
> \
> \`GET\` always authenticates as self; use \`POST\` if you need to act on\
> behalf of a child account (\`actingAs: parent\`).\
> \
> Tokens expire after one hour.

```json
{"openapi":"3.0.2","info":{"title":"Qvalia Authentication API","version":"1.0.0"},"tags":[{"name":"Authentication","description":"Obtain a JWT for use as a Bearer token on any Qvalia API"}],"servers":[{"url":"https://api-test.qvalia.com"},{"url":"https://api.qvalia.com"}],"security":[{"api_key":[]},{"jwt":[]}],"components":{"securitySchemes":{"api_key":{"type":"apiKey","name":"Authorization","in":"header"},"jwt":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT-based authentication. The Authorization header must be set as:\nAuthorization: Bearer <token>\nObtain a token via POST /token/{accountRegNo} or POST /token (see Authentication API).\n"}},"parameters":{"accountRegNo":{"name":"accountRegNo","in":"path","required":true,"schema":{"type":"string","description":"","default":""},"description":"Account registration number issued by Qvalia. A Partner uses its own partnerRegNo here."}},"responses":{"tokenCreated":{"description":"OK. The response carries `Cache-Control: no-store` and `Pragma: no-cache`\n([RFC 6749 §5.1](https://www.rfc-editor.org/rfc/rfc6749#section-5.1)) — do not\ncache or log the token.","headers":{"Cache-Control":{"description":"Always `no-store`. The token must not be cached by anything in between.","schema":{"type":"string"}},"Pragma":{"description":"Always `no-cache`, for HTTP/1.0 intermediaries.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"access_token":{"type":"string"},"token_type":{"type":"string"},"expires_in":{"type":"integer"}}}}}},"TooManyRequests":{"description":"Too Many Requests. The account has exceeded its request budget, which is counted\nper account across all Qvalia APIs.\n\nRead `Retry-After` and wait at least that many seconds before retrying — retrying\nimmediately is simply rejected again. `RateLimit-Remaining` on every response tells\nyou how much of the budget is left, so a well-behaved client need not hit this at\nall. Contact [Qvalia Helpdesk](https://qvalia.com/help/) if your integration needs\na higher limit.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","description":"Every error returned by the Qvalia APIs uses this envelope. `type` is a stable\nmachine-readable code — branch on it rather than on `data`, whose wording may change.","properties":{"status":{"type":"string","description":"Always `error` on a failed request."},"type":{"type":"string","description":"Stable error code. One of `E_BAD_REQUEST` (400), `E_UNAUTHORIZED_CLIENT` /\n`E_CLIENT_UNSUCCESSFUL_AUTHENTICATION` (401), `E_MISSING_PERMISSION` (403),\n`E_MISSING` (404), `E_VALIDATION` (422), `E_RATE_LIMITED` (429) or\n`E_INTERNAL_PROXY_ERROR` (500)."},"data":{"type":"string","description":"Human-readable description of what went wrong."},"metadata":{"type":"object","description":"Additional detail. Shape varies by error type, and it is omitted entirely on a `500`."}}}}},"paths":{"/token/{accountRegNo}":{"get":{"tags":["Authentication"],"summary":"Create access token (JWT) for accountRegNo","description":"Exchange an API key for a short-lived JWT access token, authenticating\nas `accountRegNo` (a Partner uses its own `partnerRegNo` here). The\nreturned token can be used as a Bearer token\n(`Authorization: Bearer <token>`) on any Qvalia API endpoint as an\nalternative to the API key.\n\n`GET` always authenticates as self; use `POST` if you need to act on\nbehalf of a child account (`actingAs: parent`).\n\nTokens expire after one hour.","operationId":"authentication/get-token","parameters":[{"$ref":"#/components/parameters/accountRegNo"}],"responses":{"200":{"$ref":"#/components/responses/tokenCreated"},"401":{"description":"Unauthorized — the credentials were missing, malformed, or not valid for\nthis account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Unprocessable Entity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"description":"Internal Server Error"}}}}}}
```

## Create access token (JWT) for accountRegNo, or on behalf of a child account

> Exchange an API key for a short-lived JWT access token, authenticating\
> as \`accountRegNo\` (a Partner uses its own \`partnerRegNo\` here).\
> \
> \- \`actingAs: self\` (default) — issue a token for \`accountRegNo\` itself.\
> \- \`actingAs: parent\` — a Partner issues a token to act on behalf of a\
> &#x20; child account; \`forChildRegNo\` is required and the Partner must be\
> &#x20; authorized for that child. The token's \`sub\` claim will be the child\
> &#x20; account.\
> \
> The request body may be omitted entirely, which is equivalent to\
> \`{"actingAs": "self"}\`.\
> \
> Tokens expire after one hour.

```json
{"openapi":"3.0.2","info":{"title":"Qvalia Authentication API","version":"1.0.0"},"tags":[{"name":"Authentication","description":"Obtain a JWT for use as a Bearer token on any Qvalia API"}],"servers":[{"url":"https://api-test.qvalia.com"},{"url":"https://api.qvalia.com"}],"security":[{"api_key":[]},{"jwt":[]}],"components":{"securitySchemes":{"api_key":{"type":"apiKey","name":"Authorization","in":"header"},"jwt":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT-based authentication. The Authorization header must be set as:\nAuthorization: Bearer <token>\nObtain a token via POST /token/{accountRegNo} or POST /token (see Authentication API).\n"}},"parameters":{"accountRegNo":{"name":"accountRegNo","in":"path","required":true,"schema":{"type":"string","description":"","default":""},"description":"Account registration number issued by Qvalia. A Partner uses its own partnerRegNo here."}},"schemas":{"CreateTokenBody":{"type":"object","properties":{"actingAs":{"type":"string","enum":["self","parent"],"default":"self","description":"Optional, defaults to \"self\". If \"parent\", `forChildRegNo` is required and the caller must be authorized to act on behalf of that child."},"forChildRegNo":{"type":"string","description":"Required when actingAs is \"parent\"; the child account to act for."}}},"Error":{"type":"object","description":"Every error returned by the Qvalia APIs uses this envelope. `type` is a stable\nmachine-readable code — branch on it rather than on `data`, whose wording may change.","properties":{"status":{"type":"string","description":"Always `error` on a failed request."},"type":{"type":"string","description":"Stable error code. One of `E_BAD_REQUEST` (400), `E_UNAUTHORIZED_CLIENT` /\n`E_CLIENT_UNSUCCESSFUL_AUTHENTICATION` (401), `E_MISSING_PERMISSION` (403),\n`E_MISSING` (404), `E_VALIDATION` (422), `E_RATE_LIMITED` (429) or\n`E_INTERNAL_PROXY_ERROR` (500)."},"data":{"type":"string","description":"Human-readable description of what went wrong."},"metadata":{"type":"object","description":"Additional detail. Shape varies by error type, and it is omitted entirely on a `500`."}}}},"responses":{"tokenCreated":{"description":"OK. The response carries `Cache-Control: no-store` and `Pragma: no-cache`\n([RFC 6749 §5.1](https://www.rfc-editor.org/rfc/rfc6749#section-5.1)) — do not\ncache or log the token.","headers":{"Cache-Control":{"description":"Always `no-store`. The token must not be cached by anything in between.","schema":{"type":"string"}},"Pragma":{"description":"Always `no-cache`, for HTTP/1.0 intermediaries.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"access_token":{"type":"string"},"token_type":{"type":"string"},"expires_in":{"type":"integer"}}}}}},"TooManyRequests":{"description":"Too Many Requests. The account has exceeded its request budget, which is counted\nper account across all Qvalia APIs.\n\nRead `Retry-After` and wait at least that many seconds before retrying — retrying\nimmediately is simply rejected again. `RateLimit-Remaining` on every response tells\nyou how much of the budget is left, so a well-behaved client need not hit this at\nall. Contact [Qvalia Helpdesk](https://qvalia.com/help/) if your integration needs\na higher limit.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/token/{accountRegNo}":{"post":{"tags":["Authentication"],"summary":"Create access token (JWT) for accountRegNo, or on behalf of a child account","description":"Exchange an API key for a short-lived JWT access token, authenticating\nas `accountRegNo` (a Partner uses its own `partnerRegNo` here).\n\n- `actingAs: self` (default) — issue a token for `accountRegNo` itself.\n- `actingAs: parent` — a Partner issues a token to act on behalf of a\n  child account; `forChildRegNo` is required and the Partner must be\n  authorized for that child. The token's `sub` claim will be the child\n  account.\n\nThe request body may be omitted entirely, which is equivalent to\n`{\"actingAs\": \"self\"}`.\n\nTokens expire after one hour.","operationId":"authentication/create-token","parameters":[{"$ref":"#/components/parameters/accountRegNo"}],"requestBody":{"description":"Request body. May be omitted (defaults to `actingAs: self`).","required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTokenBody"}}}},"responses":{"200":{"$ref":"#/components/responses/tokenCreated"},"401":{"description":"Unauthorized — the credentials were missing, malformed, or not valid for\nthis account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Unprocessable Entity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"description":"Internal Server Error"}}}}}}
```

## Create access token (JWT) using client\_id/client\_secret

> Exchange \`client\_id\` (your \`accountRegNo\`) and \`client\_secret\` (your API\
> key) for a short-lived JWT access token. Use this as an alternative to\
> \`POST /token/{accountRegNo}\` when you'd rather not put \`accountRegNo\` in\
> the URI and the API key in the \`Authorization\` header - for example, if\
> your client is built around an OAuth2-style client-credentials exchange.\
> \
> The request body may be sent either as JSON (\`application/json\`) or\
> form-encoded (\`application/x-www-form-urlencoded\`), so a standard OAuth2\
> client-credentials client works unchanged. \`grant\_type=client\_credentials\` is\
> accepted and, being the only supported grant, may also be omitted.\
> \
> Supply the credentials either way:\
> \- \*\*In the body\*\* — \`client\_id\` and \`client\_secret\` as JSON or form fields (see below).\
> \- \*\*As HTTP Basic auth\*\* — \`Authorization: Basic base64(client\_id:client\_secret)\`,\
> &#x20; per \[RFC 6749 §2.3.1]\(<https://www.rfc-editor.org/rfc/rfc6749#section-2.3.1),\\>
> &#x20; the convention most off-the-shelf OAuth2 client libraries default to for a\
> &#x20; client\_credentials exchange. When Basic auth is present, the body may be\
> &#x20; omitted entirely (or contain only \`actingAs\`/\`forChildRegNo\`); a\
> &#x20; \`client\_id\`/\`client\_secret\` pair in the body always takes precedence over\
> &#x20; Basic auth if both are supplied.\
> \
> \- \`actingAs: self\` (default) — issue a token for \`client\_id\` itself.\
> \- \`actingAs: parent\` — a Partner issues a token to act on behalf of a\
> &#x20; child account; \`forChildRegNo\` is required and the Partner\
> &#x20; (\`client\_id\`) must be authorized for that child. The token's \`sub\`\
> &#x20; claim will be the child account.\
> \
> There is no bodyless \`GET /token\` equivalent - \`GET\` always requires\
> \`accountRegNo\` in the URI, see \`GET /token/{accountRegNo}\`.\
> \
> Tokens expire after one hour.

```json
{"openapi":"3.0.2","info":{"title":"Qvalia Authentication API","version":"1.0.0"},"tags":[{"name":"Authentication","description":"Obtain a JWT for use as a Bearer token on any Qvalia API"}],"servers":[{"url":"https://api-test.qvalia.com"},{"url":"https://api.qvalia.com"}],"security":[{"basic":[]},{}],"components":{"securitySchemes":{"basic":{"type":"http","scheme":"basic","description":"HTTP Basic auth as an alternative way to supply client_id/client_secret to\nPOST /token (username = client_id, password = client_secret). Only accepted\non POST /token, not on other Qvalia API endpoints.\n"}},"schemas":{"ClientCredentialsBody":{"allOf":[{"$ref":"#/components/schemas/CreateTokenBody"},{"type":"object","properties":{"client_id":{"type":"string","description":"Your accountRegNo (a Partner uses its own partnerRegNo here). Required unless supplied via HTTP Basic auth instead."},"client_secret":{"type":"string","description":"Your API key. Required unless supplied via HTTP Basic auth instead."},"grant_type":{"type":"string","description":"Optional. `client_credentials` is the only supported grant, so it may be\nomitted. Any other value is rejected.","enum":["client_credentials"]}}}]},"CreateTokenBody":{"type":"object","properties":{"actingAs":{"type":"string","enum":["self","parent"],"default":"self","description":"Optional, defaults to \"self\". If \"parent\", `forChildRegNo` is required and the caller must be authorized to act on behalf of that child."},"forChildRegNo":{"type":"string","description":"Required when actingAs is \"parent\"; the child account to act for."}}},"Error":{"type":"object","description":"Every error returned by the Qvalia APIs uses this envelope. `type` is a stable\nmachine-readable code — branch on it rather than on `data`, whose wording may change.","properties":{"status":{"type":"string","description":"Always `error` on a failed request."},"type":{"type":"string","description":"Stable error code. One of `E_BAD_REQUEST` (400), `E_UNAUTHORIZED_CLIENT` /\n`E_CLIENT_UNSUCCESSFUL_AUTHENTICATION` (401), `E_MISSING_PERMISSION` (403),\n`E_MISSING` (404), `E_VALIDATION` (422), `E_RATE_LIMITED` (429) or\n`E_INTERNAL_PROXY_ERROR` (500)."},"data":{"type":"string","description":"Human-readable description of what went wrong."},"metadata":{"type":"object","description":"Additional detail. Shape varies by error type, and it is omitted entirely on a `500`."}}}},"responses":{"tokenCreated":{"description":"OK. The response carries `Cache-Control: no-store` and `Pragma: no-cache`\n([RFC 6749 §5.1](https://www.rfc-editor.org/rfc/rfc6749#section-5.1)) — do not\ncache or log the token.","headers":{"Cache-Control":{"description":"Always `no-store`. The token must not be cached by anything in between.","schema":{"type":"string"}},"Pragma":{"description":"Always `no-cache`, for HTTP/1.0 intermediaries.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"access_token":{"type":"string"},"token_type":{"type":"string"},"expires_in":{"type":"integer"}}}}}},"TooManyRequests":{"description":"Too Many Requests. The account has exceeded its request budget, which is counted\nper account across all Qvalia APIs.\n\nRead `Retry-After` and wait at least that many seconds before retrying — retrying\nimmediately is simply rejected again. `RateLimit-Remaining` on every response tells\nyou how much of the budget is left, so a well-behaved client need not hit this at\nall. Contact [Qvalia Helpdesk](https://qvalia.com/help/) if your integration needs\na higher limit.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/token":{"post":{"tags":["Authentication"],"summary":"Create access token (JWT) using client_id/client_secret","description":"Exchange `client_id` (your `accountRegNo`) and `client_secret` (your API\nkey) for a short-lived JWT access token. Use this as an alternative to\n`POST /token/{accountRegNo}` when you'd rather not put `accountRegNo` in\nthe URI and the API key in the `Authorization` header - for example, if\nyour client is built around an OAuth2-style client-credentials exchange.\n\nThe request body may be sent either as JSON (`application/json`) or\nform-encoded (`application/x-www-form-urlencoded`), so a standard OAuth2\nclient-credentials client works unchanged. `grant_type=client_credentials` is\naccepted and, being the only supported grant, may also be omitted.\n\nSupply the credentials either way:\n- **In the body** — `client_id` and `client_secret` as JSON or form fields (see below).\n- **As HTTP Basic auth** — `Authorization: Basic base64(client_id:client_secret)`,\n  per [RFC 6749 §2.3.1](https://www.rfc-editor.org/rfc/rfc6749#section-2.3.1),\n  the convention most off-the-shelf OAuth2 client libraries default to for a\n  client_credentials exchange. When Basic auth is present, the body may be\n  omitted entirely (or contain only `actingAs`/`forChildRegNo`); a\n  `client_id`/`client_secret` pair in the body always takes precedence over\n  Basic auth if both are supplied.\n\n- `actingAs: self` (default) — issue a token for `client_id` itself.\n- `actingAs: parent` — a Partner issues a token to act on behalf of a\n  child account; `forChildRegNo` is required and the Partner\n  (`client_id`) must be authorized for that child. The token's `sub`\n  claim will be the child account.\n\nThere is no bodyless `GET /token` equivalent - `GET` always requires\n`accountRegNo` in the URI, see `GET /token/{accountRegNo}`.\n\nTokens expire after one hour.","operationId":"authentication/create-token-client-credentials","requestBody":{"description":"Request body. May be omitted (or contain only `actingAs`/`forChildRegNo`)\nwhen `client_id`/`client_secret` are instead supplied via HTTP Basic auth.","required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientCredentialsBody"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/ClientCredentialsBody"}}}},"responses":{"200":{"$ref":"#/components/responses/tokenCreated"},"401":{"description":"Unauthorized — the credentials were missing, malformed, or not valid for\nthis account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Unprocessable Entity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"description":"Internal Server Error"}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://api.qvalia.io/api-documentation/apis/authentication.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
