> 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/account-api/webhook-api.md).

# Webhook API

Operations related to Web hooks

## Get Webhook Configuration

> An API to fetch (GET) the webhook subscription for your Partner account.\
> \
> \### Partner or Partners Account\
> Partners can configure their own web hooks through \`/partner/{partnerRegNo}/webhook/...\` URI, or their child accounts using \`/partner/{partnerRegNo}/account/{accountRegNo}/webhook/...\`.\
> The latter is useful if you want to scope the subscription to a single account.\
> A partner-level subscription covers the partner's own account \*\*only\*\*, not its\
> children: to receive a child's events, subscribe to that child with\
> \`/partner/{partnerRegNo}/account/{accountRegNo}/webhook/...\`, one child at a time.\
> A partner's subscription to a child is separate from the child's own subscription\
> (neither can see or change the other's), and an event for the child is delivered to\
> both, with the same \`eventId\`. It delivers only while the partner may act for the\
> child (the child's \`parentAccount\` is the partner and the partner holds the\
> \`webhook\` scope), which is checked on every delivery.\
> \### parameter \`accountRegNo\` is only required for child accounts, and should be omitted for the Partner account itself.

```json
{"openapi":"3.0.2","info":{"title":"Qvalia Account API","version":"1.0.0"},"tags":[{"name":"Webhook API","description":"Operations related to Web hooks"}],"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>\n\nObtain a token via POST /token/{accountRegNo} (see Authentication API).\n"}},"parameters":{"accountRegNo":{"name":"accountRegNo","in":"path","required":true,"schema":{"type":"string"},"description":"Account registration number issued by Qvalia"}},"schemas":{"WebhookSigningSecretInfo":{"type":"object","description":"A signing secret on a subscription, described without its value. Secrets are\nstored encrypted and are only ever shown once, when issued.","properties":{"id":{"type":"string","description":"Identifier for the secret. Not itself a secret."},"createdAt":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time","nullable":true,"description":"When this secret stops verifying. `null` for the current secret, which does\nnot expire; a date on a secret being rotated away from."},"active":{"type":"boolean","description":"Whether the secret is still used to sign deliveries."}}},"Error":{"type":"object","description":"Every error returned by the Qvalia APIs uses this envelope. `type` is a\nstable machine-readable code — branch on it rather than on `data`, which is\na human-readable message 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),\n`E_UNAUTHORIZED_CLIENT` / `E_CLIENT_UNSUCCESSFUL_AUTHENTICATION` (401),\n`E_MISSING_PERMISSION` (403), `E_MISSING` (404), `E_CONFLICT` (409),\n`E_VALIDATION` / `E_PEPPOL_PARTICIPANT_SMP_LOOKUP` (422),\n`E_RATE_LIMITED` (429), `E_NOT_IMPLEMENTED` (501) or\n`E_INTERNAL_PROXY_ERROR` (500)."},"data":{"type":"string","description":"Human-readable description of what went wrong."},"metadata":{"type":"object","description":"Additional detail about the failure. The shape varies by error type — a `429`\ncarries `limit` and `retryAfterSeconds`, a `409` carries the colliding\n`integrationId` — and it is omitted entirely on a `500`. Treat it as an open\nmap and read only the keys you need.","additionalProperties":true,"properties":{"debug_error_message":{"type":"string","description":"Longer explanation intended for a developer reading a log."},"debug_error_code":{"type":"integer","description":"Echoes the HTTP status code."}}}}}},"responses":{"NoContent":{"description":"No Content. The request succeeded and there is no body to return."},"Unauthorized":{"description":"Unauthorized. The API key or Bearer token is missing, malformed, or not valid\nfor the account in the URI.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"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"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"type":{"type":"string","description":"`E_INTERNAL_PROXY_ERROR`, or `E_UNKNOWN` when the failure carried no type."},"data":{"type":"string"}}}}}}}},"paths":{"/account/{accountRegNo}/webhook/configure":{"get":{"tags":["Webhook API"],"summary":"Get Webhook Configuration","description":"An API to fetch (GET) the webhook subscription for your Partner account.\n\n### Partner or Partners Account\nPartners can configure their own web hooks through `/partner/{partnerRegNo}/webhook/...` URI, or their child accounts using `/partner/{partnerRegNo}/account/{accountRegNo}/webhook/...`.\nThe latter is useful if you want to scope the subscription to a single account.\nA partner-level subscription covers the partner's own account **only**, not its\nchildren: to receive a child's events, subscribe to that child with\n`/partner/{partnerRegNo}/account/{accountRegNo}/webhook/...`, one child at a time.\nA partner's subscription to a child is separate from the child's own subscription\n(neither can see or change the other's), and an event for the child is delivered to\nboth, with the same `eventId`. It delivers only while the partner may act for the\nchild (the child's `parentAccount` is the partner and the partner holds the\n`webhook` scope), which is checked on every delivery.\n### parameter `accountRegNo` is only required for child accounts, and should be omitted for the Partner account itself.","operationId":"account/get-webhook-config","parameters":[{"$ref":"#/components/parameters/accountRegNo"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string"},"types":{"type":"array","items":{"type":"string"}},"accountRegNo":{"type":"string"},"enabled":{"type":"boolean"},"authType":{"type":"string","nullable":true,"enum":["oauth","api_key","basic"]},"signing":{"type":"object","nullable":true,"description":"Signing state for this subscription, or `null` when deliveries are\nunsigned. This block carries ids and dates only, never a secret value.","properties":{"algorithm":{"type":"string","enum":["hmac-sha256"]},"secrets":{"type":"array","items":{"$ref":"#/components/schemas/WebhookSigningSecretInfo"}}}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}},"204":{"$ref":"#/components/responses/NoContent"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Configure Webhook

> An API to create or update (PUT) the webhook subscription for your account.\
> \
> An account has a single webhook subscription. The first \`PUT\` creates it and\
> returns a generated webhook \`id\` (a UUID v4); subsequent \`PUT\` requests update\
> the same subscription (its \`url\` and/or \`types\`). Use the returned \`id\` with the\
> \`/account/{accountRegNo}/webhook/{webhookId}/auth\` endpoints to attach outbound\
> authentication.\
> \
> A \`PUT\` that creates the subscription returns a \`signingSecret\` in clear text in\
> that response only. Store it; see \`/account/{accountRegNo}/webhook/{webhookId}/secret\`\
> to rotate it or to obtain one for an older subscription.\
> \
> \### Event types\
> \
> \- \`new\_document\` — sent when a new document is received/created for an account.\
> \- \`document\_delivery\` — sent when a document's delivery status changes.\
> \- \`document\_delayed\` — sent when a delivery is being retried and has not finished.\
> \- \`document\_error\` — sent when a document's delivery fails.\
> \
> \### Delivery (webhook usage)\
> \
> Events are delivered as an HTTP \`POST\` with a JSON body to the configured \`url\`\
> (which must be \`https\`). Your endpoint should respond with a \`2xx\` status code;\
> the delivery request times out after 10 seconds. If outbound authentication is\
> configured (see \`/account/{accountRegNo}/webhook/{webhookId}/auth\`) it is applied\
> as request headers on every delivery. The delivered payload is a single flat\
> JSON object — see the \`webhookEvent\` callback below for the full schema, and\
> \`/partner/{partnerRegNo}/webhook/configure\` in the Partner API for worked\
> examples of all three event types.\
> \
> Every delivery carries \`X-Qvalia-Event-Id\`, and \`X-Qvalia-Signature\` once the\
> subscription has a signing secret — see\
> \`/account/{accountRegNo}/webhook/{webhookId}/secret\`.\
> \
> Delivery is best-effort: duplicates are possible, and a failed delivery is not\
> retried. A missed event can be fetched again for 30 days with \`GET .../webhook/{eventId}\`,\
> but keep polling the Transaction API\
> as a safety net — see \`/partner/{partnerRegNo}/webhook/configure\` in the Partner\
> API for details.

```json
{"openapi":"3.0.2","info":{"title":"Qvalia Account API","version":"1.0.0"},"tags":[{"name":"Webhook API","description":"Operations related to Web hooks"}],"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>\n\nObtain a token via POST /token/{accountRegNo} (see Authentication API).\n"}},"parameters":{"accountRegNo":{"name":"accountRegNo","in":"path","required":true,"schema":{"type":"string"},"description":"Account registration number issued by Qvalia"}},"responses":{"Unauthorized":{"description":"Unauthorized. The API key or Bearer token is missing, malformed, or not valid\nfor the account in the URI.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UnprocessableEntity":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"type":{"type":"string"},"data":{"type":"string"},"metadata":{"type":"object","properties":{}}}}}}},"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"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"type":{"type":"string","description":"`E_INTERNAL_PROXY_ERROR`, or `E_UNKNOWN` when the failure carried no type."},"data":{"type":"string"}}}}}}},"schemas":{"Error":{"type":"object","description":"Every error returned by the Qvalia APIs uses this envelope. `type` is a\nstable machine-readable code — branch on it rather than on `data`, which is\na human-readable message 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),\n`E_UNAUTHORIZED_CLIENT` / `E_CLIENT_UNSUCCESSFUL_AUTHENTICATION` (401),\n`E_MISSING_PERMISSION` (403), `E_MISSING` (404), `E_CONFLICT` (409),\n`E_VALIDATION` / `E_PEPPOL_PARTICIPANT_SMP_LOOKUP` (422),\n`E_RATE_LIMITED` (429), `E_NOT_IMPLEMENTED` (501) or\n`E_INTERNAL_PROXY_ERROR` (500)."},"data":{"type":"string","description":"Human-readable description of what went wrong."},"metadata":{"type":"object","description":"Additional detail about the failure. The shape varies by error type — a `429`\ncarries `limit` and `retryAfterSeconds`, a `409` carries the colliding\n`integrationId` — and it is omitted entirely on a `500`. Treat it as an open\nmap and read only the keys you need.","additionalProperties":true,"properties":{"debug_error_message":{"type":"string","description":"Longer explanation intended for a developer reading a log."},"debug_error_code":{"type":"integer","description":"Echoes the HTTP status code."}}}}}}},"paths":{"/account/{accountRegNo}/webhook/configure":{"put":{"tags":["Webhook API"],"summary":"Configure Webhook","description":"An API to create or update (PUT) the webhook subscription for your account.\n\nAn account has a single webhook subscription. The first `PUT` creates it and\nreturns a generated webhook `id` (a UUID v4); subsequent `PUT` requests update\nthe same subscription (its `url` and/or `types`). Use the returned `id` with the\n`/account/{accountRegNo}/webhook/{webhookId}/auth` endpoints to attach outbound\nauthentication.\n\nA `PUT` that creates the subscription returns a `signingSecret` in clear text in\nthat response only. Store it; see `/account/{accountRegNo}/webhook/{webhookId}/secret`\nto rotate it or to obtain one for an older subscription.\n\n### Event types\n\n- `new_document` — sent when a new document is received/created for an account.\n- `document_delivery` — sent when a document's delivery status changes.\n- `document_delayed` — sent when a delivery is being retried and has not finished.\n- `document_error` — sent when a document's delivery fails.\n\n### Delivery (webhook usage)\n\nEvents are delivered as an HTTP `POST` with a JSON body to the configured `url`\n(which must be `https`). Your endpoint should respond with a `2xx` status code;\nthe delivery request times out after 10 seconds. If outbound authentication is\nconfigured (see `/account/{accountRegNo}/webhook/{webhookId}/auth`) it is applied\nas request headers on every delivery. The delivered payload is a single flat\nJSON object — see the `webhookEvent` callback below for the full schema, and\n`/partner/{partnerRegNo}/webhook/configure` in the Partner API for worked\nexamples of all three event types.\n\nEvery delivery carries `X-Qvalia-Event-Id`, and `X-Qvalia-Signature` once the\nsubscription has a signing secret — see\n`/account/{accountRegNo}/webhook/{webhookId}/secret`.\n\nDelivery is best-effort: duplicates are possible, and a failed delivery is not\nretried. A missed event can be fetched again for 30 days with `GET .../webhook/{eventId}`,\nbut keep polling the Transaction API\nas a safety net — see `/partner/{partnerRegNo}/webhook/configure` in the Partner\nAPI for details.","operationId":"account/put-webhook-config","parameters":[{"$ref":"#/components/parameters/accountRegNo"}],"requestBody":{"description":"Request body","required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","types"],"properties":{"url":{"type":"string","format":"uri","description":"HTTPS endpoint that will receive webhook events"},"types":{"type":"array","minItems":1,"items":{"type":"string","enum":["new_document","document_delivery","document_delayed","document_error"]}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string"},"types":{"type":"array","items":{"type":"string"}},"accountRegNo":{"type":"string"},"signingSecret":{"type":"string","description":"Secret used to sign deliveries to this subscription (HMAC-SHA256).\n\n**Returned only when this `PUT` created the subscription, and only\nin this one response** — we store it encrypted and cannot show it\nagain. Store it now. Lost it, or updating a subscription created\nbefore signing existed? Use\n`POST /account/{accountRegNo}/webhook/{webhookId}/secret`."},"signingSecretId":{"type":"string","description":"Identifier for the secret above, for use in support and audit. Not itself a secret."},"signatureAlgorithm":{"type":"string","enum":["hmac-sha256"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"}},"callbacks":{"webhookEvent":{"{$request.body#/url}":{"post":{"summary":"Webhook event delivered to your endpoint","description":"Qvalia POSTs this JSON payload to your configured `url` when a subscribed\nevent occurs. Your endpoint should respond with a `2xx` status code; the\nrequest times out after 10 seconds. Any configured outbound authentication\n(see `/account/{accountRegNo}/webhook/{webhookId}/auth`) is applied as\nrequest headers.\n\nWhen the subscription has a signing secret, the delivery is also signed —\nsee `POST /account/{accountRegNo}/webhook/{webhookId}/secret`.","parameters":[{"name":"X-Qvalia-Event-Id","in":"header","required":true,"description":"Identifies the event, not the delivery attempt: redeliveries of the same\nevent carry the same value. Mirrors `eventId` in the body. Deduplicate on it.","schema":{"type":"string","format":"uuid"}},{"name":"X-Qvalia-Signature","in":"header","required":false,"description":"HMAC-SHA256 signature of the delivered body, in the form\n`t=<unix seconds>,v1=<hex>`. Recompute\n`HMAC-SHA256(secret, \"<t>.<raw body>\")` over the **raw** bytes received\nand compare in constant time. More than one `v1=` part is sent while a\nsecret rotation overlap is open — any one matching is a pass. Ignore\nparts whose prefix you do not recognise. Only sent when the subscription\nhas a signing secret.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["eventId","eventType","accountRegNo"],"properties":{"eventId":{"type":"string","format":"uuid","description":"Identifies the event, not the delivery attempt. Derived from the\nevent content, so every redelivery of the same event carries the\nsame value — deduplicate on it. Also sent as the\n`X-Qvalia-Event-Id` header."},"eventType":{"type":"string","enum":["new_document","document_delivery","document_delayed","document_error"]},"accountRegNo":{"type":"string"},"documentType":{"type":"string","description":"e.g. Invoice, CreditNote, Order"},"integrationId":{"type":"string","format":"uuid","description":"Qvalia unique identifier for the transaction/message"},"direction":{"type":"string","enum":["incoming","outgoing"]},"occurredAt":{"type":"string","format":"date-time"},"documentId":{"type":"string","description":"Document number (e.g. invoice number). Present on `new_document`;\nmay be absent on `document_delivery`/`document_error` when the\nupstream delivery channel does not report one."},"globalTransactionId":{"type":"string","format":"uuid","description":"Qvalia's platform-wide transaction id for this document exchange. Absent if not available for this event."},"status":{"type":"object","description":"Delivery-lifecycle detail for this event. Present on all event types.","properties":{"status":{"type":"string","description":"Delivery status reported by the upstream delivery channel (Peppol,\nemail, print, …).\n\nValues currently emitted, and whether each is final:\n\n- `pending` (non-final) — logged; nothing attempted yet. Also the\n  upstream column default.\n- `warning` (non-final) — reopened by a rules-processor reset.\n- `delayed` (non-final) — being retried: a Peppol send still inside\n  its retry window. Another event **will** follow. Not a failure!\n- `processed` (final) — delivered successfully.\n- `processed_with_warning` (final) — delivered, but something about\n  the exchange is worth flagging.\n- `error` (non-final) — delivery failed; the top-level `error` carries\n  the reason. Message resend might follow.\n- *absent* — no status reported for this event. Documents entering\n  through the Public API announce themselves without one.\n\n**To tell a retry from a real failure, branch on this field rather\nthan on the text of `error`:** `delayed` means another attempt is\ncoming, `error` means the send has stopped for good."},"event":{"type":"string","description":"The internal message-log lifecycle event that triggered this webhook.","enum":["message-log/create","message-log/update","message-log/delayed","message-log/error"]},"deliveryMethod":{"type":"string","description":"Delivery method used for this document, e.g. `peppol`, `print`, `email`,\n`api`, `internetbank`, `kivra`, `billo`, `minameddelanden`, `postal`,\n`dynamic_routing`. Like `status`, an open set. May be absent."},"updatedAt":{"type":"string","format":"date-time"}}},"error":{"type":"string","description":"Error message describing the delivery failure. Only present when `eventType` is `document_error`."},"peppol_metadata":{"type":"object","nullable":true,"description":"Peppol exchange detail recorded for the document so far — a later status report\ncarries what was stored when the document was sent or received. `null` when\n`status.deliveryMethod` is not `peppol`; `{}` when nothing is known yet, e.g. a\nretry report before any exchange succeeded.","properties":{"messageId":{"type":"string"},"accessPoint":{"type":"string"},"docTypeId":{"type":"string"},"processId":{"type":"string"},"exchangeDateTime":{"type":"string","format":"date-time"},"senderPeppolId":{"type":"string","description":"Sender's Peppol participant id."},"receiverPeppolId":{"type":"string","description":"Receiver's Peppol participant id."}}}}}}}},"responses":{"2XX":{"description":"Event acknowledged by your endpoint"},"4XX":{"description":"Event not acknowledged by your endpoint"}},"security":[{}]}}}}}}}}
```

## Delete Webhook Configuration

> An API to DELETE the webhook subscription for your Partner account.\
> \
> This removes the subscription and any attached outbound authentication.\
> \
> \### Partner or Partners Account\
> Partners can configure their own web hooks through \`/partner/{partnerRegNo}/webhook/...\` URI, or their child accounts using \`/partner/{partnerRegNo}/account/{accountRegNo}/webhook/...\`.\
> The latter is useful if you want to scope the subscription to a single account.\
> A partner-level subscription covers the partner's own account \*\*only\*\*, not its\
> children: to receive a child's events, subscribe to that child with\
> \`/partner/{partnerRegNo}/account/{accountRegNo}/webhook/...\`, one child at a time.\
> A partner's subscription to a child is separate from the child's own subscription\
> (neither can see or change the other's), and an event for the child is delivered to\
> both, with the same \`eventId\`. It delivers only while the partner may act for the\
> child (the child's \`parentAccount\` is the partner and the partner holds the\
> \`webhook\` scope), which is checked on every delivery.\
> \### parameter \`accountRegNo\` is only required for child accounts, and should be omitted for the Partner account itself.

```json
{"openapi":"3.0.2","info":{"title":"Qvalia Account API","version":"1.0.0"},"tags":[{"name":"Webhook API","description":"Operations related to Web hooks"}],"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>\n\nObtain a token via POST /token/{accountRegNo} (see Authentication API).\n"}},"parameters":{"accountRegNo":{"name":"accountRegNo","in":"path","required":true,"schema":{"type":"string"},"description":"Account registration number issued by Qvalia"}},"responses":{"NoContent":{"description":"No Content. The request succeeded and there is no body to return."},"Unauthorized":{"description":"Unauthorized. The API key or Bearer token is missing, malformed, or not valid\nfor the account in the URI.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"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"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"type":{"type":"string","description":"`E_INTERNAL_PROXY_ERROR`, or `E_UNKNOWN` when the failure carried no type."},"data":{"type":"string"}}}}}}},"schemas":{"Error":{"type":"object","description":"Every error returned by the Qvalia APIs uses this envelope. `type` is a\nstable machine-readable code — branch on it rather than on `data`, which is\na human-readable message 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),\n`E_UNAUTHORIZED_CLIENT` / `E_CLIENT_UNSUCCESSFUL_AUTHENTICATION` (401),\n`E_MISSING_PERMISSION` (403), `E_MISSING` (404), `E_CONFLICT` (409),\n`E_VALIDATION` / `E_PEPPOL_PARTICIPANT_SMP_LOOKUP` (422),\n`E_RATE_LIMITED` (429), `E_NOT_IMPLEMENTED` (501) or\n`E_INTERNAL_PROXY_ERROR` (500)."},"data":{"type":"string","description":"Human-readable description of what went wrong."},"metadata":{"type":"object","description":"Additional detail about the failure. The shape varies by error type — a `429`\ncarries `limit` and `retryAfterSeconds`, a `409` carries the colliding\n`integrationId` — and it is omitted entirely on a `500`. Treat it as an open\nmap and read only the keys you need.","additionalProperties":true,"properties":{"debug_error_message":{"type":"string","description":"Longer explanation intended for a developer reading a log."},"debug_error_code":{"type":"integer","description":"Echoes the HTTP status code."}}}}}}},"paths":{"/account/{accountRegNo}/webhook/configure":{"delete":{"tags":["Webhook API"],"summary":"Delete Webhook Configuration","description":"An API to DELETE the webhook subscription for your Partner account.\n\nThis removes the subscription and any attached outbound authentication.\n\n### Partner or Partners Account\nPartners can configure their own web hooks through `/partner/{partnerRegNo}/webhook/...` URI, or their child accounts using `/partner/{partnerRegNo}/account/{accountRegNo}/webhook/...`.\nThe latter is useful if you want to scope the subscription to a single account.\nA partner-level subscription covers the partner's own account **only**, not its\nchildren: to receive a child's events, subscribe to that child with\n`/partner/{partnerRegNo}/account/{accountRegNo}/webhook/...`, one child at a time.\nA partner's subscription to a child is separate from the child's own subscription\n(neither can see or change the other's), and an event for the child is delivered to\nboth, with the same `eventId`. It delivers only while the partner may act for the\nchild (the child's `parentAccount` is the partner and the partner holds the\n`webhook` scope), which is checked on every delivery.\n### parameter `accountRegNo` is only required for child accounts, and should be omitted for the Partner account itself.","operationId":"account/delete-webhook-config","parameters":[{"$ref":"#/components/parameters/accountRegNo"}],"responses":{"204":{"$ref":"#/components/responses/NoContent"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Get Webhook Authentication

> An API to fetch (GET) the outbound authentication type configured for your\
> account's webhook subscription. The credential itself is never returned.

```json
{"openapi":"3.0.2","info":{"title":"Qvalia Account API","version":"1.0.0"},"tags":[{"name":"Webhook API","description":"Operations related to Web hooks"}],"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>\n\nObtain a token via POST /token/{accountRegNo} (see Authentication API).\n"}},"parameters":{"accountRegNo":{"name":"accountRegNo","in":"path","required":true,"schema":{"type":"string"},"description":"Account registration number issued by Qvalia"},"webhookId":{"name":"webhookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Webhook identifier returned by PUT /webhook/configure, e.g. \"a1b2c3d4-5678-90ab-cdef-1234567890ab\""}},"responses":{"NoContent":{"description":"No Content. The request succeeded and there is no body to return."},"Unauthorized":{"description":"Unauthorized. The API key or Bearer token is missing, malformed, or not valid\nfor the account in the URI.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"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"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"type":{"type":"string","description":"`E_INTERNAL_PROXY_ERROR`, or `E_UNKNOWN` when the failure carried no type."},"data":{"type":"string"}}}}}}},"schemas":{"Error":{"type":"object","description":"Every error returned by the Qvalia APIs uses this envelope. `type` is a\nstable machine-readable code — branch on it rather than on `data`, which is\na human-readable message 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),\n`E_UNAUTHORIZED_CLIENT` / `E_CLIENT_UNSUCCESSFUL_AUTHENTICATION` (401),\n`E_MISSING_PERMISSION` (403), `E_MISSING` (404), `E_CONFLICT` (409),\n`E_VALIDATION` / `E_PEPPOL_PARTICIPANT_SMP_LOOKUP` (422),\n`E_RATE_LIMITED` (429), `E_NOT_IMPLEMENTED` (501) or\n`E_INTERNAL_PROXY_ERROR` (500)."},"data":{"type":"string","description":"Human-readable description of what went wrong."},"metadata":{"type":"object","description":"Additional detail about the failure. The shape varies by error type — a `429`\ncarries `limit` and `retryAfterSeconds`, a `409` carries the colliding\n`integrationId` — and it is omitted entirely on a `500`. Treat it as an open\nmap and read only the keys you need.","additionalProperties":true,"properties":{"debug_error_message":{"type":"string","description":"Longer explanation intended for a developer reading a log."},"debug_error_code":{"type":"integer","description":"Echoes the HTTP status code."}}}}}}},"paths":{"/account/{accountRegNo}/webhook/{webhookId}/auth":{"get":{"tags":["Webhook API"],"summary":"Get Webhook Authentication","description":"An API to fetch (GET) the outbound authentication type configured for your\naccount's webhook subscription. The credential itself is never returned.","operationId":"account/get-webhook-auth","parameters":[{"$ref":"#/components/parameters/accountRegNo"},{"$ref":"#/components/parameters/webhookId"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["oauth","api_key","basic"]}}}}}},"204":{"$ref":"#/components/responses/NoContent"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Set Webhook Authentication

> An API to set (POST) the outbound authentication applied to webhook deliveries\
> for your Partner account's subscription.\
> \
> \`{webhookId}\` must match the \`id\` returned by \`PUT /partner/{partnerRegNo}/account/{accountRegNo}/webhook/configure\`.\
> \
> Provide exactly one of the supported auth \`type\`s:\
> \
> \- \`oauth\` — client-credentials. Qvalia fetches a Bearer token from \`tokenUrl\`\
> &#x20; using \`clientId\`/\`clientSecret\` (and optional \`scope\`) at delivery time.\
> \- \`api\_key\` — sent as a request header (\`header\`, default \`X-API-Key\`) with \`value\`.\
> \- \`basic\` — HTTP Basic auth using \`username\`/\`password\`. The \`password\` must be at\
> &#x20; least 16 characters and contain an uppercase letter, a lowercase letter, a digit\
> &#x20; and a special character.

```json
{"openapi":"3.0.2","info":{"title":"Qvalia Account API","version":"1.0.0"},"tags":[{"name":"Webhook API","description":"Operations related to Web hooks"}],"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>\n\nObtain a token via POST /token/{accountRegNo} (see Authentication API).\n"}},"parameters":{"accountRegNo":{"name":"accountRegNo","in":"path","required":true,"schema":{"type":"string"},"description":"Account registration number issued by Qvalia"},"webhookId":{"name":"webhookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Webhook identifier returned by PUT /webhook/configure, e.g. \"a1b2c3d4-5678-90ab-cdef-1234567890ab\""}},"responses":{"Unauthorized":{"description":"Unauthorized. The API key or Bearer token is missing, malformed, or not valid\nfor the account in the URI.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Not Found. The requested resource does not exist, or is not available to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UnprocessableEntity":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"type":{"type":"string"},"data":{"type":"string"},"metadata":{"type":"object","properties":{}}}}}}},"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"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"type":{"type":"string","description":"`E_INTERNAL_PROXY_ERROR`, or `E_UNKNOWN` when the failure carried no type."},"data":{"type":"string"}}}}}}},"schemas":{"Error":{"type":"object","description":"Every error returned by the Qvalia APIs uses this envelope. `type` is a\nstable machine-readable code — branch on it rather than on `data`, which is\na human-readable message 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),\n`E_UNAUTHORIZED_CLIENT` / `E_CLIENT_UNSUCCESSFUL_AUTHENTICATION` (401),\n`E_MISSING_PERMISSION` (403), `E_MISSING` (404), `E_CONFLICT` (409),\n`E_VALIDATION` / `E_PEPPOL_PARTICIPANT_SMP_LOOKUP` (422),\n`E_RATE_LIMITED` (429), `E_NOT_IMPLEMENTED` (501) or\n`E_INTERNAL_PROXY_ERROR` (500)."},"data":{"type":"string","description":"Human-readable description of what went wrong."},"metadata":{"type":"object","description":"Additional detail about the failure. The shape varies by error type — a `429`\ncarries `limit` and `retryAfterSeconds`, a `409` carries the colliding\n`integrationId` — and it is omitted entirely on a `500`. Treat it as an open\nmap and read only the keys you need.","additionalProperties":true,"properties":{"debug_error_message":{"type":"string","description":"Longer explanation intended for a developer reading a log."},"debug_error_code":{"type":"integer","description":"Echoes the HTTP status code."}}}}}}},"paths":{"/account/{accountRegNo}/webhook/{webhookId}/auth":{"post":{"tags":["Webhook API"],"summary":"Set Webhook Authentication","description":"An API to set (POST) the outbound authentication applied to webhook deliveries\nfor your Partner account's subscription.\n\n`{webhookId}` must match the `id` returned by `PUT /partner/{partnerRegNo}/account/{accountRegNo}/webhook/configure`.\n\nProvide exactly one of the supported auth `type`s:\n\n- `oauth` — client-credentials. Qvalia fetches a Bearer token from `tokenUrl`\n  using `clientId`/`clientSecret` (and optional `scope`) at delivery time.\n- `api_key` — sent as a request header (`header`, default `X-API-Key`) with `value`.\n- `basic` — HTTP Basic auth using `username`/`password`. The `password` must be at\n  least 16 characters and contain an uppercase letter, a lowercase letter, a digit\n  and a special character.","operationId":"account/post-webhook-auth","parameters":[{"$ref":"#/components/parameters/accountRegNo"},{"$ref":"#/components/parameters/webhookId"}],"requestBody":{"description":"Request body","required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["type","clientId","clientSecret","tokenUrl"],"properties":{"type":{"type":"string","enum":["oauth"]},"clientId":{"type":"string"},"clientSecret":{"type":"string"},"tokenUrl":{"type":"string","format":"uri"},"scope":{"type":"string","description":"Optional OAuth scope(s) sent with the client-credentials token request."}}},{"type":"object","required":["type","value"],"properties":{"type":{"type":"string","enum":["api_key"]},"header":{"type":"string","default":"X-API-Key","description":"Header the API key is sent in.\n\n`X-Qvalia-*` is reserved and rejected: that prefix carries the delivery's\nevent id and HMAC signature, so claiming one would overwrite a security\nheader on your own deliveries.","pattern":"^(?![Xx]-[Qq][Vv][Aa][Ll][Ii][Aa]-).+$"},"value":{"type":"string"}}},{"type":"object","required":["type","username","password"],"properties":{"type":{"type":"string","enum":["basic"]},"username":{"type":"string"},"password":{"type":"string","description":"Minimum 16 characters; must contain uppercase, lowercase, digit and special character."}}}]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["oauth","api_key","basic"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Delete Webhook Authentication

> An API to DELETE the outbound authentication from your account's webhook\
> subscription. The subscription itself is kept; deliveries are sent without auth\
> headers afterwards.

```json
{"openapi":"3.0.2","info":{"title":"Qvalia Account API","version":"1.0.0"},"tags":[{"name":"Webhook API","description":"Operations related to Web hooks"}],"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>\n\nObtain a token via POST /token/{accountRegNo} (see Authentication API).\n"}},"parameters":{"accountRegNo":{"name":"accountRegNo","in":"path","required":true,"schema":{"type":"string"},"description":"Account registration number issued by Qvalia"},"webhookId":{"name":"webhookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Webhook identifier returned by PUT /webhook/configure, e.g. \"a1b2c3d4-5678-90ab-cdef-1234567890ab\""}},"responses":{"NoContent":{"description":"No Content. The request succeeded and there is no body to return."},"Unauthorized":{"description":"Unauthorized. The API key or Bearer token is missing, malformed, or not valid\nfor the account in the URI.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"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"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"type":{"type":"string","description":"`E_INTERNAL_PROXY_ERROR`, or `E_UNKNOWN` when the failure carried no type."},"data":{"type":"string"}}}}}}},"schemas":{"Error":{"type":"object","description":"Every error returned by the Qvalia APIs uses this envelope. `type` is a\nstable machine-readable code — branch on it rather than on `data`, which is\na human-readable message 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),\n`E_UNAUTHORIZED_CLIENT` / `E_CLIENT_UNSUCCESSFUL_AUTHENTICATION` (401),\n`E_MISSING_PERMISSION` (403), `E_MISSING` (404), `E_CONFLICT` (409),\n`E_VALIDATION` / `E_PEPPOL_PARTICIPANT_SMP_LOOKUP` (422),\n`E_RATE_LIMITED` (429), `E_NOT_IMPLEMENTED` (501) or\n`E_INTERNAL_PROXY_ERROR` (500)."},"data":{"type":"string","description":"Human-readable description of what went wrong."},"metadata":{"type":"object","description":"Additional detail about the failure. The shape varies by error type — a `429`\ncarries `limit` and `retryAfterSeconds`, a `409` carries the colliding\n`integrationId` — and it is omitted entirely on a `500`. Treat it as an open\nmap and read only the keys you need.","additionalProperties":true,"properties":{"debug_error_message":{"type":"string","description":"Longer explanation intended for a developer reading a log."},"debug_error_code":{"type":"integer","description":"Echoes the HTTP status code."}}}}}}},"paths":{"/account/{accountRegNo}/webhook/{webhookId}/auth":{"delete":{"tags":["Webhook API"],"summary":"Delete Webhook Authentication","description":"An API to DELETE the outbound authentication from your account's webhook\nsubscription. The subscription itself is kept; deliveries are sent without auth\nheaders afterwards.","operationId":"account/delete-webhook-auth","parameters":[{"$ref":"#/components/parameters/accountRegNo"},{"$ref":"#/components/parameters/webhookId"}],"responses":{"204":{"$ref":"#/components/responses/NoContent"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Get Webhook Signing Secrets

> An API to fetch (GET) which signing secrets exist on your account's webhook\
> subscription and when each stops verifying.\
> \
> This endpoint returns ids and dates only, never a secret value.\
> \
> A secret is shown once, in the response that issues it: the \`PUT /account/{accountRegNo}/webhook/configure\`\
> that creates the subscription, or \`POST /account/{accountRegNo}/webhook/{webhookId}/secret\`. It is stored\
> encrypted and cannot be read back afterwards — if you have lost one, issue a new\
> one with \`POST\`.

```json
{"openapi":"3.0.2","info":{"title":"Qvalia Account API","version":"1.0.0"},"tags":[{"name":"Webhook API","description":"Operations related to Web hooks"}],"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>\n\nObtain a token via POST /token/{accountRegNo} (see Authentication API).\n"}},"parameters":{"accountRegNo":{"name":"accountRegNo","in":"path","required":true,"schema":{"type":"string"},"description":"Account registration number issued by Qvalia"},"webhookId":{"name":"webhookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Webhook identifier returned by PUT /webhook/configure, e.g. \"a1b2c3d4-5678-90ab-cdef-1234567890ab\""}},"schemas":{"WebhookSigningSecretInfo":{"type":"object","description":"A signing secret on a subscription, described without its value. Secrets are\nstored encrypted and are only ever shown once, when issued.","properties":{"id":{"type":"string","description":"Identifier for the secret. Not itself a secret."},"createdAt":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time","nullable":true,"description":"When this secret stops verifying. `null` for the current secret, which does\nnot expire; a date on a secret being rotated away from."},"active":{"type":"boolean","description":"Whether the secret is still used to sign deliveries."}}},"Error":{"type":"object","description":"Every error returned by the Qvalia APIs uses this envelope. `type` is a\nstable machine-readable code — branch on it rather than on `data`, which is\na human-readable message 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),\n`E_UNAUTHORIZED_CLIENT` / `E_CLIENT_UNSUCCESSFUL_AUTHENTICATION` (401),\n`E_MISSING_PERMISSION` (403), `E_MISSING` (404), `E_CONFLICT` (409),\n`E_VALIDATION` / `E_PEPPOL_PARTICIPANT_SMP_LOOKUP` (422),\n`E_RATE_LIMITED` (429), `E_NOT_IMPLEMENTED` (501) or\n`E_INTERNAL_PROXY_ERROR` (500)."},"data":{"type":"string","description":"Human-readable description of what went wrong."},"metadata":{"type":"object","description":"Additional detail about the failure. The shape varies by error type — a `429`\ncarries `limit` and `retryAfterSeconds`, a `409` carries the colliding\n`integrationId` — and it is omitted entirely on a `500`. Treat it as an open\nmap and read only the keys you need.","additionalProperties":true,"properties":{"debug_error_message":{"type":"string","description":"Longer explanation intended for a developer reading a log."},"debug_error_code":{"type":"integer","description":"Echoes the HTTP status code."}}}}}},"responses":{"NoContent":{"description":"No Content. The request succeeded and there is no body to return."},"Unauthorized":{"description":"Unauthorized. The API key or Bearer token is missing, malformed, or not valid\nfor the account in the URI.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"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"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"type":{"type":"string","description":"`E_INTERNAL_PROXY_ERROR`, or `E_UNKNOWN` when the failure carried no type."},"data":{"type":"string"}}}}}}}},"paths":{"/account/{accountRegNo}/webhook/{webhookId}/secret":{"get":{"tags":["Webhook API"],"summary":"Get Webhook Signing Secrets","description":"An API to fetch (GET) which signing secrets exist on your account's webhook\nsubscription and when each stops verifying.\n\nThis endpoint returns ids and dates only, never a secret value.\n\nA secret is shown once, in the response that issues it: the `PUT /account/{accountRegNo}/webhook/configure`\nthat creates the subscription, or `POST /account/{accountRegNo}/webhook/{webhookId}/secret`. It is stored\nencrypted and cannot be read back afterwards — if you have lost one, issue a new\none with `POST`.","operationId":"account/get-webhook-secret","parameters":[{"$ref":"#/components/parameters/accountRegNo"},{"$ref":"#/components/parameters/webhookId"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"webhookId":{"type":"string","format":"uuid"},"algorithm":{"type":"string","enum":["hmac-sha256"]},"secrets":{"type":"array","items":{"$ref":"#/components/schemas/WebhookSigningSecretInfo"}}}}}}},"204":{"$ref":"#/components/responses/NoContent"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Issue or Rotate Webhook Signing Secret

> Issue a signing secret for your account's webhook subscription, or rotate an existing one.\
> The same endpoint does both, and the plaintext secret is returned here and nowhere\
> else.\
> \
> \`{webhookId}\` must match the \`id\` returned by \`PUT /account/{accountRegNo}/webhook/configure\`.\
> \
> Deliveries are then signed with HMAC-SHA256 (\`X-Qvalia-Signature\`). See\
> \`POST /partner/{partnerRegNo}/webhook/{webhookId}/secret\` for how to verify a\
> delivery, the rotation rules and the \`overlapHours\` window.

```json
{"openapi":"3.0.2","info":{"title":"Qvalia Account API","version":"1.0.0"},"tags":[{"name":"Webhook API","description":"Operations related to Web hooks"}],"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>\n\nObtain a token via POST /token/{accountRegNo} (see Authentication API).\n"}},"parameters":{"accountRegNo":{"name":"accountRegNo","in":"path","required":true,"schema":{"type":"string"},"description":"Account registration number issued by Qvalia"},"webhookId":{"name":"webhookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Webhook identifier returned by PUT /webhook/configure, e.g. \"a1b2c3d4-5678-90ab-cdef-1234567890ab\""}},"responses":{"Unauthorized":{"description":"Unauthorized. The API key or Bearer token is missing, malformed, or not valid\nfor the account in the URI.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Not Found. The requested resource does not exist, or is not available to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UnprocessableEntity":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"type":{"type":"string"},"data":{"type":"string"},"metadata":{"type":"object","properties":{}}}}}}},"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"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"type":{"type":"string","description":"`E_INTERNAL_PROXY_ERROR`, or `E_UNKNOWN` when the failure carried no type."},"data":{"type":"string"}}}}}}},"schemas":{"Error":{"type":"object","description":"Every error returned by the Qvalia APIs uses this envelope. `type` is a\nstable machine-readable code — branch on it rather than on `data`, which is\na human-readable message 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),\n`E_UNAUTHORIZED_CLIENT` / `E_CLIENT_UNSUCCESSFUL_AUTHENTICATION` (401),\n`E_MISSING_PERMISSION` (403), `E_MISSING` (404), `E_CONFLICT` (409),\n`E_VALIDATION` / `E_PEPPOL_PARTICIPANT_SMP_LOOKUP` (422),\n`E_RATE_LIMITED` (429), `E_NOT_IMPLEMENTED` (501) or\n`E_INTERNAL_PROXY_ERROR` (500)."},"data":{"type":"string","description":"Human-readable description of what went wrong."},"metadata":{"type":"object","description":"Additional detail about the failure. The shape varies by error type — a `429`\ncarries `limit` and `retryAfterSeconds`, a `409` carries the colliding\n`integrationId` — and it is omitted entirely on a `500`. Treat it as an open\nmap and read only the keys you need.","additionalProperties":true,"properties":{"debug_error_message":{"type":"string","description":"Longer explanation intended for a developer reading a log."},"debug_error_code":{"type":"integer","description":"Echoes the HTTP status code."}}}}}}},"paths":{"/account/{accountRegNo}/webhook/{webhookId}/secret":{"post":{"tags":["Webhook API"],"summary":"Issue or Rotate Webhook Signing Secret","description":"Issue a signing secret for your account's webhook subscription, or rotate an existing one.\nThe same endpoint does both, and the plaintext secret is returned here and nowhere\nelse.\n\n`{webhookId}` must match the `id` returned by `PUT /account/{accountRegNo}/webhook/configure`.\n\nDeliveries are then signed with HMAC-SHA256 (`X-Qvalia-Signature`). See\n`POST /partner/{partnerRegNo}/webhook/{webhookId}/secret` for how to verify a\ndelivery, the rotation rules and the `overlapHours` window.","operationId":"account/post-webhook-secret","parameters":[{"$ref":"#/components/parameters/accountRegNo"},{"$ref":"#/components/parameters/webhookId"}],"requestBody":{"description":"Request body. Optional — omit it entirely to accept the default 24-hour overlap.","required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"overlapHours":{"type":"integer","minimum":0,"maximum":168,"default":24,"description":"How long the secrets being replaced keep verifying, so you can deploy\nthe new one at your own pace. During the window every delivery carries\na `v1=` part for each active secret.\n\nUse `0` when a secret has leaked: the old one stops verifying at once."}}}}}},"responses":{"200":{"description":"OK — the new signing secret. This is the only response that contains it.","content":{"application/json":{"schema":{"type":"object","properties":{"webhookId":{"type":"string","format":"uuid"},"algorithm":{"type":"string","enum":["hmac-sha256"]},"secretId":{"type":"string","description":"Identifier for the new secret. Not itself a secret."},"secret":{"type":"string","description":"The new signing secret, in clear text. **Store it now** — it is not\nretrievable afterwards. Rotate again if you lose it."},"createdAt":{"type":"string","format":"date-time"},"previousSecrets":{"type":"array","description":"Secrets this rotation replaced and when each stops verifying. Empty\nwhen the subscription had no signing secret before.","items":{"type":"object","properties":{"id":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Delete Webhook Signing Secret

> An API to DELETE signing from your account's webhook subscription. Every secret\
> is removed and deliveries are sent \*\*unsigned\*\* from the next event onwards. The\
> subscription itself, and any outbound authentication on it, are kept.

```json
{"openapi":"3.0.2","info":{"title":"Qvalia Account API","version":"1.0.0"},"tags":[{"name":"Webhook API","description":"Operations related to Web hooks"}],"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>\n\nObtain a token via POST /token/{accountRegNo} (see Authentication API).\n"}},"parameters":{"accountRegNo":{"name":"accountRegNo","in":"path","required":true,"schema":{"type":"string"},"description":"Account registration number issued by Qvalia"},"webhookId":{"name":"webhookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Webhook identifier returned by PUT /webhook/configure, e.g. \"a1b2c3d4-5678-90ab-cdef-1234567890ab\""}},"responses":{"NoContent":{"description":"No Content. The request succeeded and there is no body to return."},"Unauthorized":{"description":"Unauthorized. The API key or Bearer token is missing, malformed, or not valid\nfor the account in the URI.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"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"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"type":{"type":"string","description":"`E_INTERNAL_PROXY_ERROR`, or `E_UNKNOWN` when the failure carried no type."},"data":{"type":"string"}}}}}}},"schemas":{"Error":{"type":"object","description":"Every error returned by the Qvalia APIs uses this envelope. `type` is a\nstable machine-readable code — branch on it rather than on `data`, which is\na human-readable message 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),\n`E_UNAUTHORIZED_CLIENT` / `E_CLIENT_UNSUCCESSFUL_AUTHENTICATION` (401),\n`E_MISSING_PERMISSION` (403), `E_MISSING` (404), `E_CONFLICT` (409),\n`E_VALIDATION` / `E_PEPPOL_PARTICIPANT_SMP_LOOKUP` (422),\n`E_RATE_LIMITED` (429), `E_NOT_IMPLEMENTED` (501) or\n`E_INTERNAL_PROXY_ERROR` (500)."},"data":{"type":"string","description":"Human-readable description of what went wrong."},"metadata":{"type":"object","description":"Additional detail about the failure. The shape varies by error type — a `429`\ncarries `limit` and `retryAfterSeconds`, a `409` carries the colliding\n`integrationId` — and it is omitted entirely on a `500`. Treat it as an open\nmap and read only the keys you need.","additionalProperties":true,"properties":{"debug_error_message":{"type":"string","description":"Longer explanation intended for a developer reading a log."},"debug_error_code":{"type":"integer","description":"Echoes the HTTP status code."}}}}}}},"paths":{"/account/{accountRegNo}/webhook/{webhookId}/secret":{"delete":{"tags":["Webhook API"],"summary":"Delete Webhook Signing Secret","description":"An API to DELETE signing from your account's webhook subscription. Every secret\nis removed and deliveries are sent **unsigned** from the next event onwards. The\nsubscription itself, and any outbound authentication on it, are kept.","operationId":"account/delete-webhook-secret","parameters":[{"$ref":"#/components/parameters/accountRegNo"},{"$ref":"#/components/parameters/webhookId"}],"responses":{"204":{"$ref":"#/components/responses/NoContent"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Get a Delivered Webhook

> Fetch a delivered webhook again by its \`eventId\`, e.g. one your endpoint missed.\
> Every delivered body is kept for \*\*30 days\*\*.\
> \
> The response is the body exactly as it was POSTed to your \`url\`, same \`eventId\`\
> included, so it deduplicates against a delivery you did receive. It is not\
> signed: this request is authenticated like the rest of the API instead.\
> \
> The \`eventId\`s of failed deliveries are listed on the document's\
> \`GET /transaction/{accountRegNo}/{documents}/{direction}/status\`, under\
> \`metadata.webhooks\_dispatched\`, with the HTTP \`status\`/\`statusText\` your endpoint\
> returned.\
> \
> An event is served only for the account it is about (\`accountRegNo\` in the body).\
> An unknown or expired \`eventId\`, or another account's, answers \`204\`.

```json
{"openapi":"3.0.2","info":{"title":"Qvalia Account API","version":"1.0.0"},"tags":[{"name":"Webhook API","description":"Operations related to Web hooks"}],"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>\n\nObtain a token via POST /token/{accountRegNo} (see Authentication API).\n"}},"parameters":{"accountRegNo":{"name":"accountRegNo","in":"path","required":true,"schema":{"type":"string"},"description":"Account registration number issued by Qvalia"},"eventId":{"name":"eventId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"The `eventId` of a delivered webhook, as sent in the body and the `X-Qvalia-Event-Id` header, e.g. \"4d1c9f84-3a2b-5c6d-9e0f-1a2b3c4d5e6f\""}},"schemas":{"WebhookEvent":{"description":"A webhook body, as POSTed to your endpoint and as returned by\n`GET /account/{accountRegNo}/webhook/{eventId}`. Field reference: the `webhookEvent`\ncallback in the Partner API.","type":"object","required":["eventId","eventType","accountRegNo"],"properties":{"eventId":{"type":"string","format":"uuid","description":"Identifies the event, not the delivery attempt. Derived from the\nevent content, so every redelivery of the same event carries the\nsame value — deduplicate on it. Also sent as the\n`X-Qvalia-Event-Id` header."},"eventType":{"type":"string","enum":["new_document","document_delivery","document_delayed","document_error"]},"accountRegNo":{"type":"string"},"documentType":{"type":"string","description":"e.g. Invoice, CreditNote, Order"},"integrationId":{"type":"string","format":"uuid","description":"Qvalia unique identifier for the transaction/message"},"direction":{"type":"string","enum":["incoming","outgoing"]},"occurredAt":{"type":"string","format":"date-time"},"documentId":{"type":"string","description":"Document number (e.g. invoice number). Present on `new_document`;\nmay be absent on `document_delivery`/`document_error` when the\nupstream delivery channel does not report one."},"globalTransactionId":{"type":"string","format":"uuid","description":"Qvalia's platform-wide transaction id for this document exchange. Absent if not available for this event."},"status":{"type":"object","description":"Delivery-lifecycle detail for this event. Present on all event types.","properties":{"status":{"type":"string","description":"Delivery status reported by the upstream delivery channel (Peppol,\nemail, print, …).\n\nValues currently emitted, and whether each is final:\n\n- `pending` (non-final) — logged; nothing attempted yet. Also the\n  upstream column default.\n- `warning` (non-final) — reopened by a rules-processor reset.\n- `delayed` (non-final) — being retried: a Peppol send still inside\n  its retry window. Another event **will** follow. Not a failure!\n- `processed` (final) — delivered successfully.\n- `processed_with_warning` (final) — delivered, but something about\n  the exchange is worth flagging.\n- `error` (non-final) — delivery failed; the top-level `error` carries\n  the reason. Message resend might follow.\n- *absent* — no status reported for this event. Documents entering\n  through the Public API announce themselves without one.\n\n**To tell a retry from a real failure, branch on this field rather\nthan on the text of `error`:** `delayed` means another attempt is\ncoming, `error` means the send has stopped for good."},"event":{"type":"string","description":"The internal message-log lifecycle event that triggered this webhook.","enum":["message-log/create","message-log/update","message-log/delayed","message-log/error"]},"deliveryMethod":{"type":"string","description":"Delivery method used for this document, e.g. `peppol`, `print`, `email`,\n`api`, `internetbank`, `kivra`, `billo`, `minameddelanden`, `postal`,\n`dynamic_routing`. Like `status`, an open set. May be absent."},"updatedAt":{"type":"string","format":"date-time"}}},"error":{"type":"string","description":"Error message describing the delivery failure. Only present when `eventType` is `document_error`."},"peppol_metadata":{"type":"object","nullable":true,"description":"Peppol exchange detail recorded for the document so far — a later status report\ncarries what was stored when the document was sent or received. `null` when\n`status.deliveryMethod` is not `peppol`; `{}` when nothing is known yet, e.g. a\nretry report before any exchange succeeded.","properties":{"messageId":{"type":"string"},"accessPoint":{"type":"string"},"docTypeId":{"type":"string"},"processId":{"type":"string"},"exchangeDateTime":{"type":"string","format":"date-time"},"senderPeppolId":{"type":"string","description":"Sender's Peppol participant id."},"receiverPeppolId":{"type":"string","description":"Receiver's Peppol participant id."}}}}},"Error":{"type":"object","description":"Every error returned by the Qvalia APIs uses this envelope. `type` is a\nstable machine-readable code — branch on it rather than on `data`, which is\na human-readable message 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),\n`E_UNAUTHORIZED_CLIENT` / `E_CLIENT_UNSUCCESSFUL_AUTHENTICATION` (401),\n`E_MISSING_PERMISSION` (403), `E_MISSING` (404), `E_CONFLICT` (409),\n`E_VALIDATION` / `E_PEPPOL_PARTICIPANT_SMP_LOOKUP` (422),\n`E_RATE_LIMITED` (429), `E_NOT_IMPLEMENTED` (501) or\n`E_INTERNAL_PROXY_ERROR` (500)."},"data":{"type":"string","description":"Human-readable description of what went wrong."},"metadata":{"type":"object","description":"Additional detail about the failure. The shape varies by error type — a `429`\ncarries `limit` and `retryAfterSeconds`, a `409` carries the colliding\n`integrationId` — and it is omitted entirely on a `500`. Treat it as an open\nmap and read only the keys you need.","additionalProperties":true,"properties":{"debug_error_message":{"type":"string","description":"Longer explanation intended for a developer reading a log."},"debug_error_code":{"type":"integer","description":"Echoes the HTTP status code."}}}}}},"responses":{"NoContent":{"description":"No Content. The request succeeded and there is no body to return."},"Unauthorized":{"description":"Unauthorized. The API key or Bearer token is missing, malformed, or not valid\nfor the account in the URI.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UnprocessableEntity":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"type":{"type":"string"},"data":{"type":"string"},"metadata":{"type":"object","properties":{}}}}}}},"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"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"type":{"type":"string","description":"`E_INTERNAL_PROXY_ERROR`, or `E_UNKNOWN` when the failure carried no type."},"data":{"type":"string"}}}}}}}},"paths":{"/account/{accountRegNo}/webhook/{eventId}":{"get":{"tags":["Webhook API"],"summary":"Get a Delivered Webhook","description":"Fetch a delivered webhook again by its `eventId`, e.g. one your endpoint missed.\nEvery delivered body is kept for **30 days**.\n\nThe response is the body exactly as it was POSTed to your `url`, same `eventId`\nincluded, so it deduplicates against a delivery you did receive. It is not\nsigned: this request is authenticated like the rest of the API instead.\n\nThe `eventId`s of failed deliveries are listed on the document's\n`GET /transaction/{accountRegNo}/{documents}/{direction}/status`, under\n`metadata.webhooks_dispatched`, with the HTTP `status`/`statusText` your endpoint\nreturned.\n\nAn event is served only for the account it is about (`accountRegNo` in the body).\nAn unknown or expired `eventId`, or another account's, answers `204`.","operationId":"account/get-webhook-event","parameters":[{"$ref":"#/components/parameters/accountRegNo"},{"$ref":"#/components/parameters/eventId"}],"responses":{"200":{"description":"OK — the webhook body as it was delivered.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"204":{"$ref":"#/components/responses/NoContent"},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
