Docs/Agentic Commerce (ACP)/Agentic Commerce (ACP)

    Webhooks

    Last updated · MAR 2026·Read as Markdown

    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.

    1. Log into app.avcodex.com and navigate to your agent.
    2. Go to Publish > Catalog.
    3. Find your API key in the API Keys section.
    4. 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.
    EventTrigger
    order.createdAn order was created from a completed checkout (manual fulfillment).
    order.fulfilledAn 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.

    json
    {
      "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#

    FieldTypeDescription
    eventstringThe event type (see table above).
    order_idstring (UUID)Unique order identifier.
    checkout_session_idstring (UUID)The checkout session that created this order.
    application_idstring (UUID)The agent this order belongs to.
    statusstringCurrent order status.
    fulfillment_resultarray or nullResults from automatic fulfillment (tool execution).
    total.amountintegerOrder total in currency minor units.
    total.currencystringISO currency code.
    created_atstring (ISO 8601)When the order was created.

    Every webhook request includes these headers:

    HeaderDescription
    Content-Typeapplication/json.
    X-ACP-EventThe event type (e.g., order.fulfilled).
    X-ACP-TimestampUnix timestamp (seconds) when the webhook was sent.
    X-ACP-SignatureHMAC-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#

    javascript
    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#

    python
    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 (like timingSafeEqual or hmac.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 2xx HTTP 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 200 response 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_id to deduplicate.
    • Verify signatures. Always verify the X-ACP-Signature header before processing the payload.
    • Use HTTPS. Webhook URLs must use HTTPS to protect payload contents in transit.

    *AVCodex · Your AV expertise. Amplified by AI.*

    Was this helpful?
    Edit this page →