Integrate with our delegated payment API when your agent platform acts a token vault during the Agentic Commerce Protocol (ACP) 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 instead, refer to our documentation on how to handle Google Pay tokens with Adyen.
Requirements
| Requirement | Description |
|---|---|
| Integration type | Make sure that you have set up an integration that follows the Agentic Commerce Protocol (ACP). |
| User role | Make sure that your Adyen credential (API key) has the following user role:
|
| Limitations |
|
| Setup steps | Before you begin, reach out to your Adyen Account Manager or our Support Team for the following:
|
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:
- The shopper enters their payment details in your agent platform.
- Your agent platform sends the payment (card number or network token) data to Adyen by making a
/agentic_commerce/delegate_paymentrequest. - Adyen validates the credentials and returns a merchant-scoped ACP token to your agent platform.
- Your agent platform sends the ACP token to your checkout application.
- The merchant's checkout application makes a
/paymentsrequest including the ACP token. - Adyen authorizes the payment and returns the payment result to your checkout application.
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 |
Use the following format: Bearer <YOUR_AGENTIC_TOKEN>. If you enter a standard API key, you get the 401 Unauthorized error. |
|
Content-Type |
application/json. | |
API-Version |
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 |
card. | |
payment_method.card_number_type |
The type of card number. Possible values:
|
|
payment_method.number |
The card number, network token, or DPAN. Must be 12–19 digits. | |
payment_method.metadata |
Arbitrary key-value pairs. Pass an empty object {} if unused. |
|
allowance.reason |
one_time. | |
allowance.max_amount |
The maximum amount the payment method can be charged, in minor currency units. | |
allowance.currency |
The three-letter ISO 4217 currency code. For example: USD. | |
allowance.checkout_session_id |
The ACP checkout session identifier that this token is bound to. | |
allowance.merchant_id |
The Adyen merchant account code for the merchant this token charges. | |
allowance.expires_at |
The token expiry timestamp, formatted as an ISO 8601 string. The token cannot be used after this time. | |
billing_address.name |
The shopper's full name. | |
billing_address.line_one |
The first line of the shopper's street address. | |
billing_address.city |
The city of the shopper's address. | |
billing_address.state |
The state or province of the shopper's address, following ISO 3166-2. | |
billing_address.country |
The country of the shopper's address. Two-letter ISO 3166-1 alpha-2 code. | |
billing_address.postal_code |
The postal code of the shopper's address. | |
risk_signals[].type |
The type of risk signal. Currently only card_testing is supported. | |
risk_signals[].score |
The numerical risk score from your platform's fraud engine. | |
risk_signals[].action |
The recommended action. Possible values:
|
|
metadata |
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:
|
|
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:
|
|
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. |
-
Get the ACP token (
id) from the HTTP 201 Created response.The response includes the following:
Parameter Type Description idString The ACP token identifier. This is Adyen's Recurring Detail Reference. Pass this as paymentMethod.storedPaymentMethodIdin the POST/paymentsrequest.createdString (ISO 8601) The timestamp when the token was created. created_atString (ISO 8601) Alias for created. Same value.metadataObject Correlation metadata. Contains recurringDetailReference,source,merchant_id, andshopperReference.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.
- Is merchant-scoped and bound to a single merchant account (
The merchant makes a payment request with the ACP token
The merchant makes a a 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. |
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. |
The response include the following:
| Parameter | Description |
|---|---|
pspReference |
Our unique identifier for the transaction. |
resultCode |
Indicates the current status of the payment. |
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:
- Your API key holds the Agentic Commerce role.
- A well-formed request with only required fields returns HTTP 201.
- A full request with all optional fields populated returns HTTP 201.
- A request with
card_number_type: network_token and acryptogramis handled correctly. - A request with
card_number_type: dpan and acryptogramis handled correctly. - Omitting
payment_method.numberreturns HTTP 400 withcode: invalid_card andparam: payment_method.number. - An unknown
allowance.merchant_idreturns HTTP 400 withcode: invalid_card andparam: allowance.merchant_id. - A malformed
allowance.expires_atreturns HTTP 400 withcode: invalid_card andparam: allowance.expires_at. - A request with
risk_signals[].action: blocked rejects tokenization. - The same request sent twice with the same
Idempotency-Keyreturns HTTP 201 with the sameid. - The same
Idempotency-Keysent with a different body returns HTTP 400 withcode: idempotency_conflict. - The returned
idused in a POST/paymentsrequest 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. |