Skip to main content
Once your ACP endpoints pass validation in staging, the final step is connecting real-time event handling and verifying your integration is resilient under production load. This guide covers webhook setup for Stripe (and Razorpay for India), the idempotency middleware pattern that prevents duplicate orders on retries, and a six-step checklist for going live safely.

Required endpoints

Your ACP integration needs exactly three endpoints. These map directly to the initiate_checkout and confirm_purchase tool calls in ChatGPT.
EndpointMethodDescription
/acp/checkout/createPOSTCreate or open a checkout session
/acp/checkout/:id/updatePATCHUpdate cart or session — shipping, items
/acp/checkout/:id/completePOSTComplete the purchase and return confirmation
See ACP tool endpoints reference for the full request and response schemas.

Webhooks

Configure webhooks so your backend receives real-time events from your PSP after payment completes or fails. Relying only on the synchronous /complete response is not sufficient — network failures can leave order state inconsistent.

Stripe

// Stripe webhook handler
app.post('/webhooks/stripe', express.raw({ type: 'application/json' }), async (req, res) => {
  const sig = req.headers['stripe-signature']
  const event = stripe.webhooks.constructEvent(req.body, sig, process.env.STRIPE_WEBHOOK_SECRET)

  switch (event.type) {
    case 'payment_intent.succeeded':
      await fulfillOrder(event.data.object.metadata.order_id)
      break
    case 'payment_intent.payment_failed':
      await markOrderFailed(event.data.object.metadata.order_id)
      break
  }

  res.json({ received: true })
})
Always verify the Stripe signature before processing an event. Use stripe.webhooks.constructEvent — never trust the raw request body alone.

Razorpay (India)

For Indian merchants using Razorpay, subscribe to equivalent payment events in the Razorpay Dashboard and verify the X-Razorpay-Signature header on each webhook delivery using your webhook secret.

Events to handle

EventAction
payment_intent.succeededFulfill the order; update status to confirmed
payment_intent.payment_failedMark the order failed; allow retry
charge.dispute.createdFlag the order for review

Idempotency

Idempotency is critical for ACP. If a network timeout causes an agent to retry a request, your server must return the same response instead of creating a duplicate order or charging the card twice. The middleware pattern below intercepts the response, caches it against the idempotency key in Redis, and returns the cached response on any repeat request.
// Middleware to handle idempotency
async function idempotencyMiddleware(req, res, next) {
  const key = req.headers['idempotency-key'] || req.body.idempotency_key

  if (!key) return next() // not required on updates

  const cached = await redis.get(`idem:${key}`)
  if (cached) {
    return res.json(JSON.parse(cached)) // return cached response
  }

  // Capture response before sending
  const originalJson = res.json.bind(res)
  res.json = (body) => {
    redis.setex(`idem:${key}`, 3600, JSON.stringify(body)) // cache for 1 hour
    return originalJson(body)
  }

  next()
}

app.post('/acp/checkout/complete', idempotencyMiddleware, async (req, res) => {
  // ... complete checkout
})
Apply idempotency middleware to both /create and /complete. Missing it on either endpoint can result in duplicate sessions or duplicate charges when agents retry on timeout.

Production go-live checklist

1

Staging validation

Run the full checkout flow in staging using Stripe test tokens:
  • tok_visa — successful payment
  • tok_chargeDeclined — payment declined
  • tok_cvcCheckFail — CVC failure
Validate all state transitions and error responses before touching production credentials.
2

Load testing

Confirm your endpoints handle concurrent checkout requests without race conditions. Pay particular attention to inventory depletion — two agents must not be able to purchase the last unit simultaneously.
# Run 50 concurrent checkout creates
ab -n 200 -c 50 -T application/json \
  -p checkout_payload.json \
  https://yourstore.com/acp/checkout/create
3

Webhook verification

Verify all Stripe webhook events are received and processed correctly in staging before switching to production. Use the Stripe CLI to replay events locally:
stripe listen --forward-to localhost:3000/webhooks/stripe
stripe trigger payment_intent.succeeded
4

Register with OpenAI

Register your ACP tool definitions in the OpenAI platform when using GPT Actions, or pass them dynamically through the function calling API. Test the full conversation flow in ChatGPT’s sandbox environment before enabling for end users.
5

Run Asva validation

Use the ACP Validator for an automated check of all endpoint schemas and response shapes.
curl -X POST https://asva-ai.com/api/audit \
  -H "Authorization: Bearer $ASVA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain": "yourstore.com", "checks": ["acp"]}'
6

Go live

Switch to your PSP’s production credentials, deploy, and monitor these signals from day one:
  • Order success rate — target above 95%
  • Checkout session expiry rate — flag if above 5%
  • Payment failure rate — investigate if above 10%
  • Webhook delivery success rate — target 100%

Monitoring

Set up alerts for the following signals. These are the earliest indicators of a degraded ACP integration.
  • Checkout completion rate dropping below 90%
  • P95 checkout completion latency exceeding 5 seconds
  • Webhook delivery failures
  • Payment failure rate spikes