Guide to Autosana Webhooks: Features and Best Practices
Autosana webhooks tell your systems when a batch of AI-driven test runs has finished. Autosana runs end-to-end flows against mobile and web app builds, and a webhook is how the pass or fail result reaches your CI pipeline, release dashboard or team chat as soon as the batch completes.
This guide covers how to add an Autosana webhook, what the payload contains, how to verify the signature, and what Autosana's documentation leaves out.
What are Autosana webhooks?
An Autosana webhook is an HTTPS URL you add in Autosana's settings. When Autosana finishes a batch of flow runs, it sends an HTTP POST with a JSON summary of the results to that URL. There is one kind of notification, so there are no events to choose from.
Signing is optional. If you set a signing secret on the webhook, Autosana adds an X-Autosana-Signature-256 header holding sha256= and the hex HMAC-SHA256 of the raw body. Without a secret, deliveries are unsigned.
Autosana webhook features
| Feature | Details |
|---|---|
| Configuration | Settings > Integrations > Webhooks |
| Endpoint URL | HTTPS only |
| Notification | batch.completed, sent when a batch of flow runs completes |
| Signature header | X-Autosana-Signature-256, only when a signing secret is set |
| Scheme | HMAC-SHA256, lowercase hex, prefixed with sha256= |
| Signed content | The raw request body only |
| Secret | A signing secret you choose when adding the webhook |
| Testing | A Test button sends a test delivery |
| Source IPs | The flow_ IPs from Autosana's network allowlist |
Autosana doesn't document a success status code, a response timeout, a retry policy or a delivery ID.
The batch.completed payload
Here is Autosana's example, with the build URL shortened:
{
"event": "batch.completed",
"timestamp": "2025-01-31T12:34:56.789Z",
"app": {
"id": "com.example.myapp",
"bundle_id": "com.example.myapp",
"name": "My App",
"platform": "android",
"url": "https://.../my_app.apk"
},
"git": {
"commit_sha": "a1b2c3d4e5f6g7h8i9j0",
"branch": "main"
},
"summary": {
"total_groups": 3,
"passed_groups": 2,
"failed_groups": 1
},
"run_groups": [
{
"name": "Login Suite",
"status": "passed",
"url": "https://autosana.ai/runs/groups/f1e2d3c4-b5a6-7890-abcd-ef1234567890",
"runs": [
{
"name": "User can sign in with email",
"status": "passed",
"url": "https://autosana.ai/runs/flow/12345678-abcd-ef12-3456-7890abcdef12"
}
]
}
]
}
summarygives the pass and fail counts across run groups, which is usually all a CI gate needs.run_groupslists each group with itsstatus, a link to the results, and its individualruns.gitis included only when the build has git metadata, for example when it was uploaded from CI with commit information. Usegit.commit_shato match the result to a pipeline.appidentifies the build and itsplatform.
Setting up Autosana webhooks
- Go to Settings > Integrations > Webhooks in Autosana and click Add Webhook.
- Enter your HTTPS endpoint URL.
- Add a signing secret. Generate a long random value, for example with
openssl rand -hex 32, and store it server-side asAUTOSANA_WEBHOOK_SECRET. - Use the Test button to send a test delivery.
If your endpoint sits behind a firewall, allowlist the flow_ IPs from Autosana's network allowlist. Results webhooks come from those IPs for every platform, including mobile. The Test button is the exception: it sends from Autosana's API, which isn't on that list.
If you use Hookdeck, create a source with the Autosana source type and paste the same signing secret into it, then use the Hookdeck source URL as the webhook URL. You must set a signing secret on the Autosana webhook. Without one, deliveries are unsigned and fail verification in Hookdeck.
Securing Autosana webhooks
Read X-Autosana-Signature-256, check that it starts with sha256=, and take the rest. Compute the hex HMAC-SHA256 of the raw request body with your secret as the key, and compare the two in constant time. If you configured a secret, reject requests that don't carry the header.
const crypto = require('crypto');
const express = require('express');
function verifyAutosanaSignature(rawBody, signatureHeader, secret) {
if (!signatureHeader || !secret || !signatureHeader.startsWith('sha256=')) return false;
const received = Buffer.from(signatureHeader.slice('sha256='.length).toLowerCase(), 'utf8');
const expected = Buffer.from(
crypto.createHmac('sha256', secret).update(rawBody).digest('hex'),
'utf8'
);
return received.length === expected.length && crypto.timingSafeEqual(received, expected);
}
const app = express();
app.post('/webhooks/autosana', express.raw({ type: '*/*' }), (req, res) => {
if (!verifyAutosanaSignature(req.body, req.get('x-autosana-signature-256'), process.env.AUTOSANA_WEBHOOK_SECRET)) {
return res.sendStatus(401);
}
const event = JSON.parse(req.body.toString('utf8'));
// event.summary.failed_groups > 0 means at least one run group failed.
res.sendStatus(200);
});
The same check in Python:
import hashlib
import hmac
def verify_autosana_signature(raw_body: bytes, signature_header, secret: str) -> bool:
if not signature_header or not secret or not signature_header.startswith("sha256="):
return False
received = signature_header[len("sha256="):].lower()
expected = hmac.new(secret.encode("utf-8"), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(received.encode("utf-8"), expected.encode("utf-8"))
# In FastAPI: raw_body = await request.body()
# verify_autosana_signature(raw_body, request.headers.get("x-autosana-signature-256"),
# os.environ["AUTOSANA_WEBHOOK_SECRET"])
Autosana's own JavaScript sample passes the header and computed value straight to crypto.timingSafeEqual, which throws when their lengths differ. The length check above avoids that. Only the body is signed and there is no timestamp header, so there is no replay window to check.
Make Autosana webhooks production-ready. Hookdeck Event Gateway verifies the
X-Autosana-Signature-256header on every delivery, keeps a record of each test batch result, and retries delivery to your CI or notification service if it is briefly unavailable.
Autosana webhook limitations and pain points
Unsigned unless you set a secret
The Problem: Anyone who finds your endpoint URL can post a fake "all passed" result.
Why It Happens: The signing secret is optional when you add the webhook, and without it Autosana sends no signature header.
Workarounds:
- Always set a signing secret, and treat a missing header as a failed check.
- If an existing webhook has no secret, replace it with one that has.
How Hookdeck Can Help: Hookdeck's Autosana source verifies the header on every request and marks unsigned ones as failed verification, so you can see when a webhook was set up without a secret.
No documented retries
The Problem: A test result disappears if your endpoint is down when the batch finishes.
Why It Happens: Autosana documents no retry policy, timeout or success code, so you can't count on a failed delivery being sent again.
Workarounds:
- Keep the receiver simple and highly available, and return
200as soon as the request is verified. - Link back to Autosana from your pipeline, so someone can check the run page if a result never arrives.
How Hookdeck Can Help: Hookdeck accepts the delivery as soon as it arrives and then delivers to your service with retries you configure, so a short outage on your side doesn't lose the result.
No delivery ID
The Problem: If the same result arrives twice, your pipeline acts on it twice.
Why It Happens: The payload has no event or delivery ID.
Workarounds:
- Build a key from fields in the body, such as
git.commit_shawithtimestamp, and skip repeats.
How Hookdeck Can Help: Hookdeck's deduplication can drop repeats based on the body fields you choose.
Best practices
Verify against the raw body
Use express.raw({ type: '*/*' }) in Express, await request.text() in Next.js and await request.body() in FastAPI. Parse only after the signature check passes.
Gate on summary, link to run_groups
Use summary.failed_groups to decide pass or fail, and post the failing groups' url values where your team will see them.
Send git metadata from CI
git appears only when the build carries git metadata. Upload builds from CI with commit information, so each result can be tied to a commit.
Acknowledge fast and process asynchronously
Verify, store the result, return 200, and update the pipeline or post notifications afterwards. See why to process webhooks asynchronously.
Conclusion
Autosana sends one batch.completed notification per finished batch of flow runs, signed with X-Autosana-Signature-256 only when you set a signing secret. Set the secret, verify the sha256= hex HMAC against the raw body, use summary for your pass or fail decision, and plan for the absence of documented retries.
Hookdeck Event Gateway verifies every Autosana signature and holds each result until your service has handled it, so a brief outage doesn't drop a test run.
Get started with Hookdeck for free and handle Autosana webhooks reliably in minutes.