webhook.url on a task and querying.ai POSTs the result there when the task reaches COMPLETED or FAILED.
Delivery payload
Each delivery is aPOST with Content-Type: application/json and this body:
For example, a completed Perplexity task (Perplexity costs 1 credit):
include.citationAnalysis, the answer’s webhook waits until the attached analysis finishes, so you get both in one delivery. See Citation Analysis.
Verify the signature
Tasks submitted with an API key are signed with that key. Each delivery carries three headers:
The HMAC key is the 32-byte SHA-256 digest of the API key that submitted the task (for a batch, the key that created the batch). Compute the signature over the raw body before you parse it, compare in constant time, and accept timestamps within five minutes:
Retries
Return any2xx within 30 seconds to acknowledge. Any other status, a timeout or a connection error is a failed attempt. Failed deliveries are retried after 2, 4, 8 and 16 minutes: five attempts in all over about 30 minutes, each with the same querying-webhook-id. After the fifth failure the delivery is abandoned.
Redirects are not followed: a 3xx counts as a failed attempt.
Delivery runs separately from the task. A task whose webhook never arrives still shows COMPLETED on GET /v1/async/task/{id}. To recover, poll within the 24-hour window described in Async tasks.
URL rules
webhook.url is checked at submit. A URL that breaks a rule is rejected with 400 VALIDATION_ERROR on the webhook.url field.
At delivery time the host must resolve only to public addresses, or the attempt fails. The connection goes to the address that was checked.
Write a safe handler
1
Verify, then acknowledge fast
Check the signature, store the payload durably, and return
200. Parse and write to your database afterwards, so a slow handler does not hit the 30-second timeout and cause a retry.2
Deduplicate
Delivery is at least once. Skip a message whose
querying-webhook-id you have already processed, or match on task.idempotencyKey and make the write idempotent.3
Branch on status
Check
task.status explicitly. A failed task also delivers a webhook, with response.error.Batch completion event
A batch created withPOST /v1/batches and a webhook.url sends each task’s result to that URL as above, then posts one completion event when every item has finished:
querying-webhook-id is batch_<batch id>, and it follows the same retry schedule.
Next steps
Async tasks
Statuses, polling and retention.
Batches and grids
One webhook URL for thousands of tasks.