> ## Documentation Index
> Fetch the complete documentation index at: https://docs.asva-ai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ACP End-to-End Implementation: State Machine and Checklist

> Step-by-step ACP implementation covering the checkout state machine, idempotency, error patterns, and a go-live validation checklist.

ACP checkout is not a single request — it is a state machine with three phases (create, update, complete) that your backend must enforce. This guide walks you through each implementation step in order, from the first endpoint to a production-ready integration, and provides a validation checklist you can use before going live.

## Prerequisites

Confirm you have everything in place before writing any code:

* [ ] Checkout API endpoints you control, or the ability to build them
* [ ] Payment method handling — Stripe is recommended; Razorpay for India
* [ ] A product catalog API
* [ ] Idempotency key handling (cache or storage layer for deduplication)

## The ACP checkout state machine

Your backend must enforce the transitions below. Do not allow a session to move to any state not shown in this diagram.

```
               ┌─────────────────┐
               │     created      │  POST /acp/checkout/create
               └────────┬────────┘
                        │
               ┌────────▼────────┐
               │ pending_confirm  │  PATCH /acp/checkout/:id/update
               └────────┬────────┘
                        │
           ┌────────────┼────────────┐
           │            │            │
    ┌──────▼─────┐ ┌───▼──────┐ ┌──▼──────────┐
    │  confirmed  │ │  failed  │ │   expired   │
    └─────────────┘ └──────────┘ └─────────────┘
```

**State transition rules:**

* `created` → `pending_confirmation` automatically on successful cart creation
* `pending_confirmation` → `confirmed` when payment succeeds
* `pending_confirmation` → `failed` on payment failure (retryable)
* `pending_confirmation` → `expired` when `expires_at` passes
* `confirmed` and `expired` are terminal — no further transitions are allowed

## Implementation steps

<Steps>
  <Step title="Implement tool definitions">
    Define the three ACP tools (`search_products`, `initiate_checkout`, `confirm_purchase`) as JSON schema objects. These register with ChatGPT through the OpenAI function calling API.

    See [Implement ACP: ChatGPT Instant Checkout](/acp/getting-started) for the full tool definitions and endpoint code.
  </Step>

  <Step title="Build checkout endpoints">
    Implement `POST /acp/checkout/create`, `PATCH /acp/checkout/:id/update`, and `POST /acp/checkout/:id/complete`.

    Key requirements for each endpoint:

    * Sessions must expire — use a 15-minute default
    * Apply idempotency keys on create and complete
    * Re-validate inventory at completion time, not just at creation

    See [ACP tool endpoints reference](/acp/endpoints) for the full request and response schemas.
  </Step>

  <Step title="Add payment processing">
    Integrate your PSP on the `/complete` endpoint. For Stripe, pass the idempotency key through to the payment intent so retries do not create duplicate charges:

    ```javascript theme={null}
    const payment = await stripe.paymentIntents.create({
      amount: checkout.total_cents,
      currency: 'usd',
      payment_method: paymentToken,
      confirm: true,
      idempotency_key: `pi_${idempotencyKey}`
    })
    ```

    Catch `CardError` and return a `payment_declined` response so the agent can relay a clear message to the user.
  </Step>

  <Step title="Implement error responses">
    Every failure case must return a structured JSON error object with a machine-readable `code` and a human-readable `message`. The agent surfaces your `message` text directly in the conversation.

    See [ACP instant checkout UX patterns](/acp/instant-checkout) for the full error taxonomy and response shapes.
  </Step>

  <Step title="Add consent and confirmation logic">
    Before calling `confirm_purchase`, the agent must show the user a purchase summary and receive an explicit affirmative response. Your backend cannot enforce this — it is the agent's responsibility. However, your UI must not trigger payment without a clear user confirmation signal.
  </Step>

  <Step title="Test all states">
    Test the full state machine including edge cases: expired sessions, out-of-stock at confirmation time, declined payments, and duplicate requests with idempotency keys.

    Run automated endpoint validation with the [ACP Validator](https://asva-ai.com/tools/acp-validator).
  </Step>
</Steps>

## Validation checklist

Use this checklist before enabling ACP in production.

| Check                 | Requirement                                                     |
| --------------------- | --------------------------------------------------------------- |
| Endpoint availability | All three endpoints respond with correct schemas                |
| State transitions     | State machine transitions are deterministic                     |
| Idempotency           | Duplicate requests with the same key return the same response   |
| Session expiry        | Sessions expire after `expires_at`; expired sessions return 410 |
| Error shapes          | All errors include `code` and `message`                         |
| Payment integration   | PSP is integrated; test tokens work in staging                  |
| Latency               | Create \< 3 s, Update \< 1 s, Complete \< 5 s                   |
| Consent               | Purchase summary is surfaced to the user before confirmation    |

## Test commands

Run these `curl` commands against your staging environment to verify each endpoint.

```bash theme={null}
# Test checkout creation
curl -X POST https://yourstore.com/acp/checkout/create \
  -H "Content-Type: application/json" \
  -d '{"items":[{"product_id":"prod_123","quantity":1}],"idempotency_key":"test_001"}'

# Test checkout completion with a Stripe test token
curl -X POST https://yourstore.com/acp/checkout/chk_abc/complete \
  -H "Content-Type: application/json" \
  -d '{"payment_method":{"type":"card","token":"tok_visa"},"idempotency_key":"test_confirm_001"}'

# Test idempotency — same key must return the same result
curl -X POST https://yourstore.com/acp/checkout/create \
  -H "Content-Type: application/json" \
  -d '{"items":[{"product_id":"prod_123","quantity":1}],"idempotency_key":"test_001"}'
```

<Note>
  The idempotency test (third command above) should return an identical response to the first request — same `checkout_id`, same `status`. If it creates a new session, your idempotency layer is not working correctly.
</Note>

## Related

<CardGroup cols={2}>
  <Card title="ACP checkout: webhooks and going live" icon="shopping-cart" href="/acp/checkout-guide">
    Webhooks, idempotency middleware, and production go-live checklist.
  </Card>

  <Card title="ACP vs UCP" icon="scale-balanced" href="https://asva-ai.com/ucp-vs-acp">
    When to implement each protocol.
  </Card>
</CardGroup>
