--- title: "Agentic Payments integration with ACP checkout flow" description: "Learn to delegate payments to Adyen from your agent platform in the ACP checkout flow." url: "https://docs.adyen.com/online-payments/agentic-commerce/agent-platform/agentic-payments-acp" source_url: "https://docs.adyen.com/online-payments/agentic-commerce/agent-platform/agentic-payments-acp.md" canonical: "https://docs.adyen.com/online-payments/agentic-commerce/agent-platform/agentic-payments-acp" last_modified: "2026-03-06T17:04:00+01:00" language: "en" --- # Agentic Payments integration with ACP checkout flow Learn to delegate payments to Adyen from your agent platform in the ACP checkout flow. [View source](/online-payments/agentic-commerce/agent-platform/agentic-payments-acp.md) Integrate with our delegated payment API when your agent platform acts a token vault during the [Agentic Commerce Protocol (ACP)](https://developers.openai.com/commerce) checkout flow, where your agent collects and tokenizes the shopper's payment details on behalf of the merchant. Adyen stores the credential and returns an ACP token that your agent passes to the merchant. The merchant uses the token to process the payment with Adyen. If you want to integrate with the [Universal Commerce Protocol](https://developers.google.com/pay/api/universal-commerce-protocol/overview) instead, refer to our [documentation on how to handle Google Pay tokens with Adyen](/payment-methods/google-pay/api-only/google-pay-token-decryption). ## Requirements | Requirement | Description | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Integration type** | Make sure that you have set up an integration that follows the [Agentic Commerce Protocol (ACP)](https://developers.openai.com/commerce). | | **User role** | Make sure that your Adyen credential (API key) has the following user role:- **Agentic Commerce**. | | **Limitations** | * Compliance: your agent platform must meet PCI DSS Level 1 compliance. * You must complete our security review to approve your platform. | | **Setup steps** | Before you begin, reach out to your Adyen Account Manager or our [Support Team](https://ca-test.adyen.com/ca/ca/contactUs/support.shtml?form=other) for the following:* Access to Delegated Payment. * Your dedicated Agentic Commerce authentication token. * Enable your Adyen merchant accounts for Agentic Commerce. | ## How it works Endpoint URL for your delegated payments: | Environment | Endpoint URL | | ----------- | --------------------------------------------------------------------------------------------------------------- | | Test | `https://pal-test.adyen.com/paltokenization/servlet/Recurring/Agentic/acp/v1/agentic_commerce/delegate_payment` | | Live | `https://pal-live.adyen.com/paltokenization/servlet/Recurring/Agentic/acp/v1/agentic_commerce/delegate_payment` | When the shopper initiates a transaction using your agent platform, the following flow occurs: 1. The shopper enters their payment details in your agent platform. 2. Your agent platform sends the payment (card number or network token) data to Adyen by making a `/agentic_commerce/delegate_payment` request. 3. Adyen validates the credentials and returns a merchant-scoped ACP token to your agent platform. 4. Your agent platform sends the ACP token to your checkout application. 5. The merchant's checkout application makes a `/payments` request including the ACP token. 6. Adyen authorizes the payment and returns the payment result to your checkout application. ```mermaid sequenceDiagram autonumber participant Shopper participant Platform as Your agent platform participant Adyen participant App as Merchant Checkout Application Shopper->>Platform: Enters payment details Platform->>Adyen: /agentic_commerce/delegate_payment Adyen-->>Platform: Merchant-scoped ACP token Platform->>App: Sends ACP token App->>Adyen: /payments (includes ACP token) Adyen-->>App: Payment result (Authorized) ``` ## Send a delegated payment request through the agent platform Make a POST `/agentic_commerce/delegate_payment` request through your agent platform, including the following: Headers: | Header | Required | Description | | ----------------- | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Authorization` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | Use the following format: `Bearer `. If you enter a standard API key, you get the 401 Unauthorized error. | | `Content-Type` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | **application/json**. | | `API-Version` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | **2025-09-29**. | | `Accept-Language` | | The preferred locale for content like messages and errors. For example: **en-US**. | | `User-Agent` | | Your platform name and version. For example: **MyPlatform/2.0**. | | `Idempotency-Key` | | A unique value, such as a universally unique identifier (UUID), to prevent duplicate transactions. If the same key is sent with the same body, the original response is returned. If sent with a different body, a 400 `idempotency_conflict` error is returned. | | `Request-Id` | | Unique trace identifier for each request. For example: **request\_id\_123**. | | `Signature` | | The Base64 HMAC-SHA256 signature of the request body. | | `Timestamp` | | The time the request as an RFC 3339 string. For example: **2025-09-25T10:30:00Z**. | Body: | Parameter name | Required | Description | | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `payment_method.type` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | **card**. | | `payment_method.card_number_type` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | The type of card number. Possible values:- **fpan** - **network\_token** - **dpan** | | `payment_method.number` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | The card number, network token, or DPAN. Must be 12–19 digits. | | `payment_method.metadata` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | Arbitrary key-value pairs. Pass an empty object `{}` if unused. | | `allowance.reason` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | **one\_time**. | | `allowance.max_amount` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | The maximum amount the payment method can be charged, in minor currency units. | | `allowance.currency` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | The three-letter [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code. For example: **USD**. | | `allowance.checkout_session_id` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | The ACP checkout session identifier that this token is bound to. | | `allowance.merchant_id` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | The Adyen merchant account code for the merchant this token charges. | | `allowance.expires_at` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | The token expiry timestamp, formatted as an ISO 8601 string. The token cannot be used after this time. | | `billing_address.name` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | The shopper's full name. | | `billing_address.line_one` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | The first line of the shopper's street address. | | `billing_address.city` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | The city of the shopper's address. | | `billing_address.state` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | The state or province of the shopper's address, following [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2). | | `billing_address.country` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | The country of the shopper's address. Two-letter [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) code. | | `billing_address.postal_code` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | The postal code of the shopper's address. | | `risk_signals[].type` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | The type of risk signal. Currently only **card\_testing** is supported. | | `risk_signals[].score` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | The numerical risk score from your platform's fraud engine. | | `risk_signals[].action` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | The recommended action. Possible values:- **authorized** - **manual\_review** - **blocked**A value of **blocked** or **manual\_review** prevents tokenization. | | `metadata` | ![Required](/user/pages/reuse/image-library/01.icons/required/required.svg?decoding=auto\&fetchpriority=auto) | Arbitrary key-value pairs for correlation at the request level. Pass an empty object `{}` if unused. | | `payment_method.exp_month` | | The card expiry month. For example: **11**. | | `payment_method.exp_year` | | The card expiry year (four digits). For example: **2030**. | | `payment_method.name` | | The cardholder name. | | `payment_method.cvc` | | The card security code (CVC/CVV). Must be 3–4 digits. | | `payment_method.cryptogram` | | The cryptogram for a network token or DPAN. Include when `card_number_type` is **network\_token** or **dpan**. | | `payment_method.eci_value` | | The Electronic Commerce Indicator. Relevant for liability shift qualification. | | `payment_method.checks_performed` | | An array of checks already performed on the card. Possible values:- **avs** - **cvv** - **ani** - **auth0** | | `payment_method.iin` | | The first six to eight digits of the card number (Issuer Identification Number). | | `payment_method.display_brand` | | The card brand for display. For example: **visa**, **mc**. | | `payment_method.display_last4` | | The last four digits of the original card number, for display to the shopper. Must be exactly 4 digits. | | `payment_method.display_card_funding_type` | | The card funding type. Possible values:- **credit** - **debit** - **prepaid** | | `payment_method.display_wallet_type` | | The digital wallet type, if the card came from a wallet. | | `payment_method.virtual` | | Set to **true** if this is a virtual card. | | `billing_address.line_two` | | The second line of the shopper's street address (apartment, suite, unit). | | `billing_address.phone_number` | | The contact phone number. | | `session_context.ip_address` | | The IP address from which the agent acts on behalf of the shopper. | | `session_context.user_agent` | | The user-agent string from the agent's session with the shopper. | | `session_context.accept_language` | | The Accept-Language header value from the shopper's session. | | `session_context.session_id` | | The session identifier of the agent's session with the shopper. | | `session_context.device_fingerprint` | | The device fingerprint from the device on which the agent acts. | ### Tab: Card number **Example request body with card number** ```bash curl -X POST https://pal-test.adyen.com/paltokenization/servlet/Recurring/Agentic/acp/v1/agentic_commerce/delegate_payment \ -H "Authorization: Bearer YOUR_AGENTIC_TOKEN" \ -H "User-Agent: MyPlatform/2.0" \ -H "Idempotency-Key: idempotency_key_123" \ -H "Request-Id: request_id_123" \ -H "Content-Type: application/json" \ -H "Signature: YOUR_SIGNATURE" \ -H "Timestamp: 2025-09-25T10:30:00Z" \ -H "API-Version: 2025-09-29" \ -H "Accept-Language: en-US" \ -d '{ "payment_method": { "type": "card", "card_number_type": "fpan", "number": "4111111111111111", "exp_month": "03", "exp_year": "2030", "name": "Jane Doe", "cvc": "737", "metadata": { "issuing_bank": "example_bank" } }, "allowance": { "reason": "one_time", "max_amount": 2500, "currency": "usd", "checkout_session_id": "cs_123", "merchant_id": "ADYEN_MERCHANT_ACCOUNT", "expires_at": "2025-10-09T07:20:50Z" }, "billing_address": { "name": "Jane Doe", "line_one": "123 Main St", "city": "San Francisco", "country": "US", "postal_code": "94105" }, "risk_signals": [ { "type": "card_testing", "score": 2, "action": "authorized" } ], "metadata": { "source": "agentic_platform", "campaign": "q4" } }' ``` ### Tab: Network token **Example request body with network token** ```bash curl -X POST https://pal-test.adyen.com/paltokenization/servlet/Recurring/Agentic/acp/v1/agentic_commerce/delegate_payment \ -H "Authorization: Bearer YOUR_AGENTIC_TOKEN" \ -H "User-Agent: MyPlatform/2.0" \ -H "Idempotency-Key: idempotency_key_123" \ -H "Request-Id: request_id_123" \ -H "Content-Type: application/json" \ -H "Signature: YOUR_SIGNATURE" \ -H "Timestamp: 2025-09-25T10:30:00Z" \ -H "API-Version: 2025-09-29" \ -H "Accept-Language: en-US" \ -d '{ "payment_method": { "type": "card", "card_number_type": "network_token", "number": "4111111111111111", "exp_month": "03", "exp_year": "2030", "name": "Jane Doe", "cryptogram":"gXc5UCLnM6ckD7pjM1TdPA==", "cvc": "737", "metadata": { "issuing_bank": "example_bank" } }, "allowance": { "reason": "one_time", "max_amount": 2500, "currency": "usd", "checkout_session_id": "cs_123", "merchant_id": "ADYEN_MERCHANT_ACCOUNT", "expires_at": "2025-10-09T07:20:50Z" }, "billing_address": { "name": "Jane Doe", "line_one": "123 Main St", "city": "San Francisco", "country": "US", "postal_code": "94105" }, "risk_signals": [ { "type": "card_testing", "score": 2, "action": "authorized" } ], "metadata": { "source": "agentic_platform", "campaign": "q4" } }' ``` 2. Get the ACP token (`id`) from the HTTP 201 Created response.[]() The response includes the following: | Parameter | Type | Description | | ------------ | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | String | The ACP token identifier. This is Adyen's Recurring Detail Reference. Pass this as `paymentMethod.storedPaymentMethodId` in the POST `/payments` request. | | `created` | String (ISO 8601) | The timestamp when the token was created. | | `created_at` | String (ISO 8601) | Alias for `created`. Same value. | | `metadata` | Object | Correlation metadata. Contains `recurringDetailReference`, `source`, `merchant_id`, and `shopperReference`. | **Example HTTP 201 Created response** ```json { "id": "FKSPNCQ8HXSKGK82", "created": "2026-02-23T23:50:55.482694934+01:00", "created_at": "2026-02-23T23:50:55.482694934+01:00", "metadata": { "recurringDetailReference": "FKSPNCQ8HXSKGK82", "source": "agent_checkout", "merchant_id": "ADYEN_MERCHANT_ACCOUNT", "shopperReference": "CHECKOUT_SESSION_ID" } } ``` The ACP token: * Is merchant-scoped and bound to a single merchant account (`allowance.merchant_id`) and checkout session (`allowance.checkout_session_id`). * Cannot be used across unauthorized merchant accounts, for a different session, or for an amount that exceeds `allowance.max_amount`. * Does not expose raw card data. ## The merchant makes a payment request with the ACP token The merchant makes a a POST [/payments](https://docs.adyen.com/api-explorer/Checkout/latest/post/payments) request through their checkout application, including: | Parameter name | Description | | ------------------------------------- | --------------------------------------------------------------------------------------------------------------- | | `shopperReference` | The `checkout_session_id` value from the response in the `/checkout_session` response from your agent platform. | | `paymentMethod.storedPaymentMethodId` | The [ACP token from the agent platform](#acp_response). | | `merchantAccount` | Your merchant account. | | `amount.value` | The value of the payment, in minor units. | | `amount.currency` | The three-character ISO currency code. | | `shopperInteraction` | **ContAuth** | | `recurringProcessingModel` | **UnscheduledCardOnFile** | | `reference` | Your reference for the order. | **Example payment request including the ACP** ```bash curl https://checkout-test.adyen.com/v72/payments \ -H 'x-api-key: ADYEN_API_KEY' \ -H "idempotency-key: YOUR_IDEMPOTENCY_KEY" \ -H 'content-type: application/json' \ -d '{ "shopperReference" : "csn_01AB2A3XYZ9ABC", "paymentMethod" : { "storedPaymentMethodId" : "FKSPNCQ8HXSKGK82" }, "merchantAccount" : "ADYEN_MERCHANT_ACCOUNT", "amount" : { "currency" : "USD", "value" : "2500" }, "shopperInteraction" : "ContAuth", "recurringProcessingModel" : "UnscheduledCardOnFile", "reference": "your-order-reference-123-abc" }' ``` The response include the following: | Parameter | Description | | -------------- | -------------------------------------------- | | `pspReference` | Our unique identifier for the transaction. | | `resultCode` | Indicates the current status of the payment. | **Example response for an authorized payment** ```json { "pspReference": "W78NTVXSJV84L675", "resultCode": "Authorised" } ``` ## Test and go live Use the test environment to verify your integration end-to-end before going live. Test endpoint: `https://pal-test.adyen.com/paltokenization/servlet/Recurring/Agentic/acp/v1/agentic_commerce/delegate_payment` ### Test checklist To verify your integration, confirm the following: 1. Your API key holds the Agentic Commerce role. 2. A well-formed request with only required fields returns HTTP 201. 3. A full request with all optional fields populated returns HTTP 201. 4. A request with `card_number_type`: **network\_token** and a `cryptogram` is handled correctly. 5. A request with `card_number_type`: **dpan** and a `cryptogram` is handled correctly. 6. Omitting `payment_method.number` returns HTTP 400 with `code`: **invalid\_card** and `param`: **payment\_method.number**. 7. An unknown `allowance.merchant_id` returns HTTP 400 with `code`: **invalid\_card** and `param`: **allowance.merchant\_id**. 8. A malformed `allowance.expires_at` returns HTTP 400 with `code`: **invalid\_card** and `param`: **allowance.expires\_at**. 9. A request with `risk_signals[].action`: **blocked** rejects tokenization. 10. The same request sent twice with the same `Idempotency-Key` returns HTTP 201 with the same `id`. 11. The same `Idempotency-Key` sent with a different body returns HTTP 400 with `code`: **idempotency\_conflict**. 12. The returned `id` used in a POST `/payments` request to the test endpoint returns an **Authorised** result. ### Go live When you are ready to go live, use the live endpoint URL: `https://pal-live.adyen.com/paltokenization/servlet/Recurring/Agentic/acp/v1/agentic_commerce/delegate_payment` ## Possible HTTP status codes | HTTP | Type | Description | | ---- | --------------------- | ------------------------------------------------------------------------------------------------- | | 201 | — | Token created. Use `id` as `paymentMethod.storedPaymentMethodId` in the POST `/payments` request. | | 400 | `invalid_request` | Validation failure. Inspect `type`, `code`, and `param`. Do not retry without fixing the request. | | 500 | `processing_error` | Unexpected Adyen-side error. Retry once after a short delay. | | 503 | `service_unavailable` | Upstream dependency temporarily down. Retry with exponential backoff. | ## Errors All error responses share the same JSON schema: | Field | Type | Always present | Description | | --------- | ------ | -------------- | ------------------------------------------------------------------- | | `type` | String | Yes | The error category. Determines your handling strategy. | | `code` | String | Yes | Machine-readable code with specific detail. | | `message` | String | Yes | Human-readable description of the error. | | `param` | String | No | JSONPath of the offending field. Only present on validation errors. | ### Error types | Type | Handling | | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `invalid_request` | The request body failed validation or contains invalid data. Check the `param` field for the offending path. Fix the request before retrying. | | `rate_limit_exceeded` | Your platform exceeded the allowed request rate. Retry with exponential backoff. | | `processing_error` | An unexpected internal error on Adyen's side. Retry once after a short delay. If the error persists, contact Adyen support. | | `service_unavailable` | An internal dependency is temporarily unavailable. Retry with exponential backoff. If unavailability persists beyond a few minutes, surface an error to the shopper. | ### Error codes | Code | Type | When it occurs | | ---------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `invalid_card` | `invalid_request` | A required field is missing, has an invalid format, or `allowance.merchant_id` cannot be resolved. The `param` field identifies the specific path. | | `duplicate_request` | `invalid_request` | The `Idempotency-Key` was already used for a successful request with the same body. The original 201 response is returned. Treat this as a successful idempotent replay. | | `idempotency_conflict` | `invalid_request` | The `Idempotency-Key` was reused but the request body differs from the original. Generate a new `Idempotency-Key` for the new request. |