ACP webhooks notify your systems when order events occur. When a checkout completes, a signed HTTP POST is sent to your configured webhook URL with the order details. Useful for syncing ACP orders into your PM tool, your CRM, or your dispatch board.
- Log into app.avcodex.com and navigate to your agent.
- Go to Publish > Catalog.
- Find your API key in the API Keys section.
- Click to configure the webhook URL and secret.
Each API key has its own webhook configuration. You can set:
- Webhook URL - the HTTPS endpoint that receives events.
- Webhook Secret - a secret string used to sign payloads for verification.
Note: Webhook URLs must be publicly accessible HTTPS endpoints. The webhook secret is used to generate HMAC-SHA256 signatures so you can verify that requests are authentic.
| Event | Trigger |
|---|---|
order.created |
An order was created from a completed checkout (manual fulfillment). |
order.fulfilled |
An order was automatically fulfilled (tool execution succeeded). |
When a checkout with automatic fulfillment products completes, the event type will be order.fulfilled. For manual fulfillment products, the event type will be order.created.
{
"event": "order.fulfilled",
"order_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"checkout_session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"application_id": "d4e5f6a7-b8c9-0123-def0-123456789abc",
"status": "fulfilled",
"fulfillment_result": [
{ "toolName": "generate_audit_report", "success": true, "output": "Audit complete" }
],
"total": {
"amount": 25000,
"currency": "usd"
},
"created_at": "2025-01-15T12:05:00.000Z"
}
Payload fields#
| Field | Type | Description |
|---|---|---|
event |
string | The event type (see table above). |
order_id |
string (UUID) | Unique order identifier. |
checkout_session_id |
string (UUID) | The checkout session that created this order. |
application_id |
string (UUID) | The agent this order belongs to. |
status |
string | Current order status. |
fulfillment_result |
array or null | Results from automatic fulfillment (tool execution). |
total.amount |
integer | Order total in currency minor units. |
total.currency |
string | ISO currency code. |
created_at |
string (ISO 8601) | When the order was created. |
Every webhook request includes these headers:
| Header | Description |
|---|---|
Content-Type |
application/json. |
X-ACP-Event |
The event type (e.g., order.fulfilled). |
X-ACP-Timestamp |
Unix timestamp (seconds) when the webhook was sent. |
X-ACP-Signature |
HMAC-SHA256 signature for payload verification. |
Verify webhook authenticity by computing the HMAC-SHA256 signature and comparing it to the X-ACP-Signature header.
The signature is computed over the string {timestamp}.{body}, where {timestamp} is the X-ACP-Timestamp header value and {body} is the raw JSON request body.
Node.js example#
import crypto from "crypto";
function verifyWebhook(req, webhookSecret) {
const signature = req.headers["x-acp-signature"];
const timestamp = req.headers["x-acp-timestamp"];
const body = req.body; // raw string, not parsed JSON
const expected = crypto
.createHmac("sha256", webhookSecret)
.update(`${timestamp}.${body}`)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature, "hex"),
Buffer.from(expected, "hex")
);
}
Python example#
import hmac
import hashlib
def verify_webhook(headers, body, webhook_secret):
signature = headers["X-ACP-Signature"]
timestamp = headers["X-ACP-Timestamp"]
expected = hmac.new(
webhook_secret.encode(),
f"{timestamp}.{body}".encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
Note: Always use constant-time comparison (liketimingSafeEqualorhmac.compare_digest) when verifying signatures to prevent timing attacks.
- Timeout: each delivery attempt has a 10-second timeout.
- Retries: up to 3 delivery attempts (1 initial plus 2 retries) with exponential backoff (1s, 2s delays).
- Success: a
2xxHTTP response from your endpoint is considered successful delivery. - Failure: after all retries fail, the error is recorded on the order. You can check the order status via the API.
- Respond quickly. Return a
200response as soon as you receive the webhook. Process the payload asynchronously if needed. - Handle duplicates. Webhooks may be delivered more than once. Use the
order_idto deduplicate. - Verify signatures. Always verify the
X-ACP-Signatureheader before processing the payload. - Use HTTPS. Webhook URLs must use HTTPS to protect payload contents in transit.
*AVCodex · Your AV expertise. Amplified by AI.*