Agentic Commerce

Webhooks

Receive real-time notifications when orders are created and fulfilled

| View as Markdown
1 min read
# acp # agentic-commerce # webhooks # orders # fulfillment # hmac # signature

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.

Setting Up Webhooks

  1. Log into build.chipp.ai and navigate to your app
  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
ℹ️

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 Types

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.

Webhook Payload

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": "analyze_data", "success": true, "output": "Analysis complete" }
  ],
  "total": {
    "amount": 2500,
    "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 application 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

Webhook Headers

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

Signature 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)
ℹ️

Always use constant-time comparison (like timingSafeEqual or hmac.compare_digest) when verifying signatures to prevent timing attacks.

Delivery Behavior

  • Timeout: Each delivery attempt has a 10-second timeout
  • Retries: Up to 3 delivery attempts (1 initial + 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

Best Practices

  • 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.