Bug Description
Hyperswitch version: v1.123.1-dirty-233117e-2026-05-18
Connector: Adyen
Flow: New mandate creation (CIT) for card
Expected behavior:
When creating a payment with payment_type: new_mandate, setup_future_usage: off_session, and mandate_data.mandate_type.multi_use, Hyperswitch should send storePaymentMethod: true and recurringProcessingModel: CardOnFile to Adyen, and store the returned recurringDetailReference as connector_mandate_id.
Actual behavior:
Adyen request does NOT contain storePaymentMethod or recurringProcessingModel
Adyen response does NOT return recurringDetailReference
Hyperswitch response returns mandate_id: null and connector_mandate_id: null
setup_future_usage in response is always on_session regardless of what is sent in request
Adyen request sent by Hyperswitch:
json{
"shopperInteraction": "Ecommerce",
"shopperReference": "merchant_1781003022_cus_oDoJmNHeHbnmAVvHWwEG",
"additionalData": { "executeThreeD": "false" }
}
storePaymentMethod and recurringProcessingModel are absent.
Payment request DTO used:
json{
"payment_type": "new_mandate",
"setup_future_usage": "off_session",
"off_session": false,
"mandate_data": {
"customer_acceptance": {
"acceptance_type": "online",
"accepted_at": "2026-06-10T13:10:00Z",
"online": { "ip_address": "x.x.x.x", "user_agent": "Mozilla/5.0..." }
},
"mandate_type": { "multi_use": { "amount": 0, "currency": "USD" } }
}
}
Config: adyen is present in mandates.supported_payment_methods for both card.credit and card.debit.
Question: What is the correct way to trigger storePaymentMethod: true in the Adyen request through Hyperswitch for a new mandate CIT flow? Is there a specific field or config missing?
Expected Behavior
Here's the expected behavior section:
Expected Behavior:
- Hyperswitch should send the following to Adyen:
json{
"amount": { "currency": "USD", "value": 6540 },
"merchantAccount": "<merchant_account>",
"paymentMethod": { "type": "scheme", "number": "***", "expiryMonth": "***", "expiryYear": "***", "cvc": "***" },
"reference": "pay_xxx_1",
"shopperReference": "merchant_xxx_cus_xxx",
"shopperInteraction": "Ecommerce",
"storePaymentMethod": true,
"recurringProcessingModel": "CardOnFile"
}
- Adyen should respond with a recurringDetailReference:
json{
"resultCode": "Authorised",
"pspReference": "XXXXXXXXXXXXXXXX",
"additionalData": {
"recurring.recurringDetailReference": "9916272248971342",
"recurring.shopperReference": "merchant_xxx_cus_xxx"
}
}
- Hyperswitch payment response should return:
json{
"payment_id": "pay_xxx",
"status": "succeeded",
"setup_future_usage": "off_session",
"mandate_id": "man_xxx",
"connector_mandate_id": "9916272248971342",
"customer_id": "cus_xxx"
}
- Subsequent MIT charge using the mandate should work:
POST /payments
{
"amount": 1000,
"currency": "USD",
"confirm": true,
"customer_id": "cus_xxx",
"mandate_id": "man_xxx",
"off_session": true
}
And Hyperswitch should send to Adyen:
json{
"shopperInteraction": "ContAuth",
"recurringProcessingModel": "CardOnFile",
"paymentMethod": {
"type": "scheme",
"storedPaymentMethodId": "9916272248971342"
}
}
This covers the full CIT → MIT flow that is currently broken.
Actual Behavior
Here's the actual behavior section:
Actual Behavior:
- Hyperswitch sends to Adyen (missing recurring fields):
json{
"amount": { "currency": "USD", "value": 6540 },
"merchantAccount": "AkhyarFoundationLimitedECOM",
"paymentMethod": { "type": "scheme", "number": "***", "expiryMonth": "***", "expiryYear": "***", "cvc": "***" },
"reference": "pay_D5GtUkbSRY7aKfZhXkCn_1",
"returnUrl": "https://dev-api-hyperswitch.g14n.net/payments/pay_D5GtUkbSRY7aKfZhXkCn/merchant_1781003022/redirect/response/adyen",
"browserInfo": { "userAgent": "...", "acceptHeader": "...", "language": "en-US", "colorDepth": 24, "screenHeight": 1080, "screenWidth": 1920, "timeZoneOffset": 330, "javaEnabled": false },
"shopperInteraction": "Ecommerce",
"shopperReference": "merchant_1781003022_cus_oDoJmNHeHbnmAVvHWwEG",
"shopperName": { "firstName": "***", "lastName": "***" },
"shopperLocale": "en",
"additionalData": { "executeThreeD": "false" }
}
❌ storePaymentMethod is absent
❌ recurringProcessingModel is absent
2. Adyen responds without any recurring token:
json{
"resultCode": "Authorised",
"pspReference": "BC8Z3ZZ28CP52775",
"amount": { "currency": "USD", "value": 6540 },
"merchantReference": "pay_D5GtUkbSRY7aKfZhXkCn_1",
"additionalData": {
"paymentMethod": "visa",
"networkTxReference": "***",
"isCardCommercial": "***",
"scaExemptionRequested": "***"
}
}
❌ No recurring.recurringDetailReference in additionalData
❌ No card stored in Adyen vault
3. Hyperswitch payment response:
json{
"payment_id": "pay_D5GtUkbSRY7aKfZhXkCn",
"status": "succeeded",
"setup_future_usage": "on_session",
"mandate_id": null,
"connector_mandate_id": null,
"network_transaction_id": "601588850742073"
}
❌ mandate_id is null
❌ connector_mandate_id is null
❌ setup_future_usage is on_session despite sending off_session in request
4. Attempted workarounds that did not work:
Adding payment_type: "new_mandate" → no effect
Adding is_stored_credential: true → field ignored
Adding connector_metadata.adyen.store_payment_method: true → field not passed through to Adyen, stripped from request
mandate_data.mandate_type.multi_use with amount: 0 → no effect
Summary: Hyperswitch is not translating the new mandate intent into Adyen-specific recurring fields (storePaymentMethod, recurringProcessingModel) regardless of what combination of fields is sent in the payment request.
Steps To Reproduce
Here are the exact reproduction steps:
Steps to Reproduce:
- Create a customer:
POST /customers
{
"name": "Test User",
"email": "test@example.com"
}
- Configure Adyen connector with recurring_enabled: true for card credit/debit in payment_methods_enabled.
- Ensure mandates.supported_payment_methods in config has adyen listed under card.credit and card.debit (already present in default config).
- Create a payment with new mandate intent:
POST /payments
{
"amount": 6540,
"currency": "USD",
"confirm": true,
"connector": ["adyen"],
"customer_id": "<customer_id>",
"payment_type": "new_mandate",
"setup_future_usage": "off_session",
"off_session": false,
"mandate_data": {
"customer_acceptance": {
"acceptance_type": "online",
"accepted_at": "2026-06-10T13:10:00Z",
"online": {
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0"
}
},
"mandate_type": {
"multi_use": {
"amount": 0,
"currency": "USD"
}
}
},
"payment_method": "card",
"payment_method_data": {
"card": {
"card_number": "4111111111111111",
"card_exp_month": "03",
"card_exp_year": "30",
"card_holder_name": "Test User",
"card_cvc": "737"
}
}
}
- Observe the Hyperswitch response:
mandate_id is null
connector_mandate_id is null
setup_future_usage is on_session (overridden from off_session)
- Observe the Adyen request sent by Hyperswitch (visible in Adyen dashboard under Developers → API logs):
storePaymentMethod field is absent
recurringProcessingModel field is absent
Only shopperReference is sent, which is not sufficient for Adyen to store the card
- Observe the Adyen response:
No recurringDetailReference in additionalData
No card stored in Adyen's token vault
Expected at step 5: mandate_id and connector_mandate_id should be populated.
Expected at step 6: Request should contain storePaymentMethod: true and recurringProcessingModel: "CardOnFile".
Context For The Bug
No response
Environment
Are you using hyperswitch hosted version? Yes/No
If yes, please provide the value of the x-request-id response header to help us debug your issue.
If not (or if building/running locally), please provide the following details:
- Operating System or Linux distribution:
- Rust version (output of
rustc --version): ``
- App version (output of
cargo r --features vergen -- --version): ``
Have you spent some time checking if this bug has been raised before?
Have you read the Contributing Guidelines?
Are you willing to submit a PR?
None
Bug Description
Hyperswitch version: v1.123.1-dirty-233117e-2026-05-18
Connector: Adyen
Flow: New mandate creation (CIT) for card
Expected behavior:
When creating a payment with payment_type: new_mandate, setup_future_usage: off_session, and mandate_data.mandate_type.multi_use, Hyperswitch should send storePaymentMethod: true and recurringProcessingModel: CardOnFile to Adyen, and store the returned recurringDetailReference as connector_mandate_id.
Actual behavior:
Adyen request does NOT contain storePaymentMethod or recurringProcessingModel
Adyen response does NOT return recurringDetailReference
Hyperswitch response returns mandate_id: null and connector_mandate_id: null
setup_future_usage in response is always on_session regardless of what is sent in request
Adyen request sent by Hyperswitch:
storePaymentMethod and recurringProcessingModel are absent.
Payment request DTO used:
Config: adyen is present in mandates.supported_payment_methods for both card.credit and card.debit.
Question: What is the correct way to trigger storePaymentMethod: true in the Adyen request through Hyperswitch for a new mandate CIT flow? Is there a specific field or config missing?
Expected Behavior
Here's the expected behavior section:
Expected Behavior:
POST /payments
And Hyperswitch should send to Adyen:
This covers the full CIT → MIT flow that is currently broken.
Actual Behavior
Here's the actual behavior section:
Actual Behavior:
❌ storePaymentMethod is absent
❌ recurringProcessingModel is absent
2. Adyen responds without any recurring token:
❌ No recurring.recurringDetailReference in additionalData
❌ No card stored in Adyen vault
3. Hyperswitch payment response:
❌ mandate_id is null
❌ connector_mandate_id is null
❌ setup_future_usage is on_session despite sending off_session in request
4. Attempted workarounds that did not work:
Adding payment_type: "new_mandate" → no effect
Adding is_stored_credential: true → field ignored
Adding connector_metadata.adyen.store_payment_method: true → field not passed through to Adyen, stripped from request
mandate_data.mandate_type.multi_use with amount: 0 → no effect
Summary: Hyperswitch is not translating the new mandate intent into Adyen-specific recurring fields (storePaymentMethod, recurringProcessingModel) regardless of what combination of fields is sent in the payment request.
Steps To Reproduce
Here are the exact reproduction steps:
Steps to Reproduce:
POST /customers
POST /payments
mandate_id is null
connector_mandate_id is null
setup_future_usage is on_session (overridden from off_session)
storePaymentMethod field is absent
recurringProcessingModel field is absent
Only shopperReference is sent, which is not sufficient for Adyen to store the card
No recurringDetailReference in additionalData
No card stored in Adyen's token vault
Expected at step 5: mandate_id and connector_mandate_id should be populated.
Expected at step 6: Request should contain storePaymentMethod: true and recurringProcessingModel: "CardOnFile".
Context For The Bug
No response
Environment
Are you using hyperswitch hosted version? Yes/No
If yes, please provide the value of the
x-request-idresponse header to help us debug your issue.If not (or if building/running locally), please provide the following details:
rustc --version): ``cargo r --features vergen -- --version): ``Have you spent some time checking if this bug has been raised before?
Have you read the Contributing Guidelines?
Are you willing to submit a PR?
None