# Authentication Types
Source: https://api-reference.hyperswitch.io/essentials/authentication
Overview of authentication types and authorization keys available in Hyperswitch.
Hyperswitch supports multiple API key types, each designed for different authentication and authorization use cases.
For security, **never expose secret or admin keys in client-side or mobile code**. Use publishable keys for public contexts.
## 1. API Key (Secret Key)
* **Primary merchant authentication key for server-side API requests.**
* Environment-specific prefix (`snd_`, `prod_`, etc.).
* Used for server to server requests.
* This key can be **generated and managed from the [Hyperswitch dashboard (sandbox)](https://app.hyperswitch.io/developers?tabIndex=1)**.
* **Never expose this key in public code.**
## 2. Admin API Key
* **Administrative key** with elevated privileges.
* Used for system-level operations such as creating merchant and connector accounts.
* Should only be used in secure, internal workflows.
* Some API calls require an admin API key. **Do not confuse this with a regular API Key.**
* The **admin API key is a configuration value that can be set at the time of deploying the Hyperswitch server**.
* **Admin API keys for the hosted Hyperswitch environments (sandbox/production) are managed by Juspay and are not provided publicly.**
You do **not** generate this key from the dashboard.\
Instead, **set your Admin API Key in your deployment configuration**:
**For Docker Compose:**\
Update the value in your `docker_compose.toml` file:
```toml theme={null}
# docker_compose.toml
admin_api_key = "your_admin_key_here"
```
**For Helm Chart deployments:** Set the admin API key in your `values.yaml` file.
```yaml theme={null}
# values.yaml
adminApiKey: your_admin_key_here
```
Do **not** expose your admin API key publicly. Only trusted entities and trusted applications should have access to this value.
Check the Docker Compose example for extra clarity:
[See example in the Hyperswitch repository](https://github.com/juspay/hyperswitch/blob/main/config/docker_compose.toml)
## 3. Publishable Key
* **Client-side key** with limited permissions.
* Safe for use in public client-side (web or mobile) code.
* Prefix: `pk_{environment}_{uuid}`.
* Generated during merchant account creation.
## 4. Ephemeral Key
* **Temporary key** for limited operations.
* Used for single or short-lived access (e.g., accessing a specific customer object).
* Validity is configurable (see `[eph_key] validity` in `development.toml`).
## 5. JWT Key
* **JWT Bearer Token** used for API authentication and session management.
* Required for certain JWT-protected endpoints and user authentication flows.
* Format: `Authorization: Bearer `
### When to Use
JWT tokens are primarily used by the Hyperswitch Control Center front end to authenticate API requests. You generally do **not** need to manage or use JWTs unless:
* You’re building a **custom front end** that replaces the Control Center, or
* You’re a developer **testing APIs directly** (e.g., using Postman or running the server without the UI).
For most users interacting through the Control Center UI, JWTs are handled automatically and do not need to be generated or included manually.
> **Note:**\
> JWTs are **not provisioned via the Hyperswitch dashboard**.\
> They are typically **issued during an authentication flow**, such as during login or session creation.
```http theme={null}
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
Keep your JWT tokens secure. Do not expose them in client-side code unless specifically required for session management, and always use HTTPS when transmitting JWTs.
## Reference Table
| Key Type | Example Prefix | Usage | Security |
| - | - | - | - |
| Secret (API Key) | snd\_c69\*\*\*, prod\_\*\*\* | Backend server API requests | Keep secret |
| Admin API Key | (admin-specific) | Admin operations | Highly confidential |
| Publishable Key | pk\_snd\_3b3\*\*\* | Client-side, public usage | Safe to expose |
| Ephemeral Key | (short-lived) | Temporary, limited access | Short validity, limited |
| JWT Key | (JWT Bearer) | Session/user authentication | Control center calls |
Get your [API Key](https://app.hyperswitch.io/developers?tabIndex=1) and [Publishable Key](https://app.hyperswitch.io/home) from the Hyperswitch dashboard.
***
# Error Codes
Source: https://api-reference.hyperswitch.io/essentials/error_codes
Hyperswitch uses error codes, types, and messages to communicate errors during API calls. There are two main types of error codes: Error Codes and Unified Error Codes.
1. **Error Codes** refer to the error code sent by the connector.
2. **Unified Error Codes** refer to the generic error code sent by the Hyperswitch server, based on the connector's error code. Hyperswitch groups the different error codes from connectors into more generic Unified Error Codes for structured relay of PSP errors, helping merchants derive patterns and determine the next steps for ongoing transactions.
There are four types of Error Codes and five types of Unified Error Codes.
**1. Error Codes:**
The section below contains all the error codes and their corresponding error messages.
| Error Code | Type | Description |
| - | - | - |
| IR | Invalid Request Error | Error caused due to invalid fields and values in API request |
| CE | Connector Error | Errors originating from connector’s end |
| HE | Hyperswitch Error | Errors originating from Hyperswitch’s end |
| WE | Webhook Error | Errors related to Webhooks |
| Error Codes | HTTP Status codes | Error Type | Error message | Error Handling |
| - | - | - | - | - |
| IR\_00 | 501 | server\_not\_available | This API is under development and will be made available soon | No action required. If you require this feature, please reach out to Hyperswitch support |
| IR\_01 | 401 | invalid\_request\_error | API key not provided or invalid API key used. Provide the API key in the Authorization header using api-key (e.g api-key: API\_KEY) or create a new API key from the dashboard | Provide the API key in the Authorization header using api-key (e.g api-key: API\_KEY) or create a new API key from the dashboard |
| IR\_02 | 404 | invalid\_request\_error | Unrecognized request URL | Please recheck and enter the correct request URL. Refer to our API documentation |
| IR\_03 | 405 | invalid\_request\_error | The HTTP method is not applicable for this API | Please recheck the HTTP method used in the request. Refer to our API documentation |
| IR\_04 | 400 | invalid\_request\_error | Missing required param: “field\_name” | Please pass the missing required parameter. Refer to our API documentation |
| IR\_05 | 422 | invalid\_request\_error | “field\_name” contains invalid data. Expected format is “expected\_format” | Please pass the data in the expected format. Refer to our API documentation |
| IR\_06 | 400 | invalid\_request\_error | “message” | Refer to our API documentation for required fields and format |
| IR\_07 | 400 | invalid\_request\_error | Invalid value provided: “field\_name” | Provide a valid value for the required fields in the expected format. Refer to our API documentation |
| IR\_08 | 400 | invalid\_request\_error | Client secret was not provided | Provide the client secret received in payments/create API response |
| IR\_09 | 400 | invalid\_request\_error | The client\_secret provided does not match the client\_secret associated with the Payment | Provide the same client secret received in payments/create API response for the corresponding payment |
| IR\_10 | 400 | invalid\_request\_error | Customer has an existing mandate/subscription | Cancel the active mandates/subscriptions for the customer before proceeding to delete the customer data |
| IR\_11 | 400 | invalid\_request\_error | Customer has already been redacted | Customer has already been redacted. No action required |
| IR\_12 | 400 | invalid\_request\_error | Reached the maximum refund attempts | Maximum refund attempts reached for this payment. Please contact Hyperswitch support for attempting more refunds for the same payment |
| IR\_13 | 400 | invalid\_request\_error | Refund amount exceeds the payment amount | Please verify and pass a refund amount equal to or less than the payment amount |
| IR\_14 | 400 | invalid\_request\_error | This Payment could not be “current\_flow” because it has a “field\_name” of “current\_value”. The expected state is “states” | Please verify the status of the payment and make sure that you are performing an action that is allowed for the current status of the payment |
| IR\_15 | 400 | invalid\_request\_error | Invalid Ephemeral Key for the customer | Please pass the right Ephemeral key for the customer |
| IR\_16 | 400 | invalid\_request\_error | “message” | Typically used when information involving multiple fields or previously provided information doesn’t satisfy a condition. Refer to our API documentation for required fields and format |
| IR\_17 | 401 | invalid\_request\_error | Access forbidden, an invalid JWT token was used | Provide a valid JWT token to access the APIs |
| IR\_18 | 401 | invalid\_request\_error | "message" | The user is not authorised to update the customer, Contact Org. Admin for the appropriate access. |
| IR\_19 | 400 | invalid\_request\_error | "message" | Please check and retry with correct details. Refer to our API documentation |
| IR\_20 | 400 | invalid\_request\_error | "flow" not supported by the "connector" | Requested flow is not supported for this Connector. |
| IR\_21 | 400 | invalid\_request\_error | Missing required params | Please add the required params in the request. Refer to our API documentation |
| IR\_22 | 403 | invalid\_request\_error | Access forbidden. Not authorized to access this "resource" | Contact Org. Admin for the appropriate access. |
| IR\_23 | 400 | invalid\_request\_error | "message" | Use a supported file provider. Refer to our API documentation |
| IR\_24 | 422 | processing\_error | Invalid "wallet\_name" wallet token | Share the correct wallet token. |
| IR\_25 | 400 | invalid\_request\_error | Cannot delete the default payment method | Check if the Payment method is activated. Refer to Control centre to check this. |
| IR\_26 | 400 | invalid\_request\_error | Invalid Cookie | Recheck the site setting for the cookies. |
| IR\_27 | 404 | invalid\_request\_error | Extended card info does not exist | Recheck the card info shared in the request. |
| IR\_28 | 400 | invalid\_request\_error | "message" | Use a valid currency. Refer to our API documentation |
| IR\_29 | 422 | invalid\_request\_error | "message" | The data format is invalid for this request. Refer to our API documentation |
| IR\_30 | 400 | invalid\_request\_error | Merchant connector account is configured with invalid config | Correct the config for merchant connector account |
| IR\_31 | 400 | invalid\_request\_error | Card with the provided iin does not exist | Check the IIN (Issuer Identification Number) and ensure it is correct. |
| IR\_32 | 400 | invalid\_request\_error | The provided card IIN length is invalid, please provide an iin with 6 or 8 digits | Provide a valid IIN with either 6 or 8 digits. |
| IR\_33 | 400 | invalid\_request\_error | File not found / valid in the request | Ensure the required file is included in the request and is valid. Refer to our API documentation |
| IR\_34 | 400 | invalid\_request\_error | Dispute id not found in the request | Ensure that a valid dispute ID is included in the request. |
| IR\_35 | 400 | invalid\_request\_error | File purpose not found in the request or is invalid | Specify a valid file purpose in the request. |
| IR\_36 | 400 | invalid\_request\_error | File content type not found / valid | Ensure the file content type is specified and is valid. |
| IR\_37 | 404 | invalid\_request\_error | "message" | Check the request for the resource being accessed and ensure it exists. |
| IR\_38 | 400 | invalid\_request\_error | "message" | Check for any duplicate entries in the request and correct them. |
| IR\_39 | 400 | invalid\_request\_error | required payment method is not configured or configured incorrectly for all configured connectors | Verify that the required payment method is correctly configured for all connectors in use. |
| CE\_00 | Status codes shared by the connectors | connector\_error | “message” | The error code and message passed from the connectors. Refer to the respective connector’s documentation for more information on the error |
| CE\_01 | 400 | processing\_error | Payment failed during authorization with the connector. Retry payment | Retry the payment again as payment failed at the connector during authorization |
| CE\_02 | 400 | processing\_error | Payment failed during authentication with the connector. Retry payment | Retry the payment again as payment failed at the connector during authentication |
| CE\_03 | 400 | processing\_error | Capture attempt failed while processing with the connector | Capture failed for the payment at the connector. Please retry the payment |
| CE\_04 | 400 | processing\_error | The card data is invalid | Invalid card data passed. Please pass valid card data |
| CE\_05 | 400 | processing\_error | The card has expired | Card expired. Please pass valid card data |
| CE\_06 | 400 | processing\_error | Refund failed while processing with the connector. Retry refund | Refund failed to process at the connector. Please retry refund |
| CE\_07 | 400 | processing\_error | Verification failed while processing with the connector. Retry operation | Retry the operation again as verification failed at the connector |
| CE\_08 | 400 | processing\_error | Dispute operation failed while processing with connector. Retry operation | Retry the operation again as dispute failed at the connector |
| CE\_09 | 400 | invalid\_request\_error | Payout validation failed | Retry the operation again with correct Payout details. |
| HE\_00 | 422,500 | server\_not\_available | Resource not available right now, Please try again later. | Please Wait for a few moments and try again. If the error still persists, please reach out to Hyperswitch support |
| HE\_01 | 400,422 | duplicate\_request | Requested operation(Customer, Payments, Merchants, Refunds etc.) for these identifier already exists. | Please verify the Details(Customer, Payments, Merchants, Refunds, as applicable on the basis of request) and enter valid details. |
| HE\_02 | 404 | object\_not\_found | Requested object(Customer, Payments, Merchants, Refunds etc.) does not exist in our records | Please verify the Details(Customer, Payments, Merchants, Refunds, as applicable on the basis of request) and enter valid details. |
| HE\_03 | 500 | validation\_error | Validation Failed for the requested operation with the given details. | Please verify the details again and enter valid details |
| HE\_04 | 404 | object\_not\_found | Requested object(Customer, Payments, Merchants, Refunds etc.) does not exist in our records | Please verify the Details(Customer, Payments, Merchants, Refunds, as applicable on the basis of request) and enter valid details. |
| HE\_05 | 500 | processing\_error | Missing or invalid tenant details. | Please verify the tenant Details and try again. |
| WE\_01 | 400 | invalid\_request\_error | Failed to authenticate the webhook | Please verify the authentication credentials and try again. |
| WE\_02 | 400 | invalid\_request\_error | Bad request received in webhook | Check the request parameters and format, then try again. |
| WE\_03 | 500 | router\_error | There was some issue processing the webhook | Please try again later. If the issue persists, contact Hyperswitch support. |
| WE\_04 | 404 | object\_not\_found | Webhook resource not found | Ensure the webhook URL is correct and the resource exists. |
| WE\_05 | 400 | invalid\_request\_error | Unable to process the webhook body | Ensure the webhook body is correctly formatted and try again. |
| WE\_06 | 400 | invalid\_request\_error | Merchant Secret set by merchant for webhook source verification is invalid | Verify the Merchant Secret, then try again. |
**2. Unified Error codes:**
The section below contains all the unified error codes and their corresponding error messages.
| Unified Error Code | Unified Error Categorisation | Unified Error message |
| - | - | - |
| UE\_1000 | Customer Error | Issue with payment method details. |
| UE\_2000 | Connector Declines | Issue with Configurations. |
| UE\_3000 | Connector Error | Technical issue with PSP. |
| UE\_4000 | Integration Error | Issue in the integration. |
| UE\_9000 | Others | Something went wrong. |
## Error Details Structure
Hyperswitch returns a structured `error_details` object for failed payments.
This object combines error information from the connector (PSP), the issuer (bank), and Hyperswitch's own interpretation.
**Unified Details**
This section is Hyperswitch's understanding of the failure. It is created by looking at the issuer and connector error signals and mapping them to a standard meaning.
* **Category** - The high-level unified error code (for example `UE_1000` for payment method issues).
* **Message** - High level unified error message that is consistent across different connectors.
* **Standardised Code** - Code that identifies the specific cause for a failure within a broader error category such as `INVALID_EXPIRY_DATE`.
* **Description** - A detailed description of the error intended for debugging, analytics, and support teams.
* **User Guidance Message** - A user-friendly message that can be safely displayed to the customer. This message provides guidance on what the user should do to resolve the issue.
* **Recommended Action** - A field that tells merchants what action to take after a payment failure.
| Action | Description |
| - | - |
| `do_not_retry` | Never retry with same card |
| `retry_later` | Retry after some time |
| `retry_after_1_hour` | Retry after 1 hour |
| `retry_after_24_hours` | Retry after 24 hours |
| `retry_after_2_days` | Retry after 2 days |
| `retry_after_4_days` | Retry after 4 days |
| `retry_after_6_days` | Retry after 6 days |
| `retry_after_8_days` | Retry after 8 days |
| `retry_after_10_days` | Retry after 10 days |
| `retry_after_instrument_update` | Retry after updating payment details |
| `retry_with_different_payment_method_data` | Use different payment method |
| `stop_recurring` | Stop recurring payments |
## Enhanced Errors
This table provides a standardized mapping that translates granular payment error into consistent standardised codes, customer-facing messages and description. The classification mappings, user guidance message and descriptions are subject to change at any time.
| Standardised Code | Unified Code(Category) | Unified Message(Message) | User Guidance Message | Description |
| - | - | - | - | - |
| **PAYMENT\_METHOD\_ISSUE** | **UE\_1000** | **Issue with payment method details** | **Issue with Payment Method details** | **Issue with Payment Method details** |
| INVALID\_CARD\_NUMBER | UE\_1000 | Issue with payment method details | The card number doesn't look right. Please check it and try again | The card number is invalid |
| INVALID\_EXPIRY\_DATE | UE\_1000 | Issue with payment method details | The card's expiry date seems incorrect or has passed. Update it or use another card. | Expiry date is in the past or improperly formatted. |
| INVALID\_CVV | UE\_1000 | Issue with payment method details | The security code (CVV) is incorrect. Please re-enter it. | CVV is missing, malformed, or does not match issuer records |
| PM\_ADDRESS\_MISMATCH | UE\_1000 | Issue with payment method details | The billing address doesn't match what the bank has on file. Update it or use another card. | Address mismatch (AVS failed) |
| INSUFFICIENT\_FUNDS | UE\_1000 | Issue with payment method details | There aren't enough funds on this card. Use another card or add funds and try again | The entered card has insufficient funds |
| CREDIT\_LIMIT\_EXCEEDED | UE\_1000 | Issue with payment method details | This card has reached its credit limit. Use another card or contact your bank. | Transaction exceeds cardholder's credit limit |
| VELOCITY\_LIMIT\_EXCEEDED | UE\_1000 | Issue with payment method details | This card has hit a usage limit set by your bank. Try another card or contact your bank. | Transaction exceeds allowed frequency or velocity |
| CARD\_LOST\_OR\_STOLEN | UE\_1000 | Issue with payment method details | The bank has blocked this card. Please use a different card. | This card has been reported as lost or stolen |
| CARD\_NOT\_SUPPORTED\_RESTRICTED | UE\_1000 | Issue with payment method details | This card can't be used for this payment. Try another card or payment method. | Card is restricted for this merchant, channel, or use case |
| ACCOUNT\_CLOSED\_OR\_INVALID | UE\_1000 | Issue with payment method details | This account is not active. Use a different payment method. | Account closed or invalid or missing |
| AUTHORIZATION\_MISSING\_OR\_REVOKED | UE\_1000 | Issue with payment method details | This payment can't be completed because the prior authorization was canceled. Try another card or contact your bank. | Customer authorization is missing or was revoked |
| INCORRECT\_AUTHENTICATION\_CODE | UE\_1000 | Issue with payment method details | The code you entered is incorrect. Request a new code and try again. | Incorrect authentication or verification code provided |
| PAYMENT\_SESSION\_TIMEOUT | UE\_1000 | Issue with payment method details | Your session expired. Start the payment again. | Payment session expired before completion |
| AUTHENTICATION\_FAILED | UE\_1000 | Issue with payment method details | We couldn't verify this payment with your bank. Try again or use a different payment method. | Authentication failed or was declined |
| PAYMENT\_CANCELLED\_BY\_USER | UE\_1000 | Issue with payment method details | The payment was canceled. If this wasn't intended, please start a new payment. | Payment flow was canceled by user or system |
| TRANSACTION\_NOT\_PERMITTED | UE\_1000 | Issue with payment method details | This payment method can't be used for this type of purchase. Try another payment method. | This type of purchase is not permitted or supported |
| PM\_TOKENISATION\_ISSUE | UE\_1000 | Issue with payment method details | We couldn't save or use this card securely. Try again or use a different payment method. | Failed to tokenize or validate card credentials |
| **CONFIGURATION\_ISSUE** | **UE\_2000** | **Issue with configuration** | **Something went wrong. Try another Payment Method** | **Issue with Configurations** |
| MERCHANT\_INACTIVE | UE\_2000 | Issue with configuration | Something went wrong. Try another Payment Method | Merchant configuration inactive or invalid |
| CFG\_PM\_NOT\_ENABLED\_OR\_MISCONFIGURED | UE\_2000 | Issue with configuration | Something went wrong. Try another Payment Method | Payment method not enabled for this merchant |
| CURRENCY\_OR\_CORRIDOR\_NOT\_ENABLED | UE\_2000 | Issue with configuration | Something went wrong. Try another Payment Method | Currency or corridor not enabled |
| WALLET\_OR\_TOKEN\_CONFIG\_ISSUE | UE\_2000 | Issue with configuration | Something went wrong. Try another Payment Method | Wallet or token configuration missing or incorrect |
| STORED\_CREDENTIAL\_OR\_MIT\_NOT\_ENABLED | UE\_2000 | Issue with configuration | Something went wrong. Try another Payment Method | Stored credential or MIT not enabled |
| THREEDS\_CONFIGURATION\_ISSUE | UE\_2000 | Issue with configuration | Something went wrong. Try another Payment Method | 3DS not enabled or improperly integrated. |
| SUBSCRIPTION\_PLAN\_INACTIVE | UE\_2000 | Issue with configuration | Something went wrong. Try another Payment Method | Attempted charge on inactive or expired subscription |
| **DOWNSTREAM\_TECHNICAL\_ISSUE** | **UE\_3000** | **Technical Issue with PSP** | **Something went wrong. Try again or contact your bank** | **Downstream technical issue** |
| ISSUER\_UNAVAILABLE | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | The card issuer's bank is temporarily unavailable |
| TRANSACTION\_TIMEDOUT | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | Issuer timeout |
| DO\_NOT\_HONOR | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | Do not honor |
| SUSPECTED\_FRAUD | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | Issuer flagged as suspected fraud. |
| PSP\_FRAUD\_ENGINE\_DECLINE | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | Declined by PSP fraud engine |
| COMPLIANCE\_OR\_SANCTIONS\_RESTRICTION | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | Sanctions or compliance blockage |
| PSP\_ACQUIRER\_ERROR | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | Temporary acquirer internal error |
| THREEDS\_AUTHENTICATION\_SERVICE\_ISSUE | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | 3DS Authentication Service Failure |
| AUTHENTICATION\_REQUIRED | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | Authentication is required |
| **INTEGRATION\_ISSUE** | **UE\_4000** | **Issue with integration** | **Something went wrong. Try another payment method or contact your bank** | **Issue with Integration** |
| MISSING\_OR\_INVALID\_PARAM | UE\_4000 | Issue with integration | Something went wrong. Try another payment method or contact your bank | Missing or invalid parameter |
| INVALID\_CREDENTIALS | UE\_4000 | Issue with integration | Something went wrong. Try another payment method or contact your bank | Invalid credentials |
| OPERATION\_NOT\_ALLOWED | UE\_4000 | Issue with integration | Something went wrong. Try another payment method or contact your bank | Operation not allowed |
| DUPLICATE\_REQUEST | UE\_4000 | Issue with integration | Something went wrong. Try another payment method or contact your bank | Duplicate or Idempotent request |
| INVALID\_STATE | UE\_4000 | Issue with integration | Something went wrong. Try another payment method or contact your bank | Invalid state of operation |
| THREEDS\_DATA\_OR\_PROTOCOL\_INVALID | UE\_4000 | Issue with integration | Something went wrong. Try another payment method or contact your bank | 3DS payload invalid or inconsistent |
| RATE\_LIMIT | UE\_4000 | Issue with integration | Something went wrong. Try another payment method or contact your bank | API rate limit exceeded |
| INTEG\_CRYPTOGRAPHIC\_ISSUE | UE\_4000 | Issue with integration | Something went wrong. Try another payment method or contact your bank | Token or cryptographic integration issue |
| **GEN\_UNKNOWN\_ERROR** | **UE\_9000** | **Something went wrong** | **Something went wrong** | **Something went wrong** |
# Go-live Checklist
Source: https://api-reference.hyperswitch.io/essentials/go-live
Refer to this checklist for a seamless transition as you prepare to go live with your integration.
The connector configurations set up in the sandbox need to be replicated on the Hyperswitch production account.
### Signing of Hyperswitch services agreement
* [ ] Ensure that the Hyperswitch services agreement is signed and shared with the Hyperswitch team. In case you need any help, please drop an email to [biz@hyperswitch.io](mailto:biz@hyperswitch.io).
The Hyperswitch team will share your production Hyperswitch credentials once the above process is completed.
### Connector Configurations
* [ ] Configure all the required connectors using production credentials on the Hyperswitch production dashboard and enable the required payment methods.
* [ ] Ensure that the payment methods are enabled on the connector (payment processor) dashboard.
* [ ] Enable raw card processing for each connector. Some connectors offer this as a dashboard toggle feature. Some processors might need you to share a PCI Attestation of Compliance over email to enable this. Drop an email to [biz@hyperswitch.io](mailto:biz@hyperswitch.io) if you need any support with PCI AOC.
### Secure your api-keys
* [ ] Make sure your secret key (api-key) is not exposed on the front-end (website/mobile app).
* [ ] Ensure that your workflow avoids the duplication or storage of your API keys in multiple locations.
### Set up Webhooks
* [ ] [Configure your webhook endpoint](https://juspay-78.mintlify.app/essentials/webhooks#configuring-webhooks) on our dashboard to receive notifications for different events.
* [ ] Update Hyperswitch's webhook endpoints on your connector's Dashboard. [Refer here](https://juspay-78.mintlify.app/essentials/webhooks#configuring-webhooks) for detailed instructions.
* [ ] Update the connector secret key in our dashboard for us to authenticate webhooks sent by your connector.
### Secure your Payments
* [ ] Make sure you decrypt and verify the signed payload sent along with the payment status in your return URL.
* [ ] Always verify the payment amount and payment status before fulfilling your customer's shopping cart/service request.
### Error Handling
* [ ] Make sure your API integration is set up to handle all the possible error scenarios (refer this [link](https://juspay-78.mintlify.app/essentials/error_codes)).
* [ ] Ensure your Unified Checkout (SDK) integration is set up to handle all the possible error scenarios (refer this [link](https://hyperswitch.io/docs/sdkIntegrations/unifiedCheckoutWeb/errorCodes)).
* [ ] Ensure that your integration can handle the entire payments lifecycle and test various scenarios using actual payment details.
### Customize and sanity check the payment experience
* [ ] Ensure the pay button is properly highlighted to the customer.
* [ ] Ensure a blended look and feel of the payment experience using the [styling APIs](https://hyperswitch.io/docs/sdkIntegrations/unifiedCheckoutWeb/customization) of Unified Checkout.
# Rate Limits
Source: https://api-reference.hyperswitch.io/essentials/rate_limit
The Hyperswitch API has multiple checks in place to enhance its stability when faced with sudden surges of incoming traffic. Merchants who send numerous requests in rapid succession could encounter error responses indicated by the status code 429.
The default rate limit for all Hyperswitch APIs is **80 requests per second**.
Reach out to [biz@hyperswitch.io](mailto:biz@hyperswitch.io) if you have a requirement for higher limits.
## How to handle rate limits
Effectively handling rate limit 429 errors is crucial for maintaining a seamless user experience.
* Implement retry mechanisms with progressively increasing intervals to avoid overwhelming the system with repeated requests.
* To proactively manage these errors, monitoring tools can help track usage patterns and provide insights for adjusting rate limits as necessary.
* Ultimately, a well-orchestrated strategy for managing 429 errors not only prevents disruption but also fosters positive user engagement by transparently addressing limitations and promoting responsible API usage.
## Understanding API locking
If you see a 429 error with the following error message, it is due to API locking and not due to rate limiting:
```text theme={null}
At this moment, access to this object is restricted due to ongoing utilization by another API request or an ongoing Hyperswitch process. Retry after some time if this error persists.
```
API locking is a robust feature that empowers us to proactively secure and optimize access to our APIs. Our API locks objects on some operations to prevent the disruption caused by concurrent workloads that could potentially lead to inconsistent outcomes.
This proactive measure not only ensures the continued integrity and performance of our APIs but also guarantees a high standard of security for our users. Once triggered, the API lock initiates a controlled pause in access, preventing any potential threats from compromising the system.
# 👋 Welcome to Hyperswitch API Reference
Source: https://api-reference.hyperswitch.io/introduction
Hyperswitch provides a collection of APIs that enable you to process and manage payments. Our APIs accept and return JSON in the HTTP body and return standard HTTP response codes. You can consume the APIs directly using your favorite HTTP/REST library.
Create your first payment using Hyperswitch APIs.
Discover how to process one-time and recurring payments, save payment methods, and more.
Save customer payment methods securely for future transactions
Host Hyperswitch on-premise? Utilize our full API suite.
## Environment
We have a testing environment referred to "sandbox," which you can set up to test API calls without affecting production data. You can sign up on our Dashboard to get API keys to access Hyperswitch API.
Use the following base URLs when making requests to the APIs:
| Environment | Base URL |
| - | - |
| Sandbox | [https://sandbox.hyperswitch.io](https://sandbox.hyperswitch.io) |
| Production | [https://api.hyperswitch.io](https://api.hyperswitch.io) |
If you **do not hold a PCI certification** to collect and store card data on your servers, we recommend using [**Unified Checkout**](https://hyperswitch.io/docs/sdkIntegrations/unifiedCheckoutWeb/#unified-checkout) to accept card information from users.
## Authentication and API keys
Hyperswitch authenticates your API requests using your account’s API keys. Each account has two API keys for authentication:
| Key | Example | When to Use |
| - | - | - |
| Secret key (API-key) | `snd_c69***` | Used to authenticate API requests from your merchant server. **Don’t expose this key** on a website or embed it in a mobile application. |
| Publishable key | `pk_snd_3b3***` | Used to authenticate API requests from your app’s client. Can be publicly-accessible in your web or mobile app’s client-side code. |
Get your [API key](https://app.hyperswitch.io/developers?tabIndex=1) and [Publishable Key](https://app.hyperswitch.io/home)
[Postman Collection](https://www.postman.com/hyperswitch/workspace/hyperswitch-development/collection/25176162-630b5353-7002-44d1-8ba1-ead6c230f2e3)
## Payment Status Lifecycle
Hyperswitch handles the complex functionality of a comprehensive payments flow through the Payments object that transitions through multiple states during its payments lifecycle. Given below are the various statuses a payment can have:
| Payment Status | Description |
| - | - |
| requires\_payment\_method | Once you create a payment through payments/create endpoint with no payment method attached to it, the payments object transitions to ‘requires\_payment\_method’. |
| requires\_confirmation | After attaching a payment method through payments/update endpoint, the payments object requires you to confirm the payment. |
| requires\_customer\_action | Once the payment is confirmed through payments/confirm endpoint, if additional authentication is required, the payments object transitions to this state. |
| requires\_capture | If you want to do separate authorize and capture, setting capture field to ‘manual’ during payments/create or confirm call will transition the payment object to this state after customer action succeeds. |
| processing | In case of automatic capture, the payments object transitions to processing state post confirm call and subsequent customer authentication if available. |
| succeeded | The payments object reaches success state post confirmation of successful processing from the payment processor. |
| failed | The payments object transitions to a failed state when the payment processor confirms the processing failure. |
## Payment Lifecycle - more payment states
| Payment Status | Description |
| - | - |
| Merchant Action Required | The payment is waiting on some action from the merchant (e.g., manual fraud approval) |
| Partially Captured | The payment has been captured partially, and the remaining amount cannot be captured |
| Partially Captured and Capturable | The payment has been captured partially and the remaining amount is capturable |
| Partially Authorized and Requires Capture | The payment has been authorized for a partial amount and requires capture |
| Conflicted | There has been a discrepancy between the amount/currency sent in the request and the amount/currency received by the processor. Applicable for Crypto payments and Bank transfer payments (EU) where user can change the amount on Bank page |
| Expired | The payment expired before it could be captured |
## Redirect URL
This is what a url looks like after redirection
`https://app.hyperswitch.io?status=succeeded&payment_intent_client_secret=pay_NCv9vc19f8aa75OpFxH8_secret_V4zAc7V0C8WAw6FECMKM&amount=10000&manual_retry_allowed=false&signature=4fae0cfa775e4551db9356563d4b98b55662fe3c1c945fe215d90ccf3541282c535909ae901d82174d6b1e46ba1684aa0aa4c8861be0e2a9ef6f950a975d5014&signature_algorithm=HMAC-SHA512`
The available parameters are as follows:
* **status** - can have values of `succeeded`, `processing`and `failed`.
* **payment\_intent\_client\_secret** - This is the client secret associated with the payment. This can be used to retrieve the payment status from hyperswitch.
* **manual\_retry\_allowed** - whether this payment can be retried or not.
* **signature** - A HMAC signature of the payload, this can be verified using the `payment_response_hash_key`.
* **signature\_algorithm** - The HMAC algorithm used to calculate the signature.
# Authentication - Create
Source: https://api-reference.hyperswitch.io/v1/authentication/authentication--create
post /authentication
Create a new authentication for accessing our APIs from your servers.
# Authentication - GET Eligibility Check
Source: https://api-reference.hyperswitch.io/v1/authentication/authentication--get-eligibility-check
get /authentication/{authentication_id}/eligibility-check
# Authentication - POST Eligibility Check
Source: https://api-reference.hyperswitch.io/v1/authentication/authentication--post-eligibility-check
post /authentication/{authentication_id}/eligibility-check
# Profile - Create
Source: https://api-reference.hyperswitch.io/v1/business-profile/business-profile--create
post /account/{account_id}/business_profile
Creates a new *profile* for a merchant
# Profile - Update
Source: https://api-reference.hyperswitch.io/v1/business-profile/business-profile--update
post /account/{account_id}/business_profile/{profile_id}
Update the *profile*
# Payment Method - Set Default Payment Method for Customer
Source: https://api-reference.hyperswitch.io/v1/customer-set-default-payment-method/customers--set-default-payment-method
post /{customer_id}/payment_methods/{payment_method_id}/default
Set the Payment Method as Default for the Customer.
# Customers - Create
Source: https://api-reference.hyperswitch.io/v1/customers/customers--create
post /customers
Creates a customer object and stores the customer details to be reused for future payments.
Incase the customer already exists in the system, this API will respond with the customer details.
# Customers - Delete
Source: https://api-reference.hyperswitch.io/v1/customers/customers--delete
delete /customers/{customer_id}
Delete a customer record.
# Customers - List
Source: https://api-reference.hyperswitch.io/v1/customers/customers--list
get /customers/list
Lists all the customers for a particular merchant id.
# Customers - Retrieve
Source: https://api-reference.hyperswitch.io/v1/customers/customers--retrieve
get /customers/{customer_id}
Retrieves a customer's details.
# Customers - Retrieve using Merchant Reference ID
Source: https://api-reference.hyperswitch.io/v1/customers/customers--retrieve-by-merchant-reference-id
get /v1/customers/reference/{merchant_reference_id}
Retrieves a customer's details using the merchant supplied reference ID.
# Customers - Update
Source: https://api-reference.hyperswitch.io/v1/customers/customers--update
post /customers/{customer_id}
Updates the customer's details in a customer object.
# Disputes - Accept Dispute
Source: https://api-reference.hyperswitch.io/v1/disputes/disputes--accept
post /disputes/accept/{dispute_id}
Accepts a dispute
# Disputes - Attach Evidence to Dispute
Source: https://api-reference.hyperswitch.io/v1/disputes/disputes--attach-evidence
put /disputes/evidence
Attaches an uploaded evidence file to a dispute
# Disputes - Delete Evidence attached to a Dispute
Source: https://api-reference.hyperswitch.io/v1/disputes/disputes--delete-evidence
delete /disputes/evidence
Deletes an evidence file attached to a dispute
# Disputes - Get Disputes Aggregate
Source: https://api-reference.hyperswitch.io/v1/disputes/disputes--get-aggregate
get /disputes/aggregate
Gets a count of disputes grouped by their status for a merchant within a time range
# Disputes - Get Disputes Aggregate for Profiles
Source: https://api-reference.hyperswitch.io/v1/disputes/disputes--get-aggregate-profiles
get /disputes/profile/aggregate
Gets a count of disputes grouped by their status for the given profiles within a time range
# Disputes - Disputes Filters
Source: https://api-reference.hyperswitch.io/v1/disputes/disputes--get-filters
get /disputes/filter
Lists all the filters associated with disputes
# Disputes - Disputes Filters Profile
Source: https://api-reference.hyperswitch.io/v1/disputes/disputes--get-filters-profiles
get /disputes/profile/filter
Lists all the filters associated with disputes for the given profiles
# Disputes - List Disputes
Source: https://api-reference.hyperswitch.io/v1/disputes/disputes--list
get /disputes/list
Lists all the Disputes for a merchant
# Disputes - List Disputes for The Given Profiles
Source: https://api-reference.hyperswitch.io/v1/disputes/disputes--list-profiles
get /disputes/profile/list
Lists all the Disputes for a merchant
# Disputes - Retrieve Dispute
Source: https://api-reference.hyperswitch.io/v1/disputes/disputes--retrieve
get /disputes/{dispute_id}
Retrieves a dispute
# Disputes - Retrieve Dispute Evidence
Source: https://api-reference.hyperswitch.io/v1/disputes/disputes--retrieve-evidence
get /disputes/evidence/{dispute_id}
Retrieves evidence for a dispute
# Disputes - Uploads Dispute Evidence
Source: https://api-reference.hyperswitch.io/v1/disputes/disputes--submit-evidence
post /disputes/evidence
Uploads evidence for a dispute
# Mandates customer mandates list
Source: https://api-reference.hyperswitch.io/v1/mandates/mandates--customer-mandates-list
post /customers/{customer_id}/mandates
# Mandates - Retrieve Mandate
Source: https://api-reference.hyperswitch.io/v1/mandates/mandates--retrieve-mandate
get /mandates/{mandate_id}
Retrieves a mandate created using the Payments/Create API
# Mandates - Revoke Mandate
Source: https://api-reference.hyperswitch.io/v1/mandates/mandates--revoke-mandate
post /mandates/revoke/{mandate_id}
Revokes a mandate created using the Payments/Create API
# Merchant Account - Create
Source: https://api-reference.hyperswitch.io/v1/merchant-account/merchant-account--create
post /accounts
Create a new account for a *merchant* and the *merchant* could be a seller or retailer or client who likes to receive and send payments.
# Merchant Account - Delete
Source: https://api-reference.hyperswitch.io/v1/merchant-account/merchant-account--delete
delete /accounts/{account_id}
Delete a *merchant* account
# Merchant Account - KV Status
Source: https://api-reference.hyperswitch.io/v1/merchant-account/merchant-account--kv-status
post /accounts/{account_id}/kv
Toggle KV mode for the Merchant Account
# Merchant Account - Retrieve
Source: https://api-reference.hyperswitch.io/v1/merchant-account/merchant-account--retrieve
get /accounts/{account_id}
Retrieve a *merchant* account details.
# Merchant Account - Update
Source: https://api-reference.hyperswitch.io/v1/merchant-account/merchant-account--update
post /accounts/{account_id}
Updates details of an existing merchant account. Helpful in updating merchant details such as email, contact details, or other configuration details like webhook, routing algorithm etc
# Organization - Create
Source: https://api-reference.hyperswitch.io/v1/organization/organization--create
post /organization
Create a new organization
# Organization - Retrieve
Source: https://api-reference.hyperswitch.io/v1/organization/organization--retrieve
get /organization/{id}
Retrieve an existing organization
# Organization - Update
Source: https://api-reference.hyperswitch.io/v1/organization/organization--update
put /organization/{id}
Create a new organization for .
# List customer saved payment methods for a Payment
Source: https://api-reference.hyperswitch.io/v1/payment-methods/list-customer-saved-payment-methods-for-a-payment
get /customers/payment_methods
Lists all the applicable payment methods for a particular payment tied to the `client_secret`.
# List payment methods for a Customer
Source: https://api-reference.hyperswitch.io/v1/payment-methods/list-payment-methods-for-a-customer
get /customers/{customer_id}/payment_methods
Lists all the applicable payment methods for a particular Customer ID.
# List payment methods for a Merchant
Source: https://api-reference.hyperswitch.io/v1/payment-methods/list-payment-methods-for-a-merchant
get /account/payment_methods
Lists the applicable payment methods for a particular Merchant ID.
Use the client secret and publishable key authorization to list all relevant payment methods of the merchant for the payment corresponding to the client secret.
# List payment methods for a Payment
Source: https://api-reference.hyperswitch.io/v1/payment-methods/list-payment-methods-for-a-payment-via-client-sdk
get /payments/{payment_id}/client
Client SDK endpoint. Returns a unified response combining merchant-enabled
payment methods and customer saved payment methods, filtered via Euclid
constraint graph and session flow routing.
Supported auth:
- SDK auth via `Authorization`.
- Publishable-key auth via `api-key: pk_...` and `client_secret` query param.
- Merchant API-key auth via `api-key: `.
# Payment Method - Delete
Source: https://api-reference.hyperswitch.io/v1/payment-methods/payment-method--delete
delete /payment_methods/{method_id}
Deletes a payment method of a customer.
# Payment Method - Retrieve
Source: https://api-reference.hyperswitch.io/v1/payment-methods/payment-method--retrieve
get /payment_methods/{method_id}
Retrieves a payment method of a customer.
# Payment Method - Set Default Payment Method for Customer
Source: https://api-reference.hyperswitch.io/v1/payment-methods/payment-method--set-default-payment-method-for-customer
post /{customer_id}/payment_methods/{payment_method_id}/default
Set the Payment Method as Default for the Customer.
# Payment Method - Update
Source: https://api-reference.hyperswitch.io/v1/payment-methods/payment-method--update
post /payment_methods/{method_id}/update
Update an existing payment method of a customer.
This API is useful for use cases such as updating the card number for expired cards to prevent discontinuity in recurring payments.
# PaymentMethods - Create
Source: https://api-reference.hyperswitch.io/v1/payment-methods/paymentmethods--create
post /payment_methods
Creates and stores a payment method against a customer.
In case of cards, this API should be used only by PCI compliant merchants.
# Payment flows
Source: https://api-reference.hyperswitch.io/v1/payments/payment--flows
Hyperswitch provides flexible payment processing with multiple flow patterns to accommodate different business needs. The system supports one-time payments, saved payment methods, and recurring billing through a comprehensive API design.
```mermaid theme={null}
graph TD
A["Payment Request"] --> B{"Payment Type"}
B -->|One-time| C["One-time Payment Flows"]
B -->|Save for Future| D["Payment Method Storage"]
B -->|Recurring| E["Recurring Payment Flows"]
C --> C1["Instant Payment"]
C --> C2["Manual Capture"]
C --> C3["Decoupled Flow"]
C --> C4["3DS Authentication"]
D --> D1["Save During Payment"]
D --> D2["List Saved Methods"]
E --> E1["Setup (CIT)"]
E --> E2["Execute (MIT)"]
```
## One-Time Payment Patterns
### 1. Instant Payment (Automatic Capture)
**Use Case:** Simple, immediate payment processing
**Endpoint:**
`POST /payments`
```mermaid theme={null}
sequenceDiagram
participant Client
participant Hyperswitch
participant Processor
Client->>Hyperswitch: POST /payments
{confirm: true, capture_method: "automatic"}
Hyperswitch->>Processor: Authorize + Capture
Processor-->>Hyperswitch: Payment Complete
Hyperswitch-->>Client: Status: succeeded
```
**Required Fields:**
* `confirm: true`
* `capture_method: "automatic"`
* `payment_method`
**Final Status:** `succeeded`
### 2. Two-Step Manual Capture
**Use Case:** Deferred settlement (e.g., ship before charging)
```mermaid theme={null}
sequenceDiagram
participant Client
participant Hyperswitch
participant Processor
Client->>Hyperswitch: POST /payments
{confirm: true, capture_method: "manual"}
Hyperswitch->>Processor: Authorize Only
Processor-->>Hyperswitch: Authorization Hold
Hyperswitch-->>Client: Status: requires_capture
Note over Client: Ship goods, then capture
Client->>Hyperswitch: POST /payments/{id}/capture
Hyperswitch->>Processor: Capture Funds
Processor-->>Hyperswitch: Capture Complete
Hyperswitch-->>Client: Status: succeeded
```
**Flow:**
1. **Authorize:** `POST /payments` with `capture_method: "manual"`
2. **Status:** `requires_capture`
3. **Capture:** `POST /payments/{payment_id}/capture`
4. **Final Status:** `succeeded`
### 3. Fully Decoupled Flow
**Use Case:** Complex checkout journeys with multiple modification steps. Useful in headless checkout or B2B portals where data is filled progressively.
```mermaid theme={null}
sequenceDiagram
participant Client
participant Hyperswitch
Client->>Hyperswitch: POST /payments
(Create Intent)
Hyperswitch-->>Client: payment_id + client_secret
Client->>Hyperswitch: POST /payments/{id}
(Update: customer, amount, etc.)
Hyperswitch-->>Client: Updated Intent
Client->>Hyperswitch: POST /payments/{id}/confirm
(Final Confirmation)
Hyperswitch-->>Client: Status: succeeded/requires_capture
opt Manual Capture
Client->>Hyperswitch: POST /payments/{id}/capture
Hyperswitch-->>Client: Status: succeeded
end
```
**Endpoints:**
* **Create:**
`POST /payments`
* **Update:**
`POST /payments/{payment_id}`
* **Confirm:**
`POST /payments/{payment_id}/confirm`
* **Capture:**
`POST /payments/{payment_id}/capture` (if manual)
### 4. 3D Secure Authentication Flow
**Use Case:** Enhanced security with customer authentication
```mermaid theme={null}
sequenceDiagram
participant Client
participant Hyperswitch
participant Customer
participant Bank
Client->>Hyperswitch: POST /payments
{authentication_type: "three_ds"}
Hyperswitch-->>Client: Status: requires_customer_action
+ redirect_url
Client->>Customer: Redirect to 3DS page
Customer->>Bank: Complete 3DS Challenge
Bank-->>Hyperswitch: Authentication Result
Hyperswitch->>Hyperswitch: Resume Payment Processing
Hyperswitch-->>Client: Status: succeeded
```
**Additional Fields:**
* `authentication_type: "three_ds"`
**Status Progression:** `processing` → `requires_customer_action` → `succeeded`
## Payment Method Management
### 1. Saving Payment Methods
```mermaid theme={null}
graph LR
A["Payment Request"] --> B["Add setup_future_usage"]
B --> C{"Usage Type"}
C -->|"off_session"| D["For Recurring/MIT"]
C -->|"on_session"| E["For Customer-Present"]
D --> F["payment_method_id Returned"]
E --> F
```
**During Payment Creation:**
* Add `setup_future_usage: "off_session"` or `"on_session"`
* Include `customer_id`
* **Result:** `payment_method_id` returned on success
**Understanding `setup_future_usage`:**
* **`on_session`**: Use when the customer is actively present during the transaction. This is typical for scenarios like saving card details for faster checkouts in subsequent sessions where the customer will still be present to initiate the payment (e.g., card vaulting for e-commerce sites).
* **`off_session`**: Use when you intend to charge the customer later without their active involvement at the time of charge. This is suitable for subscriptions, recurring billing, or merchant-initiated transactions (MITs) where the customer has pre-authorized future charges.
### 2. Using Saved Payment Methods
```mermaid theme={null}
sequenceDiagram
participant Client
participant Hyperswitch
Client->>Hyperswitch: POST /payments/create
{customer_id}
Hyperswitch-->>Client: client_secret
Client->>Hyperswitch: GET /customers/payment_methods
{client_secret, publishable_key}
Hyperswitch-->>Client: List of payment_tokens
Client->>Hyperswitch: POST /payments/{id}/confirm
{payment_token}
Hyperswitch-->>Client: Payment Result
```
**Steps:**
1. **Initiate:** Create payment with `customer_id`
2. **List:** Get saved cards via `GET /customers/payment_methods`
3. **Confirm:** Use selected `payment_token` in confirm call
### PCI Compliance and `payment_method_id`
Storing `payment_method_id` (which is a token representing the actual payment instrument, which could be a payment token, network token, or payment processor token) significantly reduces your PCI DSS scope. Hyperswitch securely stores the sensitive card details and provides you with this token. While you still need to ensure your systems handle `payment_method_id` and related customer data securely, you avoid the complexities of storing raw card numbers. Always consult with a PCI QSA to understand your specific compliance obligations.
## Recurring Payment Flows
### 3. Customer-Initiated Transaction (CIT) Setup
```mermaid theme={null}
graph TD
A["CIT Setup"] --> B{"Setup Type"}
B -->|"With Charge"| C["Amount > 0
setup_future_usage: off_session"]
B -->|"Zero Dollar Auth"| D["Amount: 0
payment_type: setup_mandate"]
C --> E["payment_method_id"]
D --> E
```
**Option 1 - Setup with Charge:**
* `setup_future_usage: "off_session"`
* `amount > 0`
**Option 2 - Zero Dollar Authorization:**
* `setup_future_usage: "off_session"`
* `amount: 0`
* `payment_type: "setup_mandate"`
### 4. Merchant-Initiated Transaction (MIT) Execution
```mermaid theme={null}
sequenceDiagram
participant Merchant
participant Hyperswitch
participant Processor
Note over Merchant: Subscription billing trigger
Merchant->>Hyperswitch: POST /payments
{off_session: true, recurring_details}
Hyperswitch->>Processor: Process with saved payment_method_id
Processor-->>Hyperswitch: Payment Result
Hyperswitch-->>Merchant: Status: succeeded
```
**Required Fields:**
* `off_session: true`
* `recurring_details: {
"type": "payment_method_id",
"data": ""}`
**Use Case:** Subscription charges, scheduled billing without customer interaction
## Status Flow Summary
```mermaid theme={null}
stateDiagram-v2
[*] --> RequiresConfirmation
RequiresConfirmation --> Processing: confirm=true
Processing --> RequiresCustomerAction: 3DS needed
RequiresCustomerAction --> Processing: 3DS complete
Processing --> RequiresCapture: manual capture
Processing --> Succeeded: automatic capture
RequiresCapture --> Succeeded: capture API call
RequiresCapture --> PartiallyCaptured: partial capture
PartiallyCaptured --> [*]
Succeeded --> [*]
Processing --> Failed: payment failed
Failed --> [*]
```
## Notes
* **Terminal States:** `succeeded`, `failed`, `cancelled`, `partially_captured` are terminal states requiring no further action
* **Capture Methods:** System supports `automatic` (funds captured immediately), `manual` (funds captured in a separate step), `manual_multiple` (funds captured in multiple partial amounts via separate steps), and `scheduled` (funds captured automatically at a future predefined time) capture methods.
* **Authentication:** 3DS authentication automatically resumes payment processing after customer completion
* **MIT Compliance:** Off-session recurring payments follow industry standards for merchant-initiated transactions
# Payments - Cancel
Source: https://api-reference.hyperswitch.io/v1/payments/payments--cancel
post /payments/{payment_id}/cancel
A Payment could can be cancelled when it is in one of these statuses: `requires_payment_method`, `requires_capture`, `requires_confirmation`, `requires_customer_action`.
# Payments - Cancel Post Capture
Source: https://api-reference.hyperswitch.io/v1/payments/payments--cancel-post-capture
post /payments/{payment_id}/cancel_post_capture
A Payment could can be cancelled when it is in one of these statuses: `succeeded`, `partially_captured`, `partially_captured_and_capturable`.
# Payments - Cancel Post Capture Retrieve
Source: https://api-reference.hyperswitch.io/v1/payments/payments--cancel-post-capture-retrieve
get /payments/{payment_id}/cancel_post_capture
Retrieves a canceled Payment post capture
# Payments - Capture
Source: https://api-reference.hyperswitch.io/v1/payments/payments--capture
post /payments/{payment_id}/capture
Captures the funds for a previously authorized payment intent where `capture_method` was set to `manual` and the payment is in a `requires_capture` state.
Upon successful capture, the payment status usually transitions to `succeeded`.
The `amount_to_capture` can be specified in the request body; it must be less than or equal to the payment's `amount_capturable`. If omitted, the full capturable amount is captured.
A payment must be in a capturable state (e.g., `requires_capture`). Attempting to capture an already `succeeded` (and fully captured) payment or one in an invalid state will lead to an error.
# Payments complete authorize
Source: https://api-reference.hyperswitch.io/v1/payments/payments--complete-authorize
post /{payment_id}/complete_authorize
# Payments - Confirm
Source: https://api-reference.hyperswitch.io/v1/payments/payments--confirm
post /payments/{payment_id}/confirm
Confirms a payment intent that was previously created with `confirm: false`. This action attempts to authorize the payment with the payment processor.
Expected status transitions after confirmation:
- `succeeded`: If authorization is successful and `capture_method` is `automatic`.
- `requires_capture`: If authorization is successful and `capture_method` is `manual`.
- `failed`: If authorization fails.
# Payments - Create
Source: https://api-reference.hyperswitch.io/v1/payments/payments--create
post /payments
Creates a payment resource, which represents a customer's intent to pay.
This endpoint is the starting point for various payment flows:
Use the dropdown on the top right corner of the code snippet to try out different payment scenarios.
# Payments - Extended Authorization
Source: https://api-reference.hyperswitch.io/v1/payments/payments--extend-authorization
post /payments/{payment_id}/extend_authorization
Extended authorization is available for payments currently in the `requires_capture` status
Call this endpoint to increase the authorization validity period
# Payments - External 3DS Authentication
Source: https://api-reference.hyperswitch.io/v1/payments/payments--external-3ds-authentication
post /payments/{payment_id}/3ds/authentication
External 3DS Authentication is performed and returns the AuthenticationResponse
# Payments - Incremental Authorization
Source: https://api-reference.hyperswitch.io/v1/payments/payments--incremental-authorization
post /payments/{payment_id}/incremental_authorization
Authorized amount for a payment can be incremented if it is in status: requires_capture
# Payments - List
Source: https://api-reference.hyperswitch.io/v1/payments/payments--list
get /payments/list
To list the *payments*
# Payments - Retrieve
Source: https://api-reference.hyperswitch.io/v1/payments/payments--retrieve
get /payments/{payment_id}
Retrieves a Payment. This API can also be used to get the status of a previously initiated payment or next action for an ongoing payment
# Payments - Session token
Source: https://api-reference.hyperswitch.io/v1/payments/payments--session-token
post /payments/session_tokens
Creates a session object or a session token for wallets like Apple Pay, Google Pay, etc. These tokens are used by Hyperswitch's SDK to initiate these wallets' SDK.
# Payments - Submit Eligibility Data
Source: https://api-reference.hyperswitch.io/v1/payments/payments--submit-eligibility-data
post /payments/{payment_id}/eligibility
Runs eligibility checks (blocklist, card testing guard) and calculates an external surcharge
in a single call. Intended to be called by the SDK before the final confirm step.
- If eligibility is denied the response will contain `sdk_next_action: deny` and no surcharge details.
- If the merchant has no surcharge connector configured, `surcharge_details` will be `null`.
- Surcharge calculation is best-effort: if the external call fails the payment still proceeds
with `surcharge_details: null`.
# Payments - Update
Source: https://api-reference.hyperswitch.io/v1/payments/payments--update
post /payments/{payment_id}
To update the properties of a *PaymentIntent* object. This may include attaching a payment method, or attaching customer object or metadata fields after the Payment is created
# Payments - Update Metadata
Source: https://api-reference.hyperswitch.io/v1/payments/payments--update-metadata
post /payments/{payment_id}/update_metadata
# Payments Link - Retrieve
Source: https://api-reference.hyperswitch.io/v1/payments/payments-link--retrieve
get /payment_link/{payment_link_id}
To retrieve the properties of a Payment Link. This may be used to get the status of a previously initiated payment or next action for an ongoing payment
# Setup instructions
Source: https://api-reference.hyperswitch.io/v1/payments/setup--instructions
The **Hyperswitch Payments API** enables businesses to **accept, process, and manage payments seamlessly**. It supports the entire **payment lifecycle**—from creation to capture, refunds, and disputes—allowing smooth integration of **various payment methods** into any application with minimal complexity.
### How to try your first payment through hyperswitch?
You have two options to use the Payments API:
1. **Sandbox API Key (Dashboard)** – Quick testing without setup.
2. **Self-Deploy** – Create merchants and API keys through Rest API.
Each option has specific nuances, we have mentioned the differences in the below step by step guide
We recommend using our [Dashboard](https://app.hyperswitch.io/dashboard/login) to generate API Key and setting up Connectors (Step 4) for faster trial and simple setup.
This account is representative of you or your organization that would like to accept payments from different payment connectors
Access the [Dashboard](https://app.hyperswitch.io/dashboard/login) and sign up -> **Sign up here is equivalent to creating a Merchant Account**
Use the admin api key and the [Merchant Account - Create](api-reference/merchant-account/merchant-account--create) endpoint to create your Merchant Account
You can now generate an API key that will be the secret key used to authenticate your payment request
In Dashboard go to Developer-> API Keys -> +Create New Api Key. This key can be used in your API requests for authentication.
Use the admin api key and the [Merchant Account - Create](api-reference/merchant-account/merchant-account--create) endpoint to create your Merchant Account
Connect the payment [connectors](api-reference/merchant-connector-account/merchant-connector--create) and payment methods that your organization will accept. Connectors could be a payment processor/facilitator/acquirer or a provider of specialized services like Fraud/Accounting
In Dashboard go to Connectors -> +Connect a Dummy Processor. Choose the payments methods to enable and complete setup.
Use the admin api key and the [Connector Account](api-reference/merchant-connector-account/merchant-connector--create) endpoints to set up a connector
You are all set! Go ahead and try the [Payments API](api-reference/payments/payments--create), be sure to try the different use cases provided
Test the use cases you are interested in and in case of difficulty, feel free to contact us on our [slack channel](https://join.slack.com/t/hyperswitch-io/shared_invite/zt-2jqxmpsbm-WXUENx022HjNEy~Ark7Orw)
# Payouts - Cancel
Source: https://api-reference.hyperswitch.io/v1/payouts/payouts--cancel
post /payouts/{payout_id}/cancel
# Payouts - Confirm
Source: https://api-reference.hyperswitch.io/v1/payouts/payouts--confirm
post /payouts/{payout_id}/confirm
# Payouts - Create
Source: https://api-reference.hyperswitch.io/v1/payouts/payouts--create
post /payouts/create
Create a payout with `payout_method_data` (including raw card details) or a saved `payout_method_id`.
## External-vault card payouts
Use a card saved during a payment. Provide a unique `payout_id`, the saved `payout_method_id`, and the card owner's `customer_id` or `customer.id`.
Set `confirm=true`, `auto_fulfill=true`, `payout_type=card`, and `recurring=false`. These values apply when omitted for external-vault payouts. Send the request from your server; no separate confirmation call is required. For this flow, use the saved `payout_method_id` instead of inline `payout_method_data`. Do not send vault tokens or credentials.
## Retry handling
After a timeout, retrieve the payout using its `payout_id` before submitting another request. Do not create a new payout ID to retry the same payout.
Creating a payout with an existing `payout_id` returns a duplicate-payout error. Use `merchant_order_reference_id` for reconciliation, not retry protection.
# Payouts - List using filters
Source: https://api-reference.hyperswitch.io/v1/payouts/payouts--filter
post /payouts/list
# Payouts - Fulfill
Source: https://api-reference.hyperswitch.io/v1/payouts/payouts--fulfill
post /payouts/{payout_id}/fulfill
# Payouts - List
Source: https://api-reference.hyperswitch.io/v1/payouts/payouts--list
get /payouts/list
# Payouts - List available filters
Source: https://api-reference.hyperswitch.io/v1/payouts/payouts--list-filters
post /payouts/filter
# Payouts - Retrieve
Source: https://api-reference.hyperswitch.io/v1/payouts/payouts--retrieve
get /payouts/{payout_id}
# Payouts - Update
Source: https://api-reference.hyperswitch.io/v1/payouts/payouts--update
post /payouts/{payout_id}
# Refunds - Create
Source: https://api-reference.hyperswitch.io/v1/refunds/refunds--create
post /refunds
Creates a refund against an already processed payment. In case of some processors, you can even opt to refund only a partial amount multiple times until the original charge amount has been refunded
# Refunds - List
Source: https://api-reference.hyperswitch.io/v1/refunds/refunds--list
post /refunds/list
Lists all the refunds associated with the merchant, or for a specific payment if payment_id is provided
# Refunds - Retrieve
Source: https://api-reference.hyperswitch.io/v1/refunds/refunds--retrieve
get /refunds/{refund_id}
Retrieves a Refund. This may be used to get the status of a previously initiated refund
# Refunds - Update
Source: https://api-reference.hyperswitch.io/v1/refunds/refunds--update
post /refunds/{refund_id}
Updates the properties of a Refund object. This API can be used to attach a reason for the refund or metadata fields
# Customers - Create
Source: https://api-reference.hyperswitch.io/v2/customers/customers--create-v1
post /v1/customers
Creates a customer object and stores the customer details to be reused for future payments.
Incase the customer already exists in the system, this API will respond with the customer details.
# Customers - Delete
Source: https://api-reference.hyperswitch.io/v2/customers/customers--delete-v1
delete /v1/customers/{id}
Delete a customer record.
# Customers - List
Source: https://api-reference.hyperswitch.io/v2/customers/customers--list-v1
get /v1/customers/list
Lists all the customers for a particular merchant id.
# Customers - Retrieve
Source: https://api-reference.hyperswitch.io/v2/customers/customers--retrieve-v1
get /v1/customers/{id}
Retrieves a customer's details.
# Customers - Update
Source: https://api-reference.hyperswitch.io/v2/customers/customers--update-v1
put /v1/customers/{id}
Updates the customer's details in a customer object.
# Payment Method Session - Confirm a payment method session
Source: https://api-reference.hyperswitch.io/v2/payment-method-session/payment-method-session--confirm-a-payment-method-session-v1
post /v1/payment-method-sessions/{id}/confirm
**Confirms a payment method session object with the payment method data**
# Payment Method Session - Create
Source: https://api-reference.hyperswitch.io/v2/payment-method-session/payment-method-session--create-v1
post /v1/payment-method-sessions
Create a payment method session for a customer
This is used to list the saved payment methods for the customer
The customer can also add a new payment method using this session
# Payment Method Session - Delete a saved payment method
Source: https://api-reference.hyperswitch.io/v2/payment-method-session/payment-method-session--delete-a-saved-payment-method-v1
delete /v1/payment-method-sessions/{id}
Delete a saved payment method from the given payment method session.
# Payment Method Session - List Payment Methods
Source: https://api-reference.hyperswitch.io/v2/payment-method-session/payment-method-session--list-payment-methods-v1
get /v1/payment-method-sessions/{id}/list-payment-methods
List payment methods for the given payment method session.
This endpoint lists the enabled payment methods for the profile and the saved payment methods of the customer.
# Payment Method Session - Retrieve
Source: https://api-reference.hyperswitch.io/v2/payment-method-session/payment-method-session--retrieve-v1
get /v1/payment-method-sessions/{id}
Retrieve the payment method session
# Payment Method Session - Update a saved payment method
Source: https://api-reference.hyperswitch.io/v2/payment-method-session/payment-method-session--update-a-saved-payment-method-v1
put /v1/payment-method-sessions/{id}/update-saved-payment-method
Update a saved payment method from the given payment method session.
# Payment Method - Create
Source: https://api-reference.hyperswitch.io/v2/payment-methods/payment-method--create-v1
post /v1/payment-methods
Creates and stores a payment method against a customer. In case of cards, this API should be used only by PCI compliant merchants.
# Payment Method - Delete
Source: https://api-reference.hyperswitch.io/v2/payment-methods/payment-method--delete-v1
delete /v1/payment-methods/{id}
Deletes a payment method of a customer.
# Payment Method - List Customer Saved Payment Methods
Source: https://api-reference.hyperswitch.io/v2/payment-methods/payment-method--list-customer-saved-payment-methods-v1
get /v1/customers/{id}/saved-payment-methods
List the payment methods saved for a customer
# Payment Method - Get Payment Method Token Data
Source: https://api-reference.hyperswitch.io/v2/payment-methods/payment-method--payment-method-token-to-payment-method-id-v1
get /v1/payment-methods/token/{payment_method_temporary_token}/details
Retrieve the Payment method id associated with a payment method token.
# Payment method retrieve v1
Source: https://api-reference.hyperswitch.io/v2/payment-methods/payment-method--retrieve-v1
get /v1/payment-methods/{id}
# Payment Method - Set Default Payment Method for Customer
Source: https://api-reference.hyperswitch.io/v2/payment-methods/payment-method--set-default-payment-method-for-customer-v1
post /v1/{customer_id}/payment-methods/{payment_method_id}/default
Set the Payment Method as Default for the Customer.
# Payment Method - Update
Source: https://api-reference.hyperswitch.io/v2/payment-methods/payment-method--update-v1
put /v1/payment-methods/{id}/update-saved-payment-method
Update an existing payment method of a customer.
# Proxy
Source: https://api-reference.hyperswitch.io/v2/proxy/proxy-v1
post /v1/proxy
Create a proxy request
# Error Codes
Source: https://api-reference.hyperswitch.io/essentials/error_codes
Hyperswitch uses error codes, types, and messages to communicate errors during API calls. There are two main types of error codes: Error Codes and Unified Error Codes.
1. **Error Codes** refer to the error code sent by the connector.
2. **Unified Error Codes** refer to the generic error code sent by the Hyperswitch server, based on the connector's error code. Hyperswitch groups the different error codes from connectors into more generic Unified Error Codes for structured relay of PSP errors, helping merchants derive patterns and determine the next steps for ongoing transactions.
There are four types of Error Codes and five types of Unified Error Codes.
**1. Error Codes:**
The section below contains all the error codes and their corresponding error messages.
| Error Code | Type | Description |
| - | - | - |
| IR | Invalid Request Error | Error caused due to invalid fields and values in API request |
| CE | Connector Error | Errors originating from connector’s end |
| HE | Hyperswitch Error | Errors originating from Hyperswitch’s end |
| WE | Webhook Error | Errors related to Webhooks |
| Error Codes | HTTP Status codes | Error Type | Error message | Error Handling |
| - | - | - | - | - |
| IR\_00 | 501 | server\_not\_available | This API is under development and will be made available soon | No action required. If you require this feature, please reach out to Hyperswitch support |
| IR\_01 | 401 | invalid\_request\_error | API key not provided or invalid API key used. Provide the API key in the Authorization header using api-key (e.g api-key: API\_KEY) or create a new API key from the dashboard | Provide the API key in the Authorization header using api-key (e.g api-key: API\_KEY) or create a new API key from the dashboard |
| IR\_02 | 404 | invalid\_request\_error | Unrecognized request URL | Please recheck and enter the correct request URL. Refer to our API documentation |
| IR\_03 | 405 | invalid\_request\_error | The HTTP method is not applicable for this API | Please recheck the HTTP method used in the request. Refer to our API documentation |
| IR\_04 | 400 | invalid\_request\_error | Missing required param: “field\_name” | Please pass the missing required parameter. Refer to our API documentation |
| IR\_05 | 422 | invalid\_request\_error | “field\_name” contains invalid data. Expected format is “expected\_format” | Please pass the data in the expected format. Refer to our API documentation |
| IR\_06 | 400 | invalid\_request\_error | “message” | Refer to our API documentation for required fields and format |
| IR\_07 | 400 | invalid\_request\_error | Invalid value provided: “field\_name” | Provide a valid value for the required fields in the expected format. Refer to our API documentation |
| IR\_08 | 400 | invalid\_request\_error | Client secret was not provided | Provide the client secret received in payments/create API response |
| IR\_09 | 400 | invalid\_request\_error | The client\_secret provided does not match the client\_secret associated with the Payment | Provide the same client secret received in payments/create API response for the corresponding payment |
| IR\_10 | 400 | invalid\_request\_error | Customer has an existing mandate/subscription | Cancel the active mandates/subscriptions for the customer before proceeding to delete the customer data |
| IR\_11 | 400 | invalid\_request\_error | Customer has already been redacted | Customer has already been redacted. No action required |
| IR\_12 | 400 | invalid\_request\_error | Reached the maximum refund attempts | Maximum refund attempts reached for this payment. Please contact Hyperswitch support for attempting more refunds for the same payment |
| IR\_13 | 400 | invalid\_request\_error | Refund amount exceeds the payment amount | Please verify and pass a refund amount equal to or less than the payment amount |
| IR\_14 | 400 | invalid\_request\_error | This Payment could not be “current\_flow” because it has a “field\_name” of “current\_value”. The expected state is “states” | Please verify the status of the payment and make sure that you are performing an action that is allowed for the current status of the payment |
| IR\_15 | 400 | invalid\_request\_error | Invalid Ephemeral Key for the customer | Please pass the right Ephemeral key for the customer |
| IR\_16 | 400 | invalid\_request\_error | “message” | Typically used when information involving multiple fields or previously provided information doesn’t satisfy a condition. Refer to our API documentation for required fields and format |
| IR\_17 | 401 | invalid\_request\_error | Access forbidden, an invalid JWT token was used | Provide a valid JWT token to access the APIs |
| IR\_18 | 401 | invalid\_request\_error | "message" | The user is not authorised to update the customer, Contact Org. Admin for the appropriate access. |
| IR\_19 | 400 | invalid\_request\_error | "message" | Please check and retry with correct details. Refer to our API documentation |
| IR\_20 | 400 | invalid\_request\_error | "flow" not supported by the "connector" | Requested flow is not supported for this Connector. |
| IR\_21 | 400 | invalid\_request\_error | Missing required params | Please add the required params in the request. Refer to our API documentation |
| IR\_22 | 403 | invalid\_request\_error | Access forbidden. Not authorized to access this "resource" | Contact Org. Admin for the appropriate access. |
| IR\_23 | 400 | invalid\_request\_error | "message" | Use a supported file provider. Refer to our API documentation |
| IR\_24 | 422 | processing\_error | Invalid "wallet\_name" wallet token | Share the correct wallet token. |
| IR\_25 | 400 | invalid\_request\_error | Cannot delete the default payment method | Check if the Payment method is activated. Refer to Control centre to check this. |
| IR\_26 | 400 | invalid\_request\_error | Invalid Cookie | Recheck the site setting for the cookies. |
| IR\_27 | 404 | invalid\_request\_error | Extended card info does not exist | Recheck the card info shared in the request. |
| IR\_28 | 400 | invalid\_request\_error | "message" | Use a valid currency. Refer to our API documentation |
| IR\_29 | 422 | invalid\_request\_error | "message" | The data format is invalid for this request. Refer to our API documentation |
| IR\_30 | 400 | invalid\_request\_error | Merchant connector account is configured with invalid config | Correct the config for merchant connector account |
| IR\_31 | 400 | invalid\_request\_error | Card with the provided iin does not exist | Check the IIN (Issuer Identification Number) and ensure it is correct. |
| IR\_32 | 400 | invalid\_request\_error | The provided card IIN length is invalid, please provide an iin with 6 or 8 digits | Provide a valid IIN with either 6 or 8 digits. |
| IR\_33 | 400 | invalid\_request\_error | File not found / valid in the request | Ensure the required file is included in the request and is valid. Refer to our API documentation |
| IR\_34 | 400 | invalid\_request\_error | Dispute id not found in the request | Ensure that a valid dispute ID is included in the request. |
| IR\_35 | 400 | invalid\_request\_error | File purpose not found in the request or is invalid | Specify a valid file purpose in the request. |
| IR\_36 | 400 | invalid\_request\_error | File content type not found / valid | Ensure the file content type is specified and is valid. |
| IR\_37 | 404 | invalid\_request\_error | "message" | Check the request for the resource being accessed and ensure it exists. |
| IR\_38 | 400 | invalid\_request\_error | "message" | Check for any duplicate entries in the request and correct them. |
| IR\_39 | 400 | invalid\_request\_error | required payment method is not configured or configured incorrectly for all configured connectors | Verify that the required payment method is correctly configured for all connectors in use. |
| CE\_00 | Status codes shared by the connectors | connector\_error | “message” | The error code and message passed from the connectors. Refer to the respective connector’s documentation for more information on the error |
| CE\_01 | 400 | processing\_error | Payment failed during authorization with the connector. Retry payment | Retry the payment again as payment failed at the connector during authorization |
| CE\_02 | 400 | processing\_error | Payment failed during authentication with the connector. Retry payment | Retry the payment again as payment failed at the connector during authentication |
| CE\_03 | 400 | processing\_error | Capture attempt failed while processing with the connector | Capture failed for the payment at the connector. Please retry the payment |
| CE\_04 | 400 | processing\_error | The card data is invalid | Invalid card data passed. Please pass valid card data |
| CE\_05 | 400 | processing\_error | The card has expired | Card expired. Please pass valid card data |
| CE\_06 | 400 | processing\_error | Refund failed while processing with the connector. Retry refund | Refund failed to process at the connector. Please retry refund |
| CE\_07 | 400 | processing\_error | Verification failed while processing with the connector. Retry operation | Retry the operation again as verification failed at the connector |
| CE\_08 | 400 | processing\_error | Dispute operation failed while processing with connector. Retry operation | Retry the operation again as dispute failed at the connector |
| CE\_09 | 400 | invalid\_request\_error | Payout validation failed | Retry the operation again with correct Payout details. |
| HE\_00 | 422,500 | server\_not\_available | Resource not available right now, Please try again later. | Please Wait for a few moments and try again. If the error still persists, please reach out to Hyperswitch support |
| HE\_01 | 400,422 | duplicate\_request | Requested operation(Customer, Payments, Merchants, Refunds etc.) for these identifier already exists. | Please verify the Details(Customer, Payments, Merchants, Refunds, as applicable on the basis of request) and enter valid details. |
| HE\_02 | 404 | object\_not\_found | Requested object(Customer, Payments, Merchants, Refunds etc.) does not exist in our records | Please verify the Details(Customer, Payments, Merchants, Refunds, as applicable on the basis of request) and enter valid details. |
| HE\_03 | 500 | validation\_error | Validation Failed for the requested operation with the given details. | Please verify the details again and enter valid details |
| HE\_04 | 404 | object\_not\_found | Requested object(Customer, Payments, Merchants, Refunds etc.) does not exist in our records | Please verify the Details(Customer, Payments, Merchants, Refunds, as applicable on the basis of request) and enter valid details. |
| HE\_05 | 500 | processing\_error | Missing or invalid tenant details. | Please verify the tenant Details and try again. |
| WE\_01 | 400 | invalid\_request\_error | Failed to authenticate the webhook | Please verify the authentication credentials and try again. |
| WE\_02 | 400 | invalid\_request\_error | Bad request received in webhook | Check the request parameters and format, then try again. |
| WE\_03 | 500 | router\_error | There was some issue processing the webhook | Please try again later. If the issue persists, contact Hyperswitch support. |
| WE\_04 | 404 | object\_not\_found | Webhook resource not found | Ensure the webhook URL is correct and the resource exists. |
| WE\_05 | 400 | invalid\_request\_error | Unable to process the webhook body | Ensure the webhook body is correctly formatted and try again. |
| WE\_06 | 400 | invalid\_request\_error | Merchant Secret set by merchant for webhook source verification is invalid | Verify the Merchant Secret, then try again. |
**2. Unified Error codes:**
The section below contains all the unified error codes and their corresponding error messages.
| Unified Error Code | Unified Error Categorisation | Unified Error message |
| - | - | - |
| UE\_1000 | Customer Error | Issue with payment method details. |
| UE\_2000 | Connector Declines | Issue with Configurations. |
| UE\_3000 | Connector Error | Technical issue with PSP. |
| UE\_4000 | Integration Error | Issue in the integration. |
| UE\_9000 | Others | Something went wrong. |
## Error Details Structure
Hyperswitch returns a structured `error_details` object for failed payments.
This object combines error information from the connector (PSP), the issuer (bank), and Hyperswitch's own interpretation.
**Unified Details**
This section is Hyperswitch's understanding of the failure. It is created by looking at the issuer and connector error signals and mapping them to a standard meaning.
* **Category** - The high-level unified error code (for example `UE_1000` for payment method issues).
* **Message** - High level unified error message that is consistent across different connectors.
* **Standardised Code** - Code that identifies the specific cause for a failure within a broader error category such as `INVALID_EXPIRY_DATE`.
* **Description** - A detailed description of the error intended for debugging, analytics, and support teams.
* **User Guidance Message** - A user-friendly message that can be safely displayed to the customer. This message provides guidance on what the user should do to resolve the issue.
* **Recommended Action** - A field that tells merchants what action to take after a payment failure.
| Action | Description |
| - | - |
| `do_not_retry` | Never retry with same card |
| `retry_later` | Retry after some time |
| `retry_after_1_hour` | Retry after 1 hour |
| `retry_after_24_hours` | Retry after 24 hours |
| `retry_after_2_days` | Retry after 2 days |
| `retry_after_4_days` | Retry after 4 days |
| `retry_after_6_days` | Retry after 6 days |
| `retry_after_8_days` | Retry after 8 days |
| `retry_after_10_days` | Retry after 10 days |
| `retry_after_instrument_update` | Retry after updating payment details |
| `retry_with_different_payment_method_data` | Use different payment method |
| `stop_recurring` | Stop recurring payments |
## Enhanced Errors
This table provides a standardized mapping that translates granular payment error into consistent standardised codes, customer-facing messages and description. The classification mappings, user guidance message and descriptions are subject to change at any time.
| Standardised Code | Unified Code(Category) | Unified Message(Message) | User Guidance Message | Description |
| - | - | - | - | - |
| **PAYMENT\_METHOD\_ISSUE** | **UE\_1000** | **Issue with payment method details** | **Issue with Payment Method details** | **Issue with Payment Method details** |
| INVALID\_CARD\_NUMBER | UE\_1000 | Issue with payment method details | The card number doesn't look right. Please check it and try again | The card number is invalid |
| INVALID\_EXPIRY\_DATE | UE\_1000 | Issue with payment method details | The card's expiry date seems incorrect or has passed. Update it or use another card. | Expiry date is in the past or improperly formatted. |
| INVALID\_CVV | UE\_1000 | Issue with payment method details | The security code (CVV) is incorrect. Please re-enter it. | CVV is missing, malformed, or does not match issuer records |
| PM\_ADDRESS\_MISMATCH | UE\_1000 | Issue with payment method details | The billing address doesn't match what the bank has on file. Update it or use another card. | Address mismatch (AVS failed) |
| INSUFFICIENT\_FUNDS | UE\_1000 | Issue with payment method details | There aren't enough funds on this card. Use another card or add funds and try again | The entered card has insufficient funds |
| CREDIT\_LIMIT\_EXCEEDED | UE\_1000 | Issue with payment method details | This card has reached its credit limit. Use another card or contact your bank. | Transaction exceeds cardholder's credit limit |
| VELOCITY\_LIMIT\_EXCEEDED | UE\_1000 | Issue with payment method details | This card has hit a usage limit set by your bank. Try another card or contact your bank. | Transaction exceeds allowed frequency or velocity |
| CARD\_LOST\_OR\_STOLEN | UE\_1000 | Issue with payment method details | The bank has blocked this card. Please use a different card. | This card has been reported as lost or stolen |
| CARD\_NOT\_SUPPORTED\_RESTRICTED | UE\_1000 | Issue with payment method details | This card can't be used for this payment. Try another card or payment method. | Card is restricted for this merchant, channel, or use case |
| ACCOUNT\_CLOSED\_OR\_INVALID | UE\_1000 | Issue with payment method details | This account is not active. Use a different payment method. | Account closed or invalid or missing |
| AUTHORIZATION\_MISSING\_OR\_REVOKED | UE\_1000 | Issue with payment method details | This payment can't be completed because the prior authorization was canceled. Try another card or contact your bank. | Customer authorization is missing or was revoked |
| INCORRECT\_AUTHENTICATION\_CODE | UE\_1000 | Issue with payment method details | The code you entered is incorrect. Request a new code and try again. | Incorrect authentication or verification code provided |
| PAYMENT\_SESSION\_TIMEOUT | UE\_1000 | Issue with payment method details | Your session expired. Start the payment again. | Payment session expired before completion |
| AUTHENTICATION\_FAILED | UE\_1000 | Issue with payment method details | We couldn't verify this payment with your bank. Try again or use a different payment method. | Authentication failed or was declined |
| PAYMENT\_CANCELLED\_BY\_USER | UE\_1000 | Issue with payment method details | The payment was canceled. If this wasn't intended, please start a new payment. | Payment flow was canceled by user or system |
| TRANSACTION\_NOT\_PERMITTED | UE\_1000 | Issue with payment method details | This payment method can't be used for this type of purchase. Try another payment method. | This type of purchase is not permitted or supported |
| PM\_TOKENISATION\_ISSUE | UE\_1000 | Issue with payment method details | We couldn't save or use this card securely. Try again or use a different payment method. | Failed to tokenize or validate card credentials |
| **CONFIGURATION\_ISSUE** | **UE\_2000** | **Issue with configuration** | **Something went wrong. Try another Payment Method** | **Issue with Configurations** |
| MERCHANT\_INACTIVE | UE\_2000 | Issue with configuration | Something went wrong. Try another Payment Method | Merchant configuration inactive or invalid |
| CFG\_PM\_NOT\_ENABLED\_OR\_MISCONFIGURED | UE\_2000 | Issue with configuration | Something went wrong. Try another Payment Method | Payment method not enabled for this merchant |
| CURRENCY\_OR\_CORRIDOR\_NOT\_ENABLED | UE\_2000 | Issue with configuration | Something went wrong. Try another Payment Method | Currency or corridor not enabled |
| WALLET\_OR\_TOKEN\_CONFIG\_ISSUE | UE\_2000 | Issue with configuration | Something went wrong. Try another Payment Method | Wallet or token configuration missing or incorrect |
| STORED\_CREDENTIAL\_OR\_MIT\_NOT\_ENABLED | UE\_2000 | Issue with configuration | Something went wrong. Try another Payment Method | Stored credential or MIT not enabled |
| THREEDS\_CONFIGURATION\_ISSUE | UE\_2000 | Issue with configuration | Something went wrong. Try another Payment Method | 3DS not enabled or improperly integrated. |
| SUBSCRIPTION\_PLAN\_INACTIVE | UE\_2000 | Issue with configuration | Something went wrong. Try another Payment Method | Attempted charge on inactive or expired subscription |
| **DOWNSTREAM\_TECHNICAL\_ISSUE** | **UE\_3000** | **Technical Issue with PSP** | **Something went wrong. Try again or contact your bank** | **Downstream technical issue** |
| ISSUER\_UNAVAILABLE | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | The card issuer's bank is temporarily unavailable |
| TRANSACTION\_TIMEDOUT | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | Issuer timeout |
| DO\_NOT\_HONOR | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | Do not honor |
| SUSPECTED\_FRAUD | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | Issuer flagged as suspected fraud. |
| PSP\_FRAUD\_ENGINE\_DECLINE | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | Declined by PSP fraud engine |
| COMPLIANCE\_OR\_SANCTIONS\_RESTRICTION | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | Sanctions or compliance blockage |
| PSP\_ACQUIRER\_ERROR | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | Temporary acquirer internal error |
| THREEDS\_AUTHENTICATION\_SERVICE\_ISSUE | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | 3DS Authentication Service Failure |
| AUTHENTICATION\_REQUIRED | UE\_3000 | Technical Issue with PSP | Something went wrong. Try again or contact your bank | Authentication is required |
| **INTEGRATION\_ISSUE** | **UE\_4000** | **Issue with integration** | **Something went wrong. Try another payment method or contact your bank** | **Issue with Integration** |
| MISSING\_OR\_INVALID\_PARAM | UE\_4000 | Issue with integration | Something went wrong. Try another payment method or contact your bank | Missing or invalid parameter |
| INVALID\_CREDENTIALS | UE\_4000 | Issue with integration | Something went wrong. Try another payment method or contact your bank | Invalid credentials |
| OPERATION\_NOT\_ALLOWED | UE\_4000 | Issue with integration | Something went wrong. Try another payment method or contact your bank | Operation not allowed |
| DUPLICATE\_REQUEST | UE\_4000 | Issue with integration | Something went wrong. Try another payment method or contact your bank | Duplicate or Idempotent request |
| INVALID\_STATE | UE\_4000 | Issue with integration | Something went wrong. Try another payment method or contact your bank | Invalid state of operation |
| THREEDS\_DATA\_OR\_PROTOCOL\_INVALID | UE\_4000 | Issue with integration | Something went wrong. Try another payment method or contact your bank | 3DS payload invalid or inconsistent |
| RATE\_LIMIT | UE\_4000 | Issue with integration | Something went wrong. Try another payment method or contact your bank | API rate limit exceeded |
| INTEG\_CRYPTOGRAPHIC\_ISSUE | UE\_4000 | Issue with integration | Something went wrong. Try another payment method or contact your bank | Token or cryptographic integration issue |
| **GEN\_UNKNOWN\_ERROR** | **UE\_9000** | **Something went wrong** | **Something went wrong** | **Something went wrong** |
# Go-live Checklist
Source: https://api-reference.hyperswitch.io/essentials/go-live
Refer to this checklist for a seamless transition as you prepare to go live with your integration.
The connector configurations set up in the sandbox need to be replicated on the Hyperswitch production account.
### Signing of Hyperswitch services agreement
* [ ] Ensure that the Hyperswitch services agreement is signed and shared with the Hyperswitch team. In case you need any help, please drop an email to [biz@hyperswitch.io](mailto:biz@hyperswitch.io).
The Hyperswitch team will share your production Hyperswitch credentials once the above process is completed.
### Connector Configurations
* [ ] Configure all the required connectors using production credentials on the Hyperswitch production dashboard and enable the required payment methods.
* [ ] Ensure that the payment methods are enabled on the connector (payment processor) dashboard.
* [ ] Enable raw card processing for each connector. Some connectors offer this as a dashboard toggle feature. Some processors might need you to share a PCI Attestation of Compliance over email to enable this. Drop an email to [biz@hyperswitch.io](mailto:biz@hyperswitch.io) if you need any support with PCI AOC.
### Secure your api-keys
* [ ] Make sure your secret key (api-key) is not exposed on the front-end (website/mobile app).
* [ ] Ensure that your workflow avoids the duplication or storage of your API keys in multiple locations.
### Set up Webhooks
* [ ] [Configure your webhook endpoint](https://juspay-78.mintlify.app/essentials/webhooks#configuring-webhooks) on our dashboard to receive notifications for different events.
* [ ] Update Hyperswitch's webhook endpoints on your connector's Dashboard. [Refer here](https://juspay-78.mintlify.app/essentials/webhooks#configuring-webhooks) for detailed instructions.
* [ ] Update the connector secret key in our dashboard for us to authenticate webhooks sent by your connector.
### Secure your Payments
* [ ] Make sure you decrypt and verify the signed payload sent along with the payment status in your return URL.
* [ ] Always verify the payment amount and payment status before fulfilling your customer's shopping cart/service request.
### Error Handling
* [ ] Make sure your API integration is set up to handle all the possible error scenarios (refer this [link](https://juspay-78.mintlify.app/essentials/error_codes)).
* [ ] Ensure your Unified Checkout (SDK) integration is set up to handle all the possible error scenarios (refer this [link](https://hyperswitch.io/docs/sdkIntegrations/unifiedCheckoutWeb/errorCodes)).
* [ ] Ensure that your integration can handle the entire payments lifecycle and test various scenarios using actual payment details.
### Customize and sanity check the payment experience
* [ ] Ensure the pay button is properly highlighted to the customer.
* [ ] Ensure a blended look and feel of the payment experience using the [styling APIs](https://hyperswitch.io/docs/sdkIntegrations/unifiedCheckoutWeb/customization) of Unified Checkout.
# Rate Limits
Source: https://api-reference.hyperswitch.io/essentials/rate_limit
The Hyperswitch API has multiple checks in place to enhance its stability when faced with sudden surges of incoming traffic. Merchants who send numerous requests in rapid succession could encounter error responses indicated by the status code 429.
The default rate limit for all Hyperswitch APIs is **80 requests per second**.
Reach out to [biz@hyperswitch.io](mailto:biz@hyperswitch.io) if you have a requirement for higher limits.
## How to handle rate limits
Effectively handling rate limit 429 errors is crucial for maintaining a seamless user experience.
* Implement retry mechanisms with progressively increasing intervals to avoid overwhelming the system with repeated requests.
* To proactively manage these errors, monitoring tools can help track usage patterns and provide insights for adjusting rate limits as necessary.
* Ultimately, a well-orchestrated strategy for managing 429 errors not only prevents disruption but also fosters positive user engagement by transparently addressing limitations and promoting responsible API usage.
## Understanding API locking
If you see a 429 error with the following error message, it is due to API locking and not due to rate limiting:
```text theme={null}
At this moment, access to this object is restricted due to ongoing utilization by another API request or an ongoing Hyperswitch process. Retry after some time if this error persists.
```
API locking is a robust feature that empowers us to proactively secure and optimize access to our APIs. Our API locks objects on some operations to prevent the disruption caused by concurrent workloads that could potentially lead to inconsistent outcomes.
This proactive measure not only ensures the continued integrity and performance of our APIs but also guarantees a high standard of security for our users. Once triggered, the API lock initiates a controlled pause in access, preventing any potential threats from compromising the system.
# 👋 Welcome to Hyperswitch API Reference
Source: https://api-reference.hyperswitch.io/introduction
Hyperswitch provides a collection of APIs that enable you to process and manage payments. Our APIs accept and return JSON in the HTTP body and return standard HTTP response codes. You can consume the APIs directly using your favorite HTTP/REST library.
Create your first payment using Hyperswitch APIs.
Discover how to process one-time and recurring payments, save payment methods, and more.
Save customer payment methods securely for future transactions
Host Hyperswitch on-premise? Utilize our full API suite.
## Environment
We have a testing environment referred to "sandbox," which you can set up to test API calls without affecting production data. You can sign up on our Dashboard to get API keys to access Hyperswitch API.
Use the following base URLs when making requests to the APIs:
| Environment | Base URL |
| - | - |
| Sandbox | [https://sandbox.hyperswitch.io](https://sandbox.hyperswitch.io) |
| Production | [https://api.hyperswitch.io](https://api.hyperswitch.io) |
If you **do not hold a PCI certification** to collect and store card data on your servers, we recommend using [**Unified Checkout**](https://hyperswitch.io/docs/sdkIntegrations/unifiedCheckoutWeb/#unified-checkout) to accept card information from users.
## Authentication and API keys
Hyperswitch authenticates your API requests using your account’s API keys. Each account has two API keys for authentication:
| Key | Example | When to Use |
| - | - | - |
| Secret key (API-key) | `snd_c69***` | Used to authenticate API requests from your merchant server. **Don’t expose this key** on a website or embed it in a mobile application. |
| Publishable key | `pk_snd_3b3***` | Used to authenticate API requests from your app’s client. Can be publicly-accessible in your web or mobile app’s client-side code. |
Get your [API key](https://app.hyperswitch.io/developers?tabIndex=1) and [Publishable Key](https://app.hyperswitch.io/home)
[Postman Collection](https://www.postman.com/hyperswitch/workspace/hyperswitch-development/collection/25176162-630b5353-7002-44d1-8ba1-ead6c230f2e3)
## Payment Status Lifecycle
Hyperswitch handles the complex functionality of a comprehensive payments flow through the Payments object that transitions through multiple states during its payments lifecycle. Given below are the various statuses a payment can have:
| Payment Status | Description |
| - | - |
| requires\_payment\_method | Once you create a payment through payments/create endpoint with no payment method attached to it, the payments object transitions to ‘requires\_payment\_method’. |
| requires\_confirmation | After attaching a payment method through payments/update endpoint, the payments object requires you to confirm the payment. |
| requires\_customer\_action | Once the payment is confirmed through payments/confirm endpoint, if additional authentication is required, the payments object transitions to this state. |
| requires\_capture | If you want to do separate authorize and capture, setting capture field to ‘manual’ during payments/create or confirm call will transition the payment object to this state after customer action succeeds. |
| processing | In case of automatic capture, the payments object transitions to processing state post confirm call and subsequent customer authentication if available. |
| succeeded | The payments object reaches success state post confirmation of successful processing from the payment processor. |
| failed | The payments object transitions to a failed state when the payment processor confirms the processing failure. |
## Payment Lifecycle - more payment states
| Payment Status | Description |
| - | - |
| Merchant Action Required | The payment is waiting on some action from the merchant (e.g., manual fraud approval) |
| Partially Captured | The payment has been captured partially, and the remaining amount cannot be captured |
| Partially Captured and Capturable | The payment has been captured partially and the remaining amount is capturable |
| Partially Authorized and Requires Capture | The payment has been authorized for a partial amount and requires capture |
| Conflicted | There has been a discrepancy between the amount/currency sent in the request and the amount/currency received by the processor. Applicable for Crypto payments and Bank transfer payments (EU) where user can change the amount on Bank page |
| Expired | The payment expired before it could be captured |
## Redirect URL
This is what a url looks like after redirection
`https://app.hyperswitch.io?status=succeeded&payment_intent_client_secret=pay_NCv9vc19f8aa75OpFxH8_secret_V4zAc7V0C8WAw6FECMKM&amount=10000&manual_retry_allowed=false&signature=4fae0cfa775e4551db9356563d4b98b55662fe3c1c945fe215d90ccf3541282c535909ae901d82174d6b1e46ba1684aa0aa4c8861be0e2a9ef6f950a975d5014&signature_algorithm=HMAC-SHA512`
The available parameters are as follows:
* **status** - can have values of `succeeded`, `processing`and `failed`.
* **payment\_intent\_client\_secret** - This is the client secret associated with the payment. This can be used to retrieve the payment status from hyperswitch.
* **manual\_retry\_allowed** - whether this payment can be retried or not.
* **signature** - A HMAC signature of the payload, this can be verified using the `payment_response_hash_key`.
* **signature\_algorithm** - The HMAC algorithm used to calculate the signature.
# API Key - Create
Source: https://api-reference.hyperswitch.io/v1/api-key/api-key--create
post /api_keys/{merchant_id}
Create a new API Key for accessing our APIs from your servers. The plaintext API Key will be
displayed only once on creation, so ensure you store it securely.
# API Key - List
Source: https://api-reference.hyperswitch.io/v1/api-key/api-key--list
get /api_keys/{merchant_id}/list
List all the API Keys associated to a merchant account.
# API Key - Retrieve
Source: https://api-reference.hyperswitch.io/v1/api-key/api-key--retrieve
get /api_keys/{merchant_id}/{key_id}
Retrieve information about the specified API Key.
# API Key - Revoke
Source: https://api-reference.hyperswitch.io/v1/api-key/api-key--revoke
delete /api_keys/{merchant_id}/{key_id}
Revoke the specified API Key. Once revoked, the API Key can no longer be used for
authenticating with our APIs.
# API Key - Update
Source: https://api-reference.hyperswitch.io/v1/api-key/api-key--update
post /api_keys/{merchant_id}/{key_id}
Update information for the specified API Key.
# Blocklist batch list
Source: https://api-reference.hyperswitch.io/v1/blocklist/blocklist--batch-list
get /blocklist/batch
# Blocklist batch status
Source: https://api-reference.hyperswitch.io/v1/blocklist/blocklist--batch-status
get /blocklist/batch/{job_id}
# Blocklist batch upload
Source: https://api-reference.hyperswitch.io/v1/blocklist/blocklist--batch-upload
post /blocklist/batch
# Blocklist - Clone Entries
Source: https://api-reference.hyperswitch.io/v1/blocklist/blocklist--clone
post /blocklist/clone
Copies a business profile's blocklist entries onto other profiles of the same merchant. The
copy runs as one background job whose process tracker clones onto the targets one at a time.
Poll `/blocklist/batch/{job_id}` for per-target progress in the job metadata.
# Blocklist count
Source: https://api-reference.hyperswitch.io/v1/blocklist/blocklist--count
get /blocklist/count
# Blocklist export create
Source: https://api-reference.hyperswitch.io/v1/blocklist/blocklist--export-create
post /blocklist/export
# Blocklist lookup
Source: https://api-reference.hyperswitch.io/v1/blocklist/blocklist--lookup
get /blocklist/lookup
# Delete blocklist
Source: https://api-reference.hyperswitch.io/v1/blocklist/delete-blocklist
delete /blocklist
# Get blocklist
Source: https://api-reference.hyperswitch.io/v1/blocklist/get-blocklist
get /blocklist
# Post blocklist
Source: https://api-reference.hyperswitch.io/v1/blocklist/post-blocklist
post /blocklist
# Post blocklisttoggle
Source: https://api-reference.hyperswitch.io/v1/blocklist/post-blocklisttoggle
post /blocklist/toggle
# Profile - Delete
Source: https://api-reference.hyperswitch.io/v1/business-profile/business-profile--delete
delete /account/{account_id}/business_profile/{profile_id}
Delete the *profile*
# Profile - List
Source: https://api-reference.hyperswitch.io/v1/business-profile/business-profile--list
get /account/{account_id}/business_profile
Lists all the *profiles* under a merchant
# Profile - Retrieve
Source: https://api-reference.hyperswitch.io/v1/business-profile/business-profile--retrieve
get /account/{account_id}/business_profile/{profile_id}
Retrieve existing *profile*
# Events - Delivery Attempt List
Source: https://api-reference.hyperswitch.io/v1/event/events--delivery-attempt-list
get /events/{merchant_id}/{event_id}/attempts
List all delivery attempts for the specified Event.
# Events - List
Source: https://api-reference.hyperswitch.io/v1/event/events--list
post /events/{merchant_id}
List all Events associated with a Merchant Account or Profile.
# Events - Manual Retry
Source: https://api-reference.hyperswitch.io/v1/event/events--manual-retry
post /events/{merchant_id}/{event_id}/retry
Manually retry the delivery of the specified Event.
# Gsm - Create
Source: https://api-reference.hyperswitch.io/v1/gsm/gsm--create
post /gsm
Creates a GSM (Global Status Mapping) Rule. A GSM rule is used to map a connector's error message/error code combination during a particular payments flow/sub-flow to Hyperswitch's unified status/error code/error message combination. It is also used to decide the next action in the flow - retry/requeue/do_default
# Gsm - Delete
Source: https://api-reference.hyperswitch.io/v1/gsm/gsm--delete
post /gsm/delete
Deletes a Gsm Rule
# Gsm - Get
Source: https://api-reference.hyperswitch.io/v1/gsm/gsm--get
post /gsm/get
Retrieves a Gsm Rule
# Gsm - Update
Source: https://api-reference.hyperswitch.io/v1/gsm/gsm--update
post /gsm/update
Updates a Gsm Rule
# Merchant Connector - Create
Source: https://api-reference.hyperswitch.io/v1/merchant-connector-account/merchant-connector--create
post /account/{account_id}/connectors
Creates a new Merchant Connector for the merchant account. The connector could be a payment processor/facilitator/acquirer or a provider of specialized services like Fraud/Accounting etc.
# Merchant Connector - Delete
Source: https://api-reference.hyperswitch.io/v1/merchant-connector-account/merchant-connector--delete
delete /account/{account_id}/connectors/{merchant_connector_id}
Delete or Detach a Merchant Connector from Merchant Account
# Merchant Connector - List
Source: https://api-reference.hyperswitch.io/v1/merchant-connector-account/merchant-connector--list
get /account/{account_id}/connectors
List Merchant Connector Details for the merchant
# Merchant Connector - Retrieve
Source: https://api-reference.hyperswitch.io/v1/merchant-connector-account/merchant-connector--retrieve
get /account/{account_id}/connectors/{merchant_connector_id}
Retrieves details of a Connector account
# Merchant Connector - Update
Source: https://api-reference.hyperswitch.io/v1/merchant-connector-account/merchant-connector--update
post /account/{account_id}/connectors/{merchant_connector_id}
To update an existing Merchant Connector account. Helpful in enabling/disabling different payment methods and other settings for the connector
# Platform - Create
Source: https://api-reference.hyperswitch.io/v1/platform/platform--create
post /user/create_platform
Create a new platform account
# Poll - Retrieve Poll Status
Source: https://api-reference.hyperswitch.io/v1/poll/poll--retrieve-poll-status
get /poll/status/{poll_id}
# Relay - Create
Source: https://api-reference.hyperswitch.io/v1/relay/relay
post /relay
Creates a relay request.
# Relay - Retrieve
Source: https://api-reference.hyperswitch.io/v1/relay/relay--retrieve
get /relay/{relay_id}
Retrieves a relay details.
# Routing - Activate config
Source: https://api-reference.hyperswitch.io/v1/routing/routing--activate-config
post /routing/{routing_algorithm_id}/activate
Activate a routing config
# Routing - Create
Source: https://api-reference.hyperswitch.io/v1/routing/routing--create
post /routing
Create a routing config
# Routing - Deactivate
Source: https://api-reference.hyperswitch.io/v1/routing/routing--deactivate
post /routing/deactivate
Deactivates a routing config
# Routing - Elimination
Source: https://api-reference.hyperswitch.io/v1/routing/routing--elimination
post /account/{account_id}/business_profile/{profile_id}/dynamic_routing/elimination/create
Create a elimination based dynamic routing algorithm
# Routing - Evaluate
Source: https://api-reference.hyperswitch.io/v1/routing/routing--evaluate
post /routing/evaluate
Evaluate routing rules
# Routing - Feedback
Source: https://api-reference.hyperswitch.io/v1/routing/routing--feedback
post /routing/feedback
Update gateway scores for dynamic routing
# Routing - List
Source: https://api-reference.hyperswitch.io/v1/routing/routing--list
get /routing
List all routing configs
# Routing - Retrieve
Source: https://api-reference.hyperswitch.io/v1/routing/routing--retrieve
get /routing/{routing_algorithm_id}
Retrieve a routing algorithm
# Routing - Retrieve Config
Source: https://api-reference.hyperswitch.io/v1/routing/routing--retrieve-config
get /routing/active
Retrieve active config
# Routing - Retrieve Default Config
Source: https://api-reference.hyperswitch.io/v1/routing/routing--retrieve-default-config
get /routing/default
Retrieve default fallback config
# Routing - Retrieve Default For Profile
Source: https://api-reference.hyperswitch.io/v1/routing/routing--retrieve-default-for-profile
get /routing/default/profile
Retrieve default config for profiles
# Routing - Rule Evaluate
Source: https://api-reference.hyperswitch.io/v1/routing/routing--rule-evaluate
post /routing/rule/evaluate
Evaluate routing rules
# Routing - Auth Rate Based
Source: https://api-reference.hyperswitch.io/v1/routing/routing--success-based
post /account/{account_id}/business_profile/{profile_id}/dynamic_routing/success_based/create
Create a success based dynamic routing algorithm
# Routing - Update Default Config
Source: https://api-reference.hyperswitch.io/v1/routing/routing--update-default-config
post /routing/default
Update default fallback config
# Routing - Update Default For Profile
Source: https://api-reference.hyperswitch.io/v1/routing/routing--update-default-for-profile
post /routing/default/profile/{profile_id}
Update default config for profiles
# Outgoing webhook
Source: https://api-reference.hyperswitch.io/v1/schemas/outgoing--webhook
# Subscription - Cancel Subscription
Source: https://api-reference.hyperswitch.io/v1/subscriptions/cancel
post /subscriptions/{subscription_id}/cancel
Cancel the subscription
# Subscription - Confirm
Source: https://api-reference.hyperswitch.io/v1/subscriptions/confirm
post /subscriptions/{subscription_id}/confirm
Confirms a previously created subscription.
# Subscription - Create
Source: https://api-reference.hyperswitch.io/v1/subscriptions/create
post /subscriptions/create
Creates a subscription that requires separate confirmation.
# Subscription - Create and Confirm
Source: https://api-reference.hyperswitch.io/v1/subscriptions/create-and-confirm
post /subscriptions
Creates and confirms a subscription in a single request.
# Subscription - Get Estimate
Source: https://api-reference.hyperswitch.io/v1/subscriptions/estimate
get /subscriptions/estimate
Gets pricing estimate for a subscription.
# Subscription - Retrieve
Source: https://api-reference.hyperswitch.io/v1/subscriptions/get
get /subscriptions/{subscription_id}
Retrieves subscription details by ID.
# Subscription - Pause Subscription
Source: https://api-reference.hyperswitch.io/v1/subscriptions/pause
post /subscriptions/{subscription_id}/pause
Pause the subscription
# Subscription - Resume Subscription
Source: https://api-reference.hyperswitch.io/v1/subscriptions/resume
post /subscriptions/{subscription_id}/resume
Resume the subscription
# Subscription - Update
Source: https://api-reference.hyperswitch.io/v1/subscriptions/update
put /subscriptions/{subscription_id}/update
Updates an existing subscription.
# Analytics
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/analytics
Routing metrics, score snapshots, and operational summaries
## What It Shows
Analytics is the operator-facing view for understanding how routing is behaving in practice.
The page is split into these sections:
* Overview
* Gateway Scoring
* Decisions
* Routing Stats
* Logs / Summaries
For single-payment inspection, use the separate Payment Audit surface documented in [`payment-audit`](/decision-engine-api-reference/payment-audit).
## Data Sources
The current implementation uses these sources:
* Redis for live SR and latency snapshots
* Prometheus for live counters and error-rate tiles
* ClickHouse as the analytics event store and analytics query backend
## Scope
Analytics is always merchant-scoped by the authenticated identity:
* Bearer JWT requests derive the merchant from the token claims
* API-key requests derive the merchant from the key binding
There is no all-merchants analytics mode. The analytics routes no longer accept `scope` or
`merchant_id` query params, and changing the merchant selector in the top bar does not widen the
backend query scope.
Connector success-rate history is sourced from stored `score_snapshot` analytics events, not directly from Redis. Redis remains the live source for current score state. The connector SR chart can be narrowed by:
* `payment_method_type`
* `payment_method`
* connector
## Generating Demo Traffic
To populate Analytics and Decision Audit with real traffic, use the routing traffic generator.
Generate traffic for `merchant_space`:
```bash theme={null}
bash scripts/generate-routing-traffic.sh
```
What the script does:
* creates or reuses `merchant_space`
* enables success-rate routing for that merchant through the real `/rule/create` or `/rule/update` flow
* sends `100` real `POST /decide-gateway` requests with mixed payment-method combinations
* follows each decision with `POST /update-gateway-score` using a mix of successful and failed outcomes
* creates and activates a priority-based routing rule through `/routing/create` and `/routing/activate`
* sends rule-based `POST /routing/evaluate` traffic so the rule-evaluation analytics path is populated
Useful overrides:
```bash theme={null}
MERCHANT_ID=merchant_space TOTAL_PAYMENTS=100 bash scripts/generate-routing-traffic.sh
RULE_EVALUATIONS=40 bash scripts/generate-routing-traffic.sh
CONNECTORS_CSV=stripe,adyen,checkout,paypal bash scripts/generate-routing-traffic.sh
```
After the script finishes, sign in as `merchant_space` and open `/dashboard/analytics` or
`/dashboard/audit`. Analytics reads will resolve the merchant from your authenticated session.
## ClickHouse Setup
ClickHouse is part of the standard local runtime stacks. To bring up only ClickHouse and its schema init job:
```bash theme={null}
COMPOSE_PROFILES= docker compose --profile analytics-clickhouse up -d
```
## Related Files
* `website/src/components/pages/AnalyticsPage.tsx`
* `website/src/components/layout/Sidebar.tsx`
* `src/routes/analytics.rs`
* `src/analytics/`
* `clickhouse/scripts/`
* `src/metrics.rs`
## Related Docs
* [Payment Audit](/decision-engine-api-reference/payment-audit) — single-payment timeline lookups.
* [ClickHouse Analytics](/decision-engine-api-reference/clickhouse-analytics) — the underlying ingestion pipeline and schema.
* [Dashboard](/decision-engine-api-reference/dashboard-guide) — where these views are surfaced.
# Cost Savings
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/analytics/analyticsCostSavings
decision_engine_openapi-specs.json GET /analytics/cost-savings
ClickHouse-backed cost savings read endpoint.
# Analytics Decisions
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/analytics/analyticsDecisions
decision_engine_openapi-specs.json GET /analytics/decisions
ClickHouse-backed decisions read endpoint.
# A/B Test Experiment Results
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/analytics/analyticsExperimentResults
decision_engine_openapi-specs.json GET /analytics/experiment/{experiment_id}/results
ClickHouse-backed A/B test experiment results read endpoint.
# A/B Test Experiment Transactions
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/analytics/analyticsExperimentTransactions
decision_engine_openapi-specs.json GET /analytics/experiment/{experiment_id}/transactions
ClickHouse-backed A/B test experiment transaction log read endpoint.
# Analytics Gateway Scores
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/analytics/analyticsGatewayScores
decision_engine_openapi-specs.json GET /analytics/gateway-scores
ClickHouse-backed gateway scores read endpoint.
# Analytics Log Summaries
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/analytics/analyticsLogSummaries
decision_engine_openapi-specs.json GET /analytics/log-summaries
ClickHouse-backed log summaries read endpoint.
# Analytics Overview
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/analytics/analyticsOverview
decision_engine_openapi-specs.json GET /analytics/overview
ClickHouse-backed overview read endpoint.
# Payment Audit
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/analytics/analyticsPaymentAudit
decision_engine_openapi-specs.json GET /analytics/payment-audit
ClickHouse-backed payment audit read endpoint.
# Preview Trace
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/analytics/analyticsPreviewTrace
decision_engine_openapi-specs.json GET /analytics/preview-trace
ClickHouse-backed rule preview trace read endpoint.
# Routing Events
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/analytics/analyticsRoutingEvents
decision_engine_openapi-specs.json GET /analytics/routing-events
ClickHouse-backed routing events read endpoint.
# Analytics Routing Stats
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/analytics/analyticsRoutingStats
decision_engine_openapi-specs.json GET /analytics/routing-stats
ClickHouse-backed routing stats read endpoint.
# Create API Key
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/auth/createApiKey
decision_engine_openapi-specs.json POST /api-key/create
Create a service-to-service API key for a merchant.
# List API Keys
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/auth/listApiKeys
decision_engine_openapi-specs.json GET /api-key/list/{merchant_id}
List active and revoked API keys for a merchant.
# List User Merchants
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/auth/listUserMerchants
decision_engine_openapi-specs.json GET /auth/merchants
Return merchants available to the current user.
# Login
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/auth/login
decision_engine_openapi-specs.json POST /auth/login
Create a dashboard JWT session.
# Logout
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/auth/logout
decision_engine_openapi-specs.json POST /auth/logout
Revoke the current dashboard JWT.
# Current User
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/auth/me
decision_engine_openapi-specs.json GET /auth/me
Return current authenticated user and merchant context.
# Onboard Merchant
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/auth/onboardMerchant
decision_engine_openapi-specs.json POST /onboarding/merchant
Create and attach a merchant to the current operator user.
# Revoke API Key
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/auth/revokeApiKey
decision_engine_openapi-specs.json DELETE /api-key/{key_id}
Mark an API key inactive and clear its Redis cache entry.
# Signup
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/auth/signup
decision_engine_openapi-specs.json POST /auth/signup
Create an operator account. Password must meet dashboard password policy.
# Switch Merchant
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/auth/switchMerchant
decision_engine_openapi-specs.json POST /auth/switch-merchant
Switch the current dashboard merchant context.
# Legacy Decision Gateway
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/compatibility/legacyDecisionGateway
decision_engine_openapi-specs.json POST /decision_gateway
Legacy compatibility route. New integrations should use /decide-gateway.
# Legacy Update Score
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/compatibility/legacyUpdateScore
decision_engine_openapi-specs.json POST /update-score
Legacy compatibility route. New integrations should use /update-gateway-score.
# Decide Gateway
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/gateway-decision/decideGateway
decision_engine_openapi-specs.json POST /decide-gateway
Core routing decision API. Given a payment context and a list of eligible gateways, returns the optimal gateway to route to.
# Decide Gateway
## Use case
Runs the core gateway decision flow for a payment. The same endpoint supports auth-rate routing, priority-list routing, debit/network routing, and network+SR hybrid routing.
## Authentication
Protected. Send either `Authorization: Bearer ` or `x-api-key: `. In sandbox, also send `x-feature: decision-engine`.
For local development, start with:
```bash theme={null}
export BASE_URL=http://localhost:8080
export AUTH_HEADER="Authorization: Bearer "
# Sandbox only:
# export BASE_URL=https://sandbox.hyperswitch.io
# export FEATURE_HEADER="x-feature: decision-engine"
```
## Request
* Method and path: `POST /decide-gateway`
* Parameters: none.
* Body: JSON body with `merchantId`, `paymentInfo`, `eligibleGatewayList`, and `rankingAlgorithm`. `rankingAlgorithm` must be one of `SR_BASED_ROUTING`, `PL_BASED_ROUTING`, `NTW_BASED_ROUTING`, or `NTW_SR_HYBRID_ROUTING`.
## Example
### SR based routing
```bash theme={null}
curl --location "$BASE_URL/decide-gateway" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchantId": "merchant_demo",
"eligibleGatewayList": ["stripe", "adyen", "checkout"],
"rankingAlgorithm": "SR_BASED_ROUTING",
"eliminationEnabled": true,
"paymentInfo": {
"paymentId": "pay_sr_001",
"amount": 1000,
"currency": "USD",
"country": "US",
"paymentType": "ORDER_PAYMENT",
"paymentMethodType": "CARD",
"paymentMethod": "CREDIT",
"authType": "THREE_DS",
"cardIsin": "424242"
}
}'
```
### Priority-list routing
```bash theme={null}
curl --location "$BASE_URL/decide-gateway" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchantId": "merchant_demo",
"eligibleGatewayList": ["stripe", "adyen", "checkout"],
"rankingAlgorithm": "PL_BASED_ROUTING",
"eliminationEnabled": true,
"paymentInfo": {
"paymentId": "pay_pl_001",
"amount": 1000,
"currency": "USD",
"country": "US",
"paymentType": "ORDER_PAYMENT",
"paymentMethodType": "CARD",
"paymentMethod": "CREDIT",
"authType": "THREE_DS",
"cardIsin": "424242"
}
}'
```
### Debit/network routing
```bash theme={null}
curl --location "$BASE_URL/decide-gateway" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchantId": "merchant_demo",
"eligibleGatewayList": ["stripe", "adyen"],
"rankingAlgorithm": "NTW_BASED_ROUTING",
"paymentInfo": {
"paymentId": "pay_debit_001",
"amount": 1000,
"currency": "USD",
"country": "US",
"paymentType": "ORDER_PAYMENT",
"paymentMethodType": "CARD",
"paymentMethod": "DEBIT",
"authType": "THREE_DS",
"metadata": "{\"merchant_category_code\":\"merchant_category_code_0001\",\"acquirer_country\":\"US\",\"co_badged_card_data\":{\"card_type\":\"debit\",\"issuer_country\":\"US\",\"is_regulated\":false,\"regulated_name\":null,\"card_networks\":[\"VISA\",\"NYCE\",\"PULSE\",\"STAR\"]}}"
}
}'
```
### Multi-objective routing
```bash theme={null}
curl --location "$BASE_URL/decide-gateway" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchantId": "merchant_demo",
"eligibleGatewayList": ["stripe", "adyen", "checkout"],
"rankingAlgorithm": "SR_BASED_ROUTING",
"eliminationEnabled": true,
"enableMultiObjective": true,
"paymentInfo": {
"paymentId": "pay_mo_001",
"amount": 1000,
"currency": "USD",
"country": "US",
"paymentType": "ORDER_PAYMENT",
"paymentMethodType": "CARD",
"paymentMethod": "CREDIT",
"authType": "THREE_DS",
"cardIsin": "424242"
}
}'
```
### Network + SR hybrid routing
```bash theme={null}
curl --location "$BASE_URL/decide-gateway" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchantId": "merchant_demo",
"eligibleGatewayList": ["stripe", "adyen"],
"rankingAlgorithm": "NTW_SR_HYBRID_ROUTING",
"paymentInfo": {
"paymentId": "pay_hybrid_001",
"amount": 1000,
"currency": "USD",
"country": "US",
"paymentType": "ORDER_PAYMENT",
"paymentMethodType": "CARD",
"paymentMethod": "DEBIT",
"authType": "THREE_DS",
"metadata": "{\"merchant_category_code\":\"merchant_category_code_0001\",\"acquirer_country\":\"US\",\"co_badged_card_data\":{\"card_type\":\"debit\",\"issuer_country\":\"US\",\"is_regulated\":false,\"regulated_name\":null,\"card_networks\":[\"VISA\",\"NYCE\",\"PULSE\",\"STAR\"]}}"
}
}'
```
## Response
```json theme={null}
{
"decided_gateway": "stripe",
"gateway_priority_map": {
"stripe": 0.94,
"adyen": 0.91
},
"routing_approach": "SR_SELECTION_V3_ROUTING",
"gateway_before_evaluation": "stripe",
"debit_routing_output": {
"co_badged_card_networks_info": [
{
"network": "NYCE",
"saving_percentage": 1.2
}
],
"issuer_country": "US",
"is_regulated": false,
"card_type": "debit"
},
"is_rust_based_decider": true
}
```
## Notes
* Use backend enum strings exactly; camelCase values such as `NtwBasedRouting` are invalid.
* Debit routing requires the merchant debit-routing flag to be enabled and debit metadata encoded as a JSON string in `paymentInfo.metadata`.
* Multi-objective routing is not a `rankingAlgorithm` value: it is a cost-aware post-step on SR-based scoring, toggled per request with `enableMultiObjective` or per merchant with the `multi_objective_routing_enabled` feature flag. When it runs, the response carries a `multi_objective_info` block, and `routing_approach` becomes `SR_SELECTION_MULTI_OBJECTIVE` when a cheaper gateway wins on expected value.
* A successful call emits analytics/audit events asynchronously.
## Related
* [Decide Gateway: SR Based Routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-sr-based)
* [Decide Gateway: PL Based Routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-pl-based)
* [Decide Gateway: Debit Routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-debit-routing)
* [Decide Gateway: Hybrid Routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-hybrid-routing)
* [Decide Gateway: Multi-Objective Routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective)
* [Update Gateway Score](/decision-engine-api-reference/api-reference/endpoint/score-feedback/updateGatewayScore)
# Health Check
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/health/healthCheck
decision_engine_openapi-specs.json GET /health
Service liveness check.
# Health Diagnostics
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/health/healthDiagnostics
decision_engine_openapi-specs.json GET /health/diagnostics
Database diagnostics for local and deployment troubleshooting.
# Health Ready
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/health/healthReady
decision_engine_openapi-specs.json GET /health/ready
Returns Up when the process is ready to serve traffic.
# Create Merchant
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/merchant-account/createMerchant
decision_engine_openapi-specs.json POST /merchant-account/create
Register a new merchant account. The merchant ID is the primary identifier used in all subsequent routing and scoring calls.
# Delete Merchant
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/merchant-account/deleteMerchant
decision_engine_openapi-specs.json DELETE /merchant-account/{merchant_id}
Delete a merchant account and all associated routing configuration.
# Get Merchant
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/merchant-account/getMerchant
decision_engine_openapi-specs.json GET /merchant-account/{merchant_id}
Retrieve a merchant account by ID.
# Get Merchant Debit Routing
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/merchant-account/getMerchantDebitRouting
decision_engine_openapi-specs.json GET /merchant-account/{merchant_id}/debit-routing
Return whether debit/network routing is enabled for a merchant. Missing flag configuration is treated as disabled.
# Update Merchant Debit Routing
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/merchant-account/updateMerchantDebitRouting
decision_engine_openapi-specs.json POST /merchant-account/{merchant_id}/debit-routing
Enable or disable runtime debit/network routing for a merchant.
# Activate Routing Rule
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/routing-rules/activateRoutingRule
decision_engine_openapi-specs.json POST /routing/activate
Activate a routing rule by ID for a merchant. Only one rule can be active at a time — activating a new rule deactivates the previous one.
# Create Routing Rule
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/routing-rules/createRoutingRule
decision_engine_openapi-specs.json POST /routing/create
Create a new Euclid declarative routing rule for a merchant. Supports `advanced` (full Euclid DSL), `priority` (ordered gateway list), `single` (fixed gateway), and `volume_split` (percentage-based distribution) algorithm types.
# Deactivate Routing Rule
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/routing-rules/deactivateRoutingRule
decision_engine_openapi-specs.json POST /routing/deactivate
Deactivate a routing rule by ID for a merchant without deleting the saved rule.
# Evaluate Routing Rule
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/routing-rules/evaluateRoutingRule
decision_engine_openapi-specs.json POST /routing/evaluate
Evaluate the active routing rule for a merchant against a payment context. Returns the ordered list of gateways selected by the rule without consuming SR data.
# Get Active Routing Rule
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/routing-rules/getActiveRoutingRule
decision_engine_openapi-specs.json POST /routing/list/active/{created_by}
Retrieve the currently active routing rule for a merchant.
# Hybrid Routing
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/routing-rules/hybridRouting
decision_engine_openapi-specs.json POST /routing/hybrid
Evaluate hybrid routing using the active routing rule plus runtime payment context.
# List Routing Rules
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/routing-rules/listRoutingRules
decision_engine_openapi-specs.json POST /routing/list/{created_by}
List all routing rules for a merchant.
# Create Rule Config
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/rule-configuration/createRuleConfig
decision_engine_openapi-specs.json POST /rule/create
Create a service-level configuration for `successRate` or `elimination` scoring. Controls the time window, minimum data thresholds, and other parameters used in SR computation.
# Delete Rule Config
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/rule-configuration/deleteRuleConfig
decision_engine_openapi-specs.json POST /rule/delete
Delete a rule configuration.
# Get Rule Config
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/rule-configuration/getRuleConfig
decision_engine_openapi-specs.json POST /rule/get
Retrieve an existing rule configuration by merchant and type.
# Update Rule Config
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/rule-configuration/updateRuleConfig
decision_engine_openapi-specs.json POST /rule/update
Update an existing rule configuration.
# Update Gateway Score
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/score-feedback/updateGatewayScore
decision_engine_openapi-specs.json POST /update-gateway-score
Feed a transaction outcome back into the success-rate model. Call this after every transaction so the engine has accurate SR data for future routing decisions.
# Update Gateway Score
## Use case
Records the observed transaction outcome for a previously selected gateway so auth-rate analytics can learn from real payment results.
## Authentication
Protected. Send either `Authorization: Bearer ` or `x-api-key: `. In sandbox, also send `x-feature: decision-engine`.
For local development, start with:
```bash theme={null}
export BASE_URL=http://localhost:8080
export AUTH_HEADER="Authorization: Bearer "
# Sandbox only:
# export BASE_URL=https://sandbox.hyperswitch.io
# export FEATURE_HEADER="x-feature: decision-engine"
```
## Request
* Method and path: `POST /update-gateway-score`
* Parameters: none.
* Body: JSON body with `merchantId`, `paymentId`, `gateway` and `status`, plus optional `gatewayReferenceId`, `enforceDynamicRoutingFailure`, `txnLatency`, `errorInfo` and `isSmartRetry`.
## Example
### Update gateway score
```bash theme={null}
curl --location "$BASE_URL/update-gateway-score" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchantId": "merchant_demo",
"paymentId": "pay_sr_001",
"gateway": "stripe",
"status": "CHARGED",
"gatewayReferenceId": "stripe_ref_001",
"enforceDynamicRoutingFailure": false,
"txnLatency": { "gatewayLatency": 120.5 }
}'
```
`status` must be a transaction status value - `CHARGED`, `AUTHORIZATION_FAILED`,
`AUTHENTICATION_FAILED`, `JUSPAY_DECLINED`, `FAILURE`, and so on. Lowercase values such as
`success` are rejected with a 400.
Payment attributes (amount, currency, payment method, auth type) are **not** part of this
payload - the engine already has them from the `/decide-gateway` call for this `paymentId`.
Any unrecognised field is silently ignored, so a misspelled key fails quietly rather than
erroring. Note in particular that latency goes in `txnLatency.gatewayLatency`, not `latency`.
## Response
```json theme={null}
{
"message": "Gateway score updated successfully",
"merchant_id": "merchant_demo",
"gateway": "stripe",
"payment_id": "pay_sr_001"
}
```
When `errorInfo` is supplied in the request and matches a gateway status map rule, the response
also carries a `gsm_info` object describing the lookup result.
## Notes
* Do not call this after `NTW_BASED_ROUTING` just to record the selected debit network; debit audit comes from `/decide-gateway` analytics.
* Call it after payment authorization completes, not before.
## Related
* [Decide Gateway](/decision-engine-api-reference/api-reference/endpoint/gateway-decision/decideGateway)
* [Analytics Gateway Scores](/decision-engine-api-reference/api-reference/endpoint/analytics/analyticsGatewayScores)
* [Update Gateway Score](/decision-engine-api-reference/api-reference/guides/feedback-scoring/update-gateway-score)
# API Guide
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/api-ref
A practical, copy-paste guide to the Decision Engine API — from creating a merchant to running routed transactions and reading analytics.
# Decision Engine API Guide
This guide walks the Decision Engine API in the order you'll actually use it: set up a merchant, configure how transactions should be routed, send transactions to `/decide-gateway`, feed outcomes back, and review analytics.
Every page below includes ready-to-run `curl` examples with realistic payloads. For exact request and response schemas plus an interactive playground, use the [OpenAPI Reference](/decision-engine-api-reference/api-reference).
**Two reference surfaces are available.** Start here for task-oriented flows; switch to the OpenAPI Reference when you need exact schemas.
| Surface | Best for |
| - | - |
| **API Guide** (this section) | Copy-paste `curl` examples, end-to-end flows, and request variants. |
| **[OpenAPI Reference](/decision-engine-api-reference/api-reference)** | One page per endpoint with full schemas and a request playground. |
## Integration flow
A typical integration follows these steps. Each links to the page with the exact request.
Create the merchant record that owns your routing config, API keys, and analytics.
See [Create Merchant Account](/decision-engine-api-reference/api-reference/guides/merchant-accounts/merchant-account-create).
Issue a server-to-server API key to authenticate the calls that follow.
See [API Keys](/decision-engine-api-reference/api-reference/guides/auth-onboarding/api-keys).
Decide how connectors are chosen — a fixed connector, a priority list, a volume split, or an advanced rule tree — then activate it.
See [Create Routing Algorithm](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-create).
Call `/decide-gateway` for each payment to get the connector to use.
See [Run Transactions](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-sr-based).
Report the authorization outcome so scoring and analytics stay accurate.
See [Update Gateway Score](/decision-engine-api-reference/api-reference/guides/feedback-scoring/update-gateway-score).
Inspect gateway scores, decisions, and audit trails.
See [Analytics & Audit](/decision-engine-api-reference/api-reference/guides/analytics-audit/analytics-endpoints).
## Environment setup
Set these once in your shell and reuse them across every example.
```bash theme={null}
# Base URL — local source build or Docker Compose
export BASE_URL=http://localhost:8080
# Sandbox (routed through Hyperswitch), when applicable
# export BASE_URL=https://sandbox.hyperswitch.io
# Protected endpoints accept either a dashboard JWT or an API key
export AUTH_HEADER="Authorization: Bearer "
# export AUTH_HEADER="x-api-key: DE_"
# Sandbox-only routing header
export FEATURE_HEADER="x-feature: decision-engine"
# Required on analytics routes, /health/diagnostics, and /gateway-score/reset only.
# "public" is the only tenant the shipped config files define.
export TENANT_HEADER="x-tenant-id: public"
```
Public routes need no auth. Protected routes include `AUTH_HEADER`:
```bash theme={null}
curl "$BASE_URL/analytics/overview?range=1d" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER" \
--header "$FEATURE_HEADER"
```
## Authentication & access
| Access class | Routes | Required headers |
| - | - | - |
| Public health | `GET /health`, `GET /health/ready` | None |
| Public health (tenant-scoped) | `GET /health/diagnostics` | `TENANT_HEADER` — no auth |
| Public auth entry | `POST /auth/signup`, `POST /auth/login` | None |
| Admin bootstrap | `POST /merchant-account/create` | Admin secret configured for the deployment |
| Protected APIs | API keys, merchant reads/deletes, routing, rule config, decisions, score updates, config | `Authorization: Bearer ` or `x-api-key: ` |
| Protected APIs (tenant-scoped) | All `GET /analytics/*`, `POST /gateway-score/reset` | The above, **plus** `TENANT_HEADER` |
| Sandbox (Hyperswitch) | Same rules, served through `https://sandbox.hyperswitch.io` | Add `x-feature: decision-engine` |
`TENANT_HEADER` (`x-tenant-id`) has no fallback — omitting it on a route that needs it fails with `TE_03: x-tenant-id not found in headers`, regardless of a valid `AUTH_HEADER`. It's easy to miss because most routes (`/decide-gateway`, `/routing/*`, `/rule/*`, `/merchant-account/*`, `/update-gateway-score`, `/auth/*`, `/api-key/*`) resolve the tenant internally and need no such header — only the routes listed above do.
## Browse by task
Liveness, readiness, and dependency diagnostics.
Sign up, log in, switch merchants, and manage API keys.
Create, read, delete a merchant, and manage debit routing.
Single, priority, volume-split, and advanced rule trees — plus activation.
Success-rate and elimination (downtime) scoring config.
Choose a connector per payment via `/decide-gateway`.
Report authorization outcomes to keep scoring accurate.
Overview, gateway scores, decisions, routing stats, and audit.
Cost-aware post-step that re-ranks gateways on expected value.
Learn real per-gateway fees from settlement reports and invoices.
Compare two routing strategies on live traffic with guardrails.
Self-tuning SR scoring, plus every merchant-level toggle.
## Ways to route transactions
`/decide-gateway` supports several strategies, selected per request with `rankingAlgorithm`.
| Strategy | Request value | Guide |
| - | - | - |
| Success-rate (auth-rate) based | `SR_BASED_ROUTING` | [SR-based routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-sr-based) |
| Priority-list based | `PL_BASED_ROUTING` | [Priority-list routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-pl-based) |
| Debit / network based | `NTW_BASED_ROUTING` | [Debit routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-debit-routing) |
| Network + SR hybrid | `NTW_SR_HYBRID_ROUTING` | [Hybrid routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-hybrid-routing) |
**Multi-objective (cost-aware) routing** is not a `rankingAlgorithm` value. It is a post-step on success-rate scoring, toggled per request with `enableMultiObjective` or per merchant with the `multi_objective_routing_enabled` feature flag. When active, responses carry a `multi_objective_info` block. See [Multi-objective routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective).
## Advanced capabilities
Beyond the core decide/feedback loop, Decision Engine ships several self-contained systems that build on it:
| Capability | What it does | Start here |
| - | - | - |
| Cost data ingestion | Learns each connector's actual fee (from settlement reports and invoices) at a per-cluster level, feeding multi-objective routing's expected-value ranking. | [Connector setup](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-setup) → [uploads](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-uploads) → [fees & coverage](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-fees) |
| A/B testing | Splits traffic between a control and variant routing strategy — auth vs. cost-aware, manual vs. autopilot, or any two saved algorithms — with a guardrail and significance testing. | [Create an experiment](/decision-engine-api-reference/api-reference/guides/ab-testing/ab-testing-create) → [read results](/decision-engine-api-reference/api-reference/guides/ab-testing/ab-testing-results) |
| Simulation | Preview what any routing algorithm (including an A/B test arm) would decide for a given payment context, without a real transaction. | [Evaluate Routing Algorithm](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-evaluate) |
| Autopilot & auto-calibration | Background job that self-tunes SR hedging % and bucket size from observed traffic, with a hard-reset endpoint for simulation runs. | [Merchant Features](/decision-engine-api-reference/api-reference/guides/autopilot/merchant-features) |
## Backward compatibility
Legacy routes are kept for older integrations. New integrations should use `/decide-gateway` and `/update-gateway-score`.
* [Legacy decision endpoint](/decision-engine-api-reference/api-reference/guides/legacy/decision-gateway-legacy) — the older `/decision_gateway` route.
* [Legacy update score](/decision-engine-api-reference/api-reference/guides/legacy/update-score-legacy) — the older `/update-score` route.
# Performance Benchmarks
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/benchmarks
Throughput and latency of the /decide-gateway and /routing/evaluate endpoints under sustained load
## Overview
The decision engine contributes **\~6 ms** (server-side average) to a payment routing
decision at typical load. A single 2-core pod sustains **835 req/s peak** with zero
errors, and throughput scales linearly with additional pods — both routing modes are
stateless and share no per-request mutable state.
These figures are from k6 load tests against a single containerised pod. All latency
numbers in the tables below represent the server-side processing time reported in each
`/decide-gateway` response — the time the pod spends on the routing decision itself,
excluding network distance to and from your application.
| Endpoint | Algorithm | Use case |
| - | - | - |
| `POST /decide-gateway` | SR\_BASED\_ROUTING | Success-rate driven gateway selection |
| `POST /routing/evaluate` | RULE\_BASED\_ROUTING | Priority-rule evaluation using the active configured routing rule |
***
## Test Environment
**Cluster node**
| Property | Value |
| - | - |
| vCPU capacity | 8 |
| Memory capacity | 15.41 GiB |
| Architecture | linux/amd64 |
| Kernel | Amazon Linux 2023 (6.12.x) |
**Pod provisioning**
| Resource | Request | Limit |
| - | -: | -: |
| CPU | 1000m | 2000m |
| Memory | 256 MiB | 512 MiB |
**Log level:** `INFO`
***
## Test Methodology
**Tool:** [k6](https://k6.io) — 30s steady load per VU step.
**Metrics**
* **Round-trip (RT)** — total time measured by the load generator, including local network.
* **Server-side** — processing time reported by the pod in the `/decide-gateway` response
`latency` field, isolating pure compute. Not available for `/routing/evaluate`.
* **HTTP overhead** — round-trip minus server-side: HTTP framing, request routing, and response
serialisation outside the handler's timer. Add your production network RTT on top of this.
***
## SR\_BASED\_ROUTING — `/decide-gateway`
Payload: 3 card variants rotated across VUs (VISA Debit/AED, Mastercard Credit/USD,
Amex Debit/EUR), 2–3 eligible gateways each.
### Throughput and latency
| VUs | Throughput | RT avg | RT p50 | RT p95 | Server avg | Server p50 | Server p95 | HTTP avg | HTTP p95 |
| -: | -: | -: | -: | -: | -: | -: | -: | -: | -: |
| 5 | 38 req/s | 8 ms | 7 ms | 15 ms | 5 ms | 4 ms | 10 ms | 3 ms | 6 ms |
| 20 | 147 req/s | 10 ms | 8 ms | 20 ms | 6 ms | 5 ms | 14 ms | 4 ms | 9 ms |
| 50 | 345 req/s | 15 ms | 12 ms | 33 ms | 10 ms | 8 ms | 23 ms | 6 ms | 13 ms |
Every `/decide-gateway` response includes a `latency` field (milliseconds) reporting
the pod's own processing time. Use this in your monitoring to separate compute time
from HTTP stack overhead in production.
**Key observations**
* Server-side p95 holds at **14 ms up to 147 req/s** (20 VUs) — gateway outages and
payment-flow config are served from in-process caches, eliminating per-request DB queries.
* At 50 VUs (345 req/s), server p95 is **23 ms**.
* The HTTP overhead column (round-trip − server-side) reflects HTTP framing and serialisation
cost, not network distance. Add your production RTT on top of the round-trip figures.
These figures model realistic client behaviour with a 100 ms pause between requests.
They reflect sustainable throughput for a typical integration, not raw server capacity.
See the saturation section below for the throughput ceiling.
### Feedback path — `/update-gateway-score`
Every `/decide-gateway` call is followed by a fire-and-forget feedback write to
`/update-gateway-score`. This is what keeps SR scores current — it records the
outcome of each routing decision back into Redis so the next decision reflects
real gateway performance. It runs outside the routing response path and does not
block the caller, but it does consume pod resources and contributes to Redis load.
| VUs | Feedback avg | Feedback p95 |
| -: | -: | -: |
| 5 | 2 ms | 4 ms |
| 20 | 3 ms | 7 ms |
| 50 | 3 ms | 6 ms |
Feedback latency stays flat under load because it is a single Redis write with no
read dependencies. At 345 req/s (50 VUs) this means \~345 score updates per second
— well within the Redis pool capacity at `pool_size = 5` with auto-pipelining.
***
### Saturation point
To find the raw throughput ceiling, the same endpoint was driven with **no sleep**
between requests — each VU fires as fast as the server can respond.
Test conditions: release build (LTO, `codegen-units=1`), 2-CPU Docker limit,
0% error rate throughout. CPU% captured via `docker stats` in parallel; 200% = 2 cores fully utilized.
| VUs | Throughput | CPU% |
| -: | -: | -: |
| 5 | 678 req/s | 151% |
| 10 | 816 req/s | 190% |
| **20** | **835 req/s** | **195%** |
| 30 | 831 req/s | 198% |
| 50 | 815 req/s | 198% |
| 75 | 792 req/s | 196% |
| 100 | 789 req/s | 198% |
| 150 | 779 req/s | 197% |
| 200 | 741 req/s | 197% |
| 300 | 725 req/s | 199% |
**Interpretation**
* **Peak: 835 req/s at 20 in-flight requests.** CPU crosses 190% at 10 VUs and stays
there — both cores are fully loaded from that point on.
* **Sustained ceiling: 725–835 req/s** from 20 to 300 VUs with zero errors. The pod
does not shed requests under overload; it queues them.
* The sleep-based figures (345 req/s at 50 VUs) represent 41% of this ceiling. The
gap is client think-time, not server capacity.
```bash theme={null}
bash scripts/load-test/benchmark.sh --saturation --max-vus 300 --step-dur 20s
```
***
## RULE\_BASED\_ROUTING — `/routing/evaluate`
Payload: same 3 payment attribute variants (amount + authentication\_type), evaluated
against an active priority rule: **checkout → stripe → adyen**.
### Throughput and latency
| VUs | Throughput | RT avg | RT p50 | RT p95 | Error rate |
| -: | -: | -: | -: | -: | -: |
| 5 | 39 req/s | 6 ms | 4 ms | 17 ms | 0.06% |
| 20 | 153 req/s | 7 ms | 4 ms | 17 ms | 0.01% |
| 50 | 389 req/s | 6 ms | 4 ms | 14 ms | 0.01% |
`/routing/evaluate` does not include a `latency` field in the response, so server-side
and network latency cannot be separated for this endpoint.
**Key observations**
* p95 stays flat at **14–17 ms across all concurrency levels** and does not grow under load.
* Throughput scales to **389 req/s on a single 2-core pod** — rule evaluation is pure
in-memory computation with no Redis or DB I/O.
***
## SR vs Rule-based
| VUs | SR throughput | SR server p95 | Rule RT p95 |
| -: | -: | -: | -: |
| 5 | 38 req/s | 10 ms | 17 ms |
| 20 | 147 req/s | 14 ms | 17 ms |
| 50 | 345 req/s | 23 ms | 14 ms |
SR server-side p95 climbs at 50 VUs as Redis round-trips grow under contention.
This is well below the pod's CPU saturation point (\~835 req/s peak with no-sleep
load); the sleep-based test reaches Redis contention before it saturates CPU.
Rule-based p95 stays flat because it issues no external I/O.
***
## Scaling Guide
### SR\_BASED\_ROUTING
Ceiling per 2-core pod: **\~725–835 req/s** (835 req/s peak at 20 in-flight requests,
sustained above 725 req/s all the way to 300 in-flight with zero errors).
| Target throughput | Pods | CPU per pod | Notes |
| -: | -: | -: | - |
| \< 100 req/s | 1 | 2 cores | Comfortable headroom — well below saturation |
| 100 – 400 req/s | 1 | 2 cores | Pod within capacity; latency remains flat |
| 400 – 800 req/s | 1 | 2 cores | Approaching ceiling; monitor server p95 |
| > 800 req/s | 2+ | 2 cores | Add pods; raise Redis `pool_size` proportionally |
### RULE\_BASED\_ROUTING
| Target throughput | Pods | CPU per pod | Notes |
| -: | -: | -: | - |
| \< 400 req/s | 1 | 2 cores | Single pod handles comfortably |
| > 400 req/s | 2+ | 2 cores | Linear scale-out; p95 remains flat |
Do not set CPU requests below 1000m. The Tokio async runtime sizes its worker thread
pool based on available CPUs — a very small quota results in a single worker thread
and elevated latency under concurrency.
***
## What Affects Performance
**Log level — largest single factor**
Running at `DEBUG` emits \~55 JSON-serialised log lines per request. At 345 req/s
(50 VUs) this means \~19 000 extra serialisations per second and raises server-side p95
significantly. Always set `INFO` or higher outside of active debugging.
```toml theme={null}
[log.console]
level = "INFO"
```
**Redis round-trips (SR routing only)**
Each SR routing decision reads per-gateway SR scores from Redis, checks in-flight
keys, and writes feedback scores. Gateway outage lists and per-merchant payment-flow
config are served from in-process caches (30 s and 60 s TTL respectively) so only
the SR score lookups reach Redis on the hot path. With `pool_size = 5` and
auto-pipelining this handles the full \~835 req/s pod ceiling on a single 2-core pod.
Raise `pool_size` proportionally when adding pods.
```toml theme={null}
[redis]
pool_size = 10 # default 5; raise when adding pods beyond the first
auto_pipeline = true # keep enabled
```
**CPU allocation**
The runtime sizes its worker pool based on available CPUs. With a 2-core limit the pod
runs 2 concurrent async workers, which is the binding constraint for SR routing throughput.
***
## Reproducing These Results
```bash theme={null}
# SR + Rule-based routing (sleep-based, realistic think-time)
bash scripts/load-test/benchmark.sh
# Saturation test — find raw throughput ceiling (no sleep, ramps to max VUs)
bash scripts/load-test/benchmark.sh --saturation
bash scripts/load-test/benchmark.sh --saturation --max-vus 300 --step-dur 20s
# Results are saved to scripts/load-test/profile_results/ after each run
```
## Related Docs
* [Configuration](/decision-engine-api-reference/configuration) — log level and Redis pool settings referenced above.
* [Local Setup Guide](/decision-engine-api-reference/local-setup) — bringing up the stack these benchmarks run against.
* [API Guide](/decision-engine-api-reference/api-reference/guides/api-ref) — `/decide-gateway` and `/routing/evaluate` request examples.
# ClickHouse Analytics
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/clickhouse-analytics
ClickHouse setup notes for analytics
## Overview
Decision Engine uses a Kafka to ClickHouse analytics pipeline:
* API server captures full request and response bodies for API analytics events
* API server publishes analytics events to Kafka
* ClickHouse Kafka engine queue tables consume Kafka and materialized views fan into the raw tables
ClickHouse remains the analytics read store for:
* business-domain analytics events
* raw API request and response events
The analytics read path uses the two raw tables:
* `analytics_domain_events`
* `analytics_api_events`
The ingestion path is explicit in ClickHouse too:
* `analytics_domain_events_queue`
* `analytics_api_events_queue`
* `analytics_payment_audit_summary_buckets`
* `analytics_domain_events_mv`
* `analytics_api_events_mv`
* `analytics_payment_audit_summary_buckets_mv`
Payment Audit and Preview Trace now use a two-layer read shape:
* raw event timelines still read from `analytics_domain_events`
* summary lists read from the pre-aggregated `analytics_payment_audit_summary_buckets`
The correlation key for those reads is the write-time `lookup_key`:
* `payment_id` when present
* otherwise `request_id`
## Local Bring-Up
Start the local analytics stack:
```bash theme={null}
COMPOSE_PROFILES= docker compose --profile analytics-clickhouse up -d
```
That profile now includes ClickHouse, Kafka, and topic creation. The full runtime profiles use the same ClickHouse-native ingestion path. There is no separate Rust worker process anymore.
Local Compose versions:
* ClickHouse: `clickhouse/clickhouse-server:26.1`
* Kafka: `apache/kafka:3.8.1`
* ClickHouse database: `default`
The bootstrap DDL now lives in:
* `clickhouse/scripts/`
ClickHouse loads those shell scripts on first boot through `/docker-entrypoint-initdb.d`. They create the raw tables, recreate the Kafka queue tables and materialized views, create the payment-audit summary bucket table, and bind the queue tables to the configured Kafka brokers and topics.
The analytics data volume is persistent, so normal restarts keep historical data.
If you need a clean reset:
```bash theme={null}
make reset-analytics-clickhouse
```
## Config
Relevant config lives under:
```toml theme={null}
[analytics]
enabled = true
[analytics.capture]
details_max_bytes = 65536
[analytics.kafka]
# container-to-container traffic uses the internal listener
brokers = "kafka:19092"
client_id = "decision-engine"
api_topic = "api"
domain_topic = "domain"
acks = "all"
compression = "lz4"
message_timeout_ms = 5000
queue_capacity = 250
[analytics.clickhouse]
url = "http://clickhouse:8123"
database = "default"
user = "decision_engine"
password = "decision_engine"
```
There is no direct API-server write path to ClickHouse anymore. ClickHouse owns Kafka consumption through the queue tables and materialized views.
## Retention
The raw analytics tables retain data for 18 months:
* `analytics_api_events`
* `analytics_domain_events`
Custom query windows are normalized to the same 18-month lookback horizon.
## Troubleshooting
Useful checks when ingestion looks stalled:
```sql theme={null}
SHOW TABLES FROM default;
SELECT * FROM system.kafka_consumers WHERE database = 'default';
SELECT count() FROM default.analytics_api_events;
SELECT count() FROM default.analytics_domain_events;
SELECT count() FROM default.analytics_payment_audit_summary_buckets;
SELECT name, engine FROM system.tables WHERE database = 'default' AND name LIKE 'analytics_%';
```
## Related Docs
* [Analytics](/decision-engine-api-reference/analytics) — the operator-facing view built on this pipeline.
* [Payment Audit](/decision-engine-api-reference/payment-audit) — single-payment timeline lookups against these tables.
* [Local Setup Guide](/decision-engine-api-reference/local-setup) — bringing up the `analytics-clickhouse` profile.
# Configuration
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/configuration
Configure Decision Engine via config files and environment variable overrides.
# Configuration Guide
This document explains how to configure Decision Engine for local and on-prem deployments.
## Primary Config Files
* `config/development.toml`: used for host/source runs
* `config/docker-configuration.toml`: used for Docker and Compose runs
* `helm-charts/config/development.toml`: Kubernetes chart template config
These files already exist with all required sections. Edit the one that matches your runtime rather than copying from `config.example.toml`, which is incomplete.
## Config Sections
### Server
```toml theme={null}
[server]
host = "0.0.0.0"
port = 8080
```
`host` is the bind address. Use `0.0.0.0` for Docker/deployed, `127.0.0.1` for local-only.
### Logging
```toml theme={null}
[log.console]
enabled = true
level = "DEBUG"
log_format = "default"
```
`log_format` accepts `"default"` (human-readable) or `"json"` (structured, recommended for prod).
### Metrics
```toml theme={null}
[metrics]
host = "0.0.0.0"
port = 9094
```
Prometheus metrics are exposed at `host:port/metrics`. Used by the `monitoring` Compose profile (Prometheus scrapes `9094`, Grafana at `3000`).
### Rate Limiting
```toml theme={null}
[limit]
request_count = 1
duration = 60
```
Controls rate limiting on the delete APIs. `request_count` requests allowed per `duration` seconds.
### Redis cache config
```toml theme={null}
[cache_config]
service_config_redis_prefix = "DE_service_config_"
service_config_ttl = 300 # Redis TTL for service config entries, in seconds
```
### Database
MySQL and PostgreSQL use separate config sections.
**MySQL:**
```toml theme={null}
[database]
username = "db_user"
password = "db_pass"
host = "localhost"
port = 3306
dbname = "decision_engine_db"
```
**PostgreSQL:**
```toml theme={null}
[pg_database]
pg_username = "db_user"
pg_password = "db_pass"
pg_host = "localhost"
pg_port = 5432
pg_dbname = "decision_engine_db"
```
For Docker Compose runs both are pre-wired via service names in `config/docker-configuration.toml`.
### Multi-Tenant Schema
```toml theme={null}
[tenant_secrets]
public = { schema = "public" }
```
Maps tenant identifiers to database schemas. The shipped config files (`config/development.toml`, `config/docker-configuration.toml`) define only the `public` tenant — add entries for any additional tenant you want to support.
Some routes resolve the tenant from an `x-tenant-id` request header rather than the authenticated merchant, and reject the request outright if it's missing (`TE_03`). Send `x-tenant-id: public` on `GET /health/diagnostics`, every `GET /analytics/*` route, and `POST /gateway-score/reset` — see [API Guide](/decision-engine-api-reference/api-reference/guides/api-ref#environment-setup).
### Redis
```toml theme={null}
[redis]
host = "127.0.0.1"
port = 6379
```
Redis is required — it's used for caching routing config and service config. For Docker, use the service name as host.
### Auth
```toml theme={null}
[user_auth]
jwt_secret = "change_me_in_production_use_32chars!!"
jwt_expiry_seconds = 86400
email_verification_enabled = false
```
Use a strong, random `jwt_secret` — 32+ characters recommended. Set `email_verification_enabled = true` if you've wired an email provider.
### Admin Secret
```toml theme={null}
[admin_secret]
secret = "test_admin"
```
Used to authenticate the `POST /merchant-account/create` endpoint (admin bootstrap). Change this in production.
### API Key Auth
```toml theme={null}
api_key_auth_enabled = true
```
Top-level flag. When `true`, protected routes accept `x-api-key` in addition to JWT bearer tokens. When `false`, the auth middleware allows **all requests through without authentication** — this effectively disables auth for every protected route. Do not set this to `false` in any environment that should enforce auth.
### Analytics
Both Kafka and ClickHouse require `enabled = true` — without it, analytics is disabled even if the connection details are configured.
```toml theme={null}
[analytics.kafka]
enabled = true
brokers = "localhost:9092"
api_topic = "api"
domain_topic = "domain"
[analytics.clickhouse]
enabled = true
url = "http://localhost:8123"
user = "decision_engine"
password = "decision_engine"
```
Decision outcomes are published to Kafka and consumed into ClickHouse. Both are required for analytics and audit dashboard views. For Docker runs, these are pre-configured and enabled via the Compose profiles.
### TLS
```toml theme={null}
[tls]
certificate = "cert.pem"
private_key = "key.pem"
```
Paths to PEM-format certificate and key files. Only needed if you're terminating TLS at the app layer rather than a reverse proxy.
### API Client
```toml theme={null}
[api_client]
client_idle_timeout = 90
pool_max_idle_per_host = 10
identity = ""
```
Controls the outbound HTTP client used for upstream calls. Set `identity` to a PEM path if you need mTLS.
## Secrets Management
By default, secrets in config are stored in plaintext. For production, use one of the two supported backends.
### AWS KMS
Requires the `kms-aws` feature (included in the `release` feature set).
```toml theme={null}
[secrets_management]
secrets_manager = "aws_kms"
[secrets_management.aws_kms]
key_id = "your-kms-key-id"
region = "us-east-1"
```
### HashiCorp Vault
Requires the `kms-hashicorp-vault` feature.
```toml theme={null}
[secrets_management]
secrets_manager = "hashi_corp_vault"
[secrets_management.hashi_corp_vault]
url = "http://127.0.0.1:8200"
token = "hvs.your_token"
```
When a secrets manager is configured, sensitive fields like `database.password` and `user_auth.jwt_secret` are resolved from the vault rather than the config file.
## Environment Overrides
Selected values can be overridden at runtime via environment variables. This is useful in Helm deployments via `extraEnvVars`. Consult `src/config.rs` for the full mapping.
## Related Docs
* [Installation](/decision-engine-api-reference/installation)
* [Local Setup Guide](/decision-engine-api-reference/local-setup)
* [API Guide](/decision-engine-api-reference/api-reference/guides/api-ref)
* [API Reference](/decision-engine-api-reference/api-reference)
# Dashboard
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/dashboard-guide
Local dashboard routes and how they are served
## Availability
The dashboard is available in the `dashboard-*` Docker Compose profiles.
Example:
```bash theme={null}
COMPOSE_PROFILES= docker compose --profile dashboard-postgres-ghcr up -d
```
Then open:
* `http://localhost:8081/dashboard/`
The dashboard is served by Nginx from the built assets in `website/dist`. This docs page intentionally lives at `/dashboard-guide` — `/dashboard/` is reserved for the React app itself.
## What It Includes
Based on the React routes in `website/src/App.tsx`, the dashboard exposes:
* `/dashboard/`
* `/dashboard/login`
* `/dashboard/signup`
* `/dashboard/onboarding`
* `/dashboard/routing`
* `/dashboard/routing/sr`
* `/dashboard/routing/rules`
* `/dashboard/routing/volume`
* `/dashboard/routing/debit`
* `/dashboard/decisions`
* `/dashboard/analytics`
* `/dashboard/audit`
For source-run Vite development, the same React routes are mounted at `http://localhost:5173/`.
For external production hosting, the preferred route is `/decision-engine/` with API traffic proxied through `/decision-engine-api/*`.
## Docs And API In The Same Profile
The same `dashboard-*` profiles also expose:
* Mintlify docs at `http://localhost:8081/introduction`
* API examples at `http://localhost:8081/api-refs/api-ref`
* the API at `http://localhost:8080`
Proxy behavior is defined in `nginx/nginx.conf`.
## Related Files
* `website/src/App.tsx`
* `website/src/components/pages/*`
* `docker-compose.yaml`
* `nginx/nginx.conf`
## Related Docs
* [Installation](/decision-engine-api-reference/installation)
* [Local Setup Guide](/decision-engine-api-reference/local-setup)
* [Analytics](/decision-engine-api-reference/analytics)
* [Payment Audit](/decision-engine-api-reference/payment-audit)
# Installation
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/installation
Everything needed to get Decision Engine running locally, end to end.
# Installation Guide
This section covers everything needed to get Decision Engine running locally — from a single `docker compose up` to the full CLI, Docker, Compose, and Helm matrix.
## Prerequisites
The Quick Start below pulls prebuilt images from GHCR, so you do **not** need Rust, `make`, or a local database. You do need:
* **Docker Engine 20+**
* **Docker Compose v2+** (the `docker compose` subcommand, not the legacy `docker-compose` binary)
* **The repository cloned locally** — the compose command reads `docker-compose.yaml`, so run it from the repo root:
```bash theme={null}
git clone https://github.com/juspay/decision-engine.git
cd decision-engine
```
* Network access to pull `ghcr.io/juspay/...` images and a few GB of free disk (the first run pulls the app, PostgreSQL, Redis, Kafka, ClickHouse, and Mailpit).
## Quick Start
The fastest path to a running instance. Every service in `docker-compose.yaml` is gated behind a profile, so a profile is required — there is no default/unprofiled bring-up:
```bash theme={null}
docker compose --profile postgres-ghcr up -d
curl http://localhost:8080/health
```
Expected response:
```json theme={null}
{ "message": "Health is good" }
```
For the API, dashboard, and docs together, use `--profile dashboard-postgres-ghcr` instead — see [Dashboard](/decision-engine-api-reference/dashboard-guide).
## In This Section
| Page | Use it for |
| - | - |
| [Local Setup](/decision-engine-api-reference/local-setup) | The canonical guide — Compose profiles, source builds, Docker images without Compose, Helm, and troubleshooting. |
| [PostgreSQL Setup](/decision-engine-api-reference/setup-guide-postgres) | Postgres-specific Compose profiles, `make` targets, and verification. |
| [MySQL Setup](/decision-engine-api-reference/setup-guide-mysql) | The same, for MySQL. |
| [Configuration](/decision-engine-api-reference/configuration) | Config file reference and environment variable overrides once the service is up. |
| [Dashboard](/decision-engine-api-reference/dashboard-guide) | Bring up the React operator dashboard alongside the API. |
## Choosing A Database
Decision Engine supports PostgreSQL and MySQL as interchangeable backends. Pick one and follow its dedicated guide, or go straight to [Local Setup](/decision-engine-api-reference/local-setup) if you want the full profile matrix (dashboard, monitoring, source builds) rather than a database-first walkthrough.
## Next Steps
* [API Guide](/decision-engine-api-reference/api-reference/guides/api-ref) — copy-paste `curl` examples once the service is running.
# Decision Engine
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/introduction
What Decision Engine does — routing strategies, cost-aware routing, A/B testing, autopilot, analytics, and the dashboard
## What It Is
Decision Engine is a Rust service that sits between your orchestrator and your payment gateways. On every payment, it picks the best gateway from an eligible list — by rule, by live success rate, by cost, or some mix of all three — and records the outcome so future decisions keep improving. It runs standalone over HTTP: no vendor lock-in, no mandatory orchestrator.
## Core Capabilities
### Routing Strategies
`POST /decide-gateway` picks a connector using one of these strategies:
| Strategy | What it does |
| - | - |
| **Rule-based routing** | Priority order, single fixed connector, percentage volume split, or a full AND/OR/nested condition tree — authored via Euclid, Juspay's open rule engine, and evaluated in `POST /routing/create`/`/routing/evaluate`. |
| **Success-rate (auth-rate) based routing** | `SR_BASED_ROUTING` — ranks gateways by live transaction success rate, with hedging (exploration) and automatic downtime elimination for failing gateways. |
| **Debit / network-based routing** | `NTW_BASED_ROUTING` — routes debit transactions by co-badged card network for cost/compliance reasons. |
| **Network + SR hybrid routing** | `NTW_SR_HYBRID_ROUTING` — combines network eligibility with success-rate ranking. |
| **Multi-objective (cost-aware) routing** | Not a `rankingAlgorithm` value — a post-step *on top of* success-rate routing. Re-ranks gateways with cost data by expected value and promotes a cheaper one if it wins. See below. |
The first four are selected per request with `rankingAlgorithm`. See the [routing configuration guides](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-create) and [decide-gateway examples](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-sr-based) for full request/response detail.
### Multi-Objective (Cost-Aware) Routing
A post-step on top of success-rate scoring: after SR picks a head gateway, Decision Engine re-ranks every gateway with cost data by **economic value** (`EV = auth rate × settlement value`, where `settlement value = txn amount − cost of payment processing (acquirer, issuer & network fee)`), and promotes a cheaper gateway if it wins on EV. Toggle it per request (`enableMultiObjective`) or per merchant (`multi_objective_routing_enabled` feature flag). See [Multi-Objective Routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective).
### Cost Data Ingestion
Learns each connector's *real* fee — not a static rate card — from settlement reports and invoices, fitted down to a per-cluster level (connector × card network × variant × funding × issuer country × currency × interchange category). This is what feeds multi-objective routing's cost side. Reports arrive by webhook, scheduled poll, or manual upload; fees can be read, overridden per connector or per cluster, and audited for coverage. See [Cost Ingestion: Connector Setup](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-setup).
### A/B Testing
Split live traffic between a control and variant routing strategy — auth-only vs. cost-aware, manual vs. autopilot, or any two saved algorithms — with a configurable split percentage, a minimum sample size, and a guardrail that auto-flags a regression before it does damage. Built-in statistical significance testing (two-sample z-test) tells you when a variant actually wins. See [A/B Testing: Create An Experiment](/decision-engine-api-reference/api-reference/guides/ab-testing/ab-testing-create).
### Autopilot & Auto-Calibration
A background job that self-tunes success-rate scoring — hedging percentage and bucket size — from observed traffic, with no manual retuning. Every calibration run is logged as an auditable event, and a merchant can hard-reset live scores back to a clean baseline at any time. See [Merchant Features: Autopilot & Feature Flags](/decision-engine-api-reference/api-reference/guides/autopilot/merchant-features).
### Analytics & Audit
ClickHouse-backed views for everything above: routing overview, gateway score trends, decision volume, cost savings, routing events (leader changes, autopilot re-tunes), and a single-payment audit trail that answers "which gateway was picked, and why" for any transaction. See [Analytics Endpoints](/decision-engine-api-reference/api-reference/guides/analytics-audit/analytics-endpoints) and [Payment Audit](/decision-engine-api-reference/payment-audit).
### Dashboard
A React operator UI for configuring routing, running A/B tests, watching analytics, and auditing decisions without touching the API directly. See [Dashboard](/decision-engine-api-reference/dashboard-guide).
### Platform
* **Multi-DB** — MySQL and PostgreSQL as interchangeable backends.
* **Team management** — invite and manage members per merchant account, with role-based access.
* **API keys** — server-to-server auth alongside dashboard JWT sessions.
* **Debit routing gate** — per-merchant toggle for debit-network routing.
## Main API Surface
The API is organized into the following endpoint groups:
| Group | Endpoints | Purpose |
| - | - | - |
| Health | `GET /health`, `GET /health/ready`, `GET /health/diagnostics` | Liveness, readiness, and dependency diagnostics. |
| Auth | `POST /auth/signup`, `POST /auth/login`, `GET /auth/me` | Dashboard operator sign-up, login, and session. |
| Decisions | `POST /decide-gateway` | Choose a connector for a payment — see Routing Strategies above. |
| Feedback | `POST /update-gateway-score` | Report authorization outcomes back to scoring. |
| Merchant accounts | `POST /merchant-account/create`, `GET`/`DELETE /merchant-account/{merchantId}`, feature flags, debit-routing settings | Manage merchants and their configuration. |
| Routing | `POST /routing/*`, `POST /rule/*` | Create, activate, evaluate, and A/B test routing algorithms. |
| Cost ingestion | `POST/GET/DELETE /merchant-account/{merchantId}/connectors/*`, `.../cost-*` | Connector credentials, settlement/invoice uploads, fee overrides. |
| Analytics | `GET /analytics/*` | Gateway scores, decisions, cost savings, routing events, experiment results, audit. |
For copy-paste `curl` examples of each flow, see the [API Guide](/decision-engine-api-reference/api-reference/guides/api-ref). For exact request and response schemas, use the OpenAPI-backed endpoint pages under [API Reference](/decision-engine-api-reference/api-reference).
## Run Locally
For API only:
```bash theme={null}
docker compose --profile postgres-ghcr up -d
curl http://localhost:8080/health
```
For API + dashboard + docs:
```bash theme={null}
docker compose --profile dashboard-postgres-ghcr up -d
```
URLs:
* API: `http://localhost:8080`
* Dashboard: `http://localhost:8081/dashboard/`
* Docs: `http://localhost:8081/introduction`
Use [Installation](/decision-engine-api-reference/installation) for the full Compose, database, and Helm matrix.
## Where To Go Next
* [Installation](/decision-engine-api-reference/installation) — Docker Compose, PostgreSQL/MySQL setup, and configuration, end to end.
* [Dashboard](/decision-engine-api-reference/dashboard-guide) — route-by-route guide to the React operator dashboard.
* [API Guide (curl examples)](/decision-engine-api-reference/api-reference/guides/api-ref) — copy-paste flows for every route family, including cost ingestion, A/B testing, and autopilot.
* [API Reference (OpenAPI)](/decision-engine-api-reference/api-reference) — schema-backed endpoint pages with a request playground.
# Local Setup
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/local-setup
Full Docker Compose, source-build, and Helm matrix for running Decision Engine locally.
# Local Setup Guide
This is the canonical local startup guide for Decision Engine.
## Prerequisites
* Docker 20+
* Docker Compose v2+
* Git 2+
Required for source runs:
* Rust 1.85+
* PostgreSQL or MySQL
* Redis
* [`just`](https://just.systems) — required for PostgreSQL source runs (`just migrate-pg`); MySQL can use `diesel migration run` directly
## Runtime Tracks
Decision Engine supports two local tracks:
1. **Published-image track** — pull existing images.
2. **Local-build track** — build images or binaries from the current source tree.
Default tags used in this repo:
* `DECISION_ENGINE_TAG=v1.4`
* `GROOVY_RUNNER_TAG=v1.4`
## Docker Compose Profiles
You must pass at least one profile.
### Core runtime profiles
| Profile | DB | Includes |
| - | - | - |
| `postgres-ghcr` | PostgreSQL | API + PostgreSQL + Redis + Kafka + ClickHouse + PG migrations |
| `postgres-local` | PostgreSQL | API + PostgreSQL + Redis + Kafka + ClickHouse + PG migrations |
| `mysql-ghcr` | MySQL | API + MySQL + Redis + Kafka + ClickHouse + MySQL migrations + routing-config |
| `mysql-local` | MySQL | API + MySQL + Redis + Kafka + ClickHouse + MySQL migrations + routing-config |
### Dashboard profiles
| Profile | DB | Includes |
| - | - | - |
| `dashboard-postgres-ghcr` | PostgreSQL | core PG stack + dashboard + Mintlify docs |
| `dashboard-postgres-local` | PostgreSQL | core PG stack + dashboard + Mintlify docs |
| `dashboard-mysql-ghcr` | MySQL | core MySQL stack + dashboard + Mintlify docs |
| `dashboard-mysql-local` | MySQL | core MySQL stack + dashboard + Mintlify docs |
### Optional profiles
| Profile | Adds |
| - | - |
| `monitoring` | Prometheus + Grafana |
| `groovy-ghcr` | Groovy runner image |
| `groovy-local` | Groovy runner built from local source |
| `analytics-clickhouse` | Kafka topic init + ClickHouse analytics bootstrap only |
## Fastest Bring-Up
### One-Command Local Dev
For local source-run development with the full PostgreSQL analytics stack:
```bash theme={null}
./oneclick.sh
```
For the full end-to-end regression gate owned by the Cypress branch:
```bash theme={null}
npm run test:e2e
```
That command runs:
* source-run validation through `oneclick.sh`
* Docker Compose validation through `dashboard-postgres-local`
* the full Cypress API/UI/docs smoke contract against both modes
Mode-specific entrypoints:
```bash theme={null}
npm run test:e2e:source
npm run test:e2e:docker
```
This flow:
* starts PostgreSQL, Redis, Kafka, ClickHouse, and the analytics init jobs with Docker Compose
* waits for infra health
* runs PostgreSQL migrations
* starts the API locally with `cargo run --no-default-features --features postgres`
* starts the dashboard locally with Vite on `http://localhost:5173/`
By default, `Ctrl+C` stops the local API/dashboard processes and any infra services that `oneclick.sh`
started itself. To keep infra running after exit:
```bash theme={null}
ONECLICK_KEEP_INFRA=1 ./oneclick.sh
```
### API Only
```bash theme={null}
docker compose --profile postgres-ghcr up -d
```
### API + Dashboard + Docs
```bash theme={null}
docker compose --profile dashboard-postgres-ghcr up -d
```
### With Monitoring
```bash theme={null}
docker compose --profile postgres-ghcr --profile monitoring up -d
```
## Make Targets
Common wrappers:
```bash theme={null}
make init-pg-ghcr
make init-pg-local
make init-mysql-ghcr
make init-mysql-local
make run-pg-ghcr
make run-mysql-local
make reset-analytics-clickhouse
make stop
```
## Analytics Bootstrap
The Kafka to ClickHouse analytics path is bootstrapped automatically.
* Kafka topics are created by `kafka-init`
* ClickHouse loads analytics SQL from `clickhouse/scripts/` on first boot
* analytics data is stored in the named Docker volume `clickhouse-data`
* normal restarts keep analytics history intact
If you need a clean analytics rebuild, use:
```bash theme={null}
make reset-analytics-clickhouse
```
That removes the ClickHouse analytics volume and recreates the Kafka + ClickHouse analytics stack.
## Source Build And Run
### PostgreSQL
```bash theme={null}
cargo build --release --no-default-features --features middleware,kms-aws,postgres
just migrate-pg
RUSTFLAGS="-Awarnings" cargo run --no-default-features --features postgres
```
### MySQL
```bash theme={null}
cargo build --release --features release
RUSTFLAGS="-Awarnings" cargo run --features release
```
## Docker Builds Without Compose
```bash theme={null}
docker build --platform=linux/amd64 -t decision-engine-mysql:local -f Dockerfile .
docker build --platform=linux/amd64 -t decision-engine-pg:local -f Dockerfile.postgres .
```
Example container run:
```bash theme={null}
docker run --platform=linux/amd64 \
-v $(pwd)/config/docker-configuration.toml:/local/config/development.toml \
-p 8080:8080 \
decision-engine-pg:local
```
## Helm
Chart location: `helm-charts/`
```bash theme={null}
cd helm-charts
helm dependency update
helm install my-release .
```
Use `helm dependency update`, not `helm dependency build` — the committed `Chart.lock` digest can drift out of sync with `Chart.yaml`, and `build` fails hard on any mismatch (`Error: the lock file (Chart.lock) is out of sync with the dependencies file`). `update` re-resolves and re-fetches the `postgresql`, `mysql`, and `redis` subcharts from the Bitnami repo unconditionally.
For image overrides, use `image.repository`, `image.version`, and `image.pullPolicy`. Verify with `helm install --dry-run` or `helm template` before applying to a cluster.
## Verification
```bash theme={null}
curl http://localhost:8080/health
```
Expected response:
```json theme={null}
{"message":"Health is good"}
```
Dashboard profiles also expose:
* Dashboard: `http://localhost:8081/dashboard/`
* Docs: `http://localhost:8081/introduction`
* API examples: `http://localhost:8081/api-refs/api-ref`
Monitoring profile also exposes:
* Prometheus: `http://localhost:9090`
* Grafana: `http://localhost:3000`
## Troubleshooting
### Recreate a profile with clean volumes
```bash theme={null}
docker compose --profile postgres-ghcr down -v
docker compose --profile postgres-ghcr up -d
```
### Inspect migration jobs
```bash theme={null}
docker compose logs db-migrator-postgres
docker compose logs db-migrator
```
### Inspect analytics infrastructure
```bash theme={null}
docker compose logs kafka-init
docker compose logs clickhouse
```
Check the ClickHouse schema directly:
```bash theme={null}
curl --user decision_engine:decision_engine \
"http://localhost:8123/?query=SHOW%20TABLES%20FROM%20default"
```
### Common Next Files To Inspect
* `docker-compose.yaml`
* `config/docker-configuration.toml`
* `src/config.rs`
* `src/app.rs`
## Related Docs
* [Installation](/decision-engine-api-reference/installation)
* [PostgreSQL Setup](/decision-engine-api-reference/setup-guide-postgres)
* [MySQL Setup](/decision-engine-api-reference/setup-guide-mysql)
* [Configuration](/decision-engine-api-reference/configuration)
* [API Guide](/decision-engine-api-reference/api-reference/guides/api-ref)
# Payment Audit
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/payment-audit
Search a payment or request and inspect the full routing timeline
## What It Shows
Payment Audit is the operator-facing timeline view for a single payment or request.
Use it when you want to answer questions like:
* which gateway was decided for this payment
* which priority rule was hit
* whether a score update succeeded or failed
* what structured event payload was captured at each step
The page is designed for exact lookups first and broad operator filtering second.
## Search Inputs
The page supports these filters:
* `payment_id`
* `request_id`
* `gateway`
* `route`
* `status`
* `flow_type`
* time window: `15m`, `1h`, `12h`, `1d`, `1w`
Use an exact `payment_id` when you have it. If you only have a request trace, use `request_id`.
Payment Audit is always merchant-scoped by the authenticated JWT or API key. The route does not
accept `scope` or `merchant_id` query params.
## Timeline Stages
The timeline is built from analytics events captured by the live request flows.
Current stages include:
* `gateway_decided`
* `rule_applied`
* `score_updated`
* `preview_evaluated`
* `request_read_failed`
* `validation_failed`
* `request_parse_failed`
* `score_update_failed`
The raw flow type remains visible as well, for example `decide_gateway_decision`,
`decide_gateway_rule_hit`, `update_gateway_score_update`, or `routing_evaluate_advanced`.
## Data Sources
Payment Audit reads from the same ClickHouse analytics store used by the analytics surface.
The read path is split intentionally:
* exact `payment_id` / `request_id` lookups read the raw `analytics_domain_events` timeline
* broad search results read pre-aggregated `analytics_payment_audit_summary_buckets`
Both views correlate events through the write-time `lookup_key`, which prefers `payment_id` and
falls back to `request_id`.
Relevant fields include:
* `merchant_id`
* `payment_id`
* `request_id`
* `event_stage`
* `route`
* `gateway`
* `routing_approach`
* `rule_name`
* `status`
* `error_code`
* `error_message`
* `details`
The `details` field is shown as structured JSON when available.
## Route
When the dashboard profile is running, open:
* `http://localhost:8081/dashboard/audit`
## Related Files
* `website/src/components/pages/PaymentAuditPage.tsx`
* `src/routes/analytics.rs`
* `src/analytics/models.rs`
* `src/analytics/service.rs`
* `src/decider/gatewaydecider/`
* `src/feedback/gateway_scoring_service.rs`
## Related Docs
* [Analytics](/decision-engine-api-reference/analytics) — the broader operator-facing metrics view.
* [ClickHouse Analytics](/decision-engine-api-reference/clickhouse-analytics) — the underlying ingestion pipeline and schema.
* [Dashboard](/decision-engine-api-reference/dashboard-guide) — where this view is surfaced.
# MySQL Setup
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/setup-guide-mysql
Set up Decision Engine with a MySQL database.
# MySQL Setup Guide
This page provides MySQL-focused commands. For the full end-to-end setup — CLI, Docker, Compose, Helm — see the [Local Setup Guide](/decision-engine-api-reference/local-setup).
## Docker Compose (GHCR track)
```bash theme={null}
export DECISION_ENGINE_TAG=v1.4
COMPOSE_PROFILES= docker compose --profile mysql-ghcr up -d
```
With dashboard + docs:
```bash theme={null}
COMPOSE_PROFILES= docker compose --profile dashboard-mysql-ghcr up -d
```
## Docker Compose (Local build track)
```bash theme={null}
COMPOSE_PROFILES= docker compose --profile mysql-local up -d --build
```
With dashboard + docs:
```bash theme={null}
COMPOSE_PROFILES= docker compose --profile dashboard-mysql-local up -d --build
```
## Make targets
```bash theme={null}
make init-mysql-ghcr
make init-mysql-local
```
## Verify
```bash theme={null}
curl http://localhost:8080/health
```
Expected response:
```json theme={null}
{"message":"Health is good"}
```
## Related Docs
* [Installation](/decision-engine-api-reference/installation)
* [Local Setup Guide](/decision-engine-api-reference/local-setup)
* [PostgreSQL Setup](/decision-engine-api-reference/setup-guide-postgres)
* [Configuration](/decision-engine-api-reference/configuration)
# PostgreSQL Setup
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/setup-guide-postgres
Set up Decision Engine with a PostgreSQL database.
# PostgreSQL Setup Guide
This page provides PostgreSQL-focused commands. For the full end-to-end setup — CLI, Docker, Compose, Helm — see the [Local Setup Guide](/decision-engine-api-reference/local-setup).
## Docker Compose (GHCR track)
```bash theme={null}
export DECISION_ENGINE_TAG=v1.4
COMPOSE_PROFILES= docker compose --profile postgres-ghcr up -d
```
With dashboard + docs:
```bash theme={null}
COMPOSE_PROFILES= docker compose --profile dashboard-postgres-ghcr up -d
```
## Docker Compose (Local build track)
```bash theme={null}
COMPOSE_PROFILES= docker compose --profile postgres-local up -d --build
```
With dashboard + docs:
```bash theme={null}
COMPOSE_PROFILES= docker compose --profile dashboard-postgres-local up -d --build
```
## Make targets
```bash theme={null}
make init-pg-ghcr
make init-pg-local
```
## Verify
```bash theme={null}
curl http://localhost:8080/health
```
Expected response:
```json theme={null}
{"message":"Health is good"}
```
## Related Docs
* [Installation](/decision-engine-api-reference/installation)
* [Local Setup Guide](/decision-engine-api-reference/local-setup)
* [MySQL Setup](/decision-engine-api-reference/setup-guide-mysql)
* [Configuration](/decision-engine-api-reference/configuration)
# Add Data in Locker
Source: https://api-reference.hyperswitch.io/locker-api-reference/cards/add-data-in-locker
rust_locker_open_api_spec post /data/add
Add sensitive data in the locker
# Delete Data from Locker
Source: https://api-reference.hyperswitch.io/locker-api-reference/cards/delete-data-from-locker
rust_locker_open_api_spec post /data/delete
Delete sensitive data from the locker
# Get or insert the data fingerprint
Source: https://api-reference.hyperswitch.io/locker-api-reference/cards/get-or-insert-the-card-fingerprint
post /data/fingerprint
Get or insert the data fingerprint
# Retrieve Data from Locker
Source: https://api-reference.hyperswitch.io/locker-api-reference/cards/retrieve-data-from-locker
rust_locker_open_api_spec post /data/retrieve
Retrieve sensitive data from the locker
# Provide Key 1
Source: https://api-reference.hyperswitch.io/locker-api-reference/key-custodian/provide-key-1
rust_locker_open_api_spec post /custodian/key1
Provide the first key to unlock the locker
# Provide Key 2
Source: https://api-reference.hyperswitch.io/locker-api-reference/key-custodian/provide-key-2
rust_locker_open_api_spec post /custodian/key2
Provide the second key to unlock the locker
# Unlock the locker
Source: https://api-reference.hyperswitch.io/locker-api-reference/key-custodian/unlock-the-locker
rust_locker_open_api_spec post /custodian/decrypt
Unlock the locker with the key1 and key2 provided
# Add Data in Locker
Source: https://api-reference.hyperswitch.io/locker-api-reference/locker-general-purpose-storage/add-data-in-locker
locker-v2 post /api/v2/vault/add
Add sensitive data in the locker
# Delete Data from Locker
Source: https://api-reference.hyperswitch.io/locker-api-reference/locker-general-purpose-storage/delete-data-from-locker
locker-v2 post /api/v2/vault/delete
Delete sensitive data from the locker
# Get or insert the data fingerprint
Source: https://api-reference.hyperswitch.io/locker-api-reference/locker-general-purpose-storage/get-or-insert-the-card-fingerprint
locker-v2 post /api/v2/vault/fingerprint
Get or insert the data fingerprint
# Retrieve Data from Locker
Source: https://api-reference.hyperswitch.io/locker-api-reference/locker-general-purpose-storage/retrieve-data-from-locker
locker-v2 post /api/v2/vault/retrieve
Retrieve sensitive data from the locker
# Get Health
Source: https://api-reference.hyperswitch.io/locker-api-reference/locker-health/get-health
rust_locker_open_api_spec get /health
To check whether the application is up
# Overview
Source: https://api-reference.hyperswitch.io/locker-api-reference/overview
The Hyperswitch Card Vault is a highly performant and a secure vault to save sensitive data such as payment card details, bank account details etc.
It is designed in an polymorphic manner to handle and store any type of sensitive information making it highly scalable with extensive coverage of payment methods and processors.
Hyperswitch Card Vault is built with a GDPR compliant personal identifiable information (PII) storage and secure encryption algorithms to be fully compliant with PCI DSS requirements.
Here's a quick guide to [Get Started](https://github.com/juspay/hyperswitch-card-vault/blob/main/docs/guides/setup.md) with setting up Hyperswitch Card Vault.
## How does Hyperswitch Card Vault work?
* Your application will communicate with Hyperswitch Card Vault via a middleware.
* All requests and responses to and from the middleware are signed and encrypted with the JWS and JWE algorithms.
* The locker supports CRD APIs on the /data and /cards endpoints -
* Cards are stored against the combination of merchant and customer identifiers.
* Internal hashing checks are in place to avoid data duplication.

## Key Hierarchy
* Master Key - AES generated key to that is encrypted/decrypted by the custodian keys to run the locker and associated configurations.
* Custodian Keys - AES generated key that is used to encrypt and decrypt the master key. It broken into two keys (key 1 and key 2) and available with two custodians to enhance security.

## Setup Guide
Follow this guide to setup - [Get Started](https://github.com/juspay/hyperswitch-card-vault/blob/main/docs/guides/setup.md)
# Configure SR Dimensions
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/compatibility/configSrDimension
decision_engine_openapi-specs.json POST /config-sr-dimension
Configure success-rate routing dimensions.
# Get Routing Config
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/compatibility/getRoutingConfig
decision_engine_openapi-specs.json GET /config/routing-keys
Return rule-builder routing keys and supported values.
# Get SR Dimensions
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/compatibility/getSrDimensions
decision_engine_openapi-specs.json GET /config-sr-dimension/{merchant_id}
Retrieve the success-rate routing dimension configuration for a merchant.
# Delete Connector Credentials
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/connector-costs/deleteConnectorCredentials
decision_engine_openapi-specs.json DELETE /merchant-account/{merchant_id}/connectors/{connector}/credentials/{account}
Remove a connector account's stored cost-report credentials.
# Delete Cost Ingestion
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/connector-costs/deleteCostIngestion
decision_engine_openapi-specs.json DELETE /merchant-account/{merchant_id}/cost-ingestions/{ingestion_id}
Delete a specific cost ingestion and its staged data.
# Delete Invoice Add-on
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/connector-costs/deleteInvoiceAddon
decision_engine_openapi-specs.json DELETE /merchant-account/{merchant_id}/connectors/{connector}/invoice-addon
Remove a connector's invoice-derived fee add-on.
# Get Cost Coverage
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/connector-costs/getCostCoverage
decision_engine_openapi-specs.json GET /merchant-account/{merchant_id}/cost-coverage
Summary of how much of the merchant's volume is covered by good (well-modelled) cost clusters.
# Get Invoice Reconciliation
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/connector-costs/getInvoiceReconciliation
decision_engine_openapi-specs.json GET /merchant-account/{merchant_id}/invoice-reconciliation
Reconciliation of invoice subtotals against modelled + add-on captured fees, per connector.
# List Connector Credentials
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/connector-costs/listConnectorCredentials
decision_engine_openapi-specs.json GET /merchant-account/{merchant_id}/connectors
Masked list of connector cost-report credentials configured for the merchant.
# List Connector Fees
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/connector-costs/listConnectorFees
decision_engine_openapi-specs.json GET /merchant-account/{merchant_id}/connector-fees
Per-connector modelled and effective fee rates (model, override and effective pct_bps/fixed).
# List Cost Clusters
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/connector-costs/listCostClusters
decision_engine_openapi-specs.json GET /merchant-account/{merchant_id}/cost-clusters
Learned per-dimension cost clusters (network/funding/country/currency/IC category) with modelled and effective fees.
# List Cost Ingestions
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/connector-costs/listCostIngestions
decision_engine_openapi-specs.json GET /merchant-account/{merchant_id}/cost-ingestions
History of uploaded/pulled cost-report ingestions with staged rows, gross, and status.
# List Cost Price Changes
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/connector-costs/listCostPriceChanges
decision_engine_openapi-specs.json GET /merchant-account/{merchant_id}/cost-price-changes
Detected changes in cluster pricing (old vs new pct_bps/fixed) across ingestions.
# List Invoice Add-ons
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/connector-costs/listInvoiceAddons
decision_engine_openapi-specs.json GET /merchant-account/{merchant_id}/invoice-addons
Per-connector periodic-fee add-ons learned from uploaded invoices.
# Set Cost Cluster Override
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/connector-costs/setClusterOverride
decision_engine_openapi-specs.json PUT /merchant-account/{merchant_id}/cost-clusters/{cluster_key}/fee-override
Override the modelled fee for a specific cost cluster identified by its cluster key.
# Set Connector Credentials
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/connector-costs/setConnectorCredentials
decision_engine_openapi-specs.json POST /merchant-account/{merchant_id}/connectors/{connector}/credentials
Store the account and report-download credentials used to pull a connector's cost reports.
# Set Connector Fee Override
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/connector-costs/setFeeOverride
decision_engine_openapi-specs.json PUT /merchant-account/{merchant_id}/connectors/{connector}/fee-override
Manually override the effective fee (pct_bps + fixed) for a connector.
# Get Merchant Features
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/features/getMerchantFeatures
decision_engine_openapi-specs.json GET /merchant-account/{merchant_id}/features
List the merchant's feature-flag states (GSM scoring, explore/exploit, A/B, multi-objective, elimination).
# Reset Gateway Scores
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/features/resetGatewayScores
decision_engine_openapi-specs.json POST /gateway-score/reset
Flush a merchant's live gateway (success-rate) scores and any manual overrides.
# Update Merchant Feature
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/endpoint/features/updateMerchantFeature
decision_engine_openapi-specs.json POST /merchant-account/{merchant_id}/features/{feature}
Enable or disable a single feature flag for the merchant.
# A/B Testing: Create An Experiment
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/ab-testing/ab-testing-create
Curl examples for creating and activating a routing A/B test via /routing/create.
# A/B Testing: Create An Experiment
A/B testing lets you compare two routing strategies — or two configurations of the same strategy — on a live split of traffic, with built-in guardrails and statistical significance checks. There is no separate create/manage API: an experiment is just another `algorithm.type` on the existing [`/routing/create`](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-create) endpoint, alongside `single`, `priority`, `volume_split`, and `advanced`.
## Why run one
Any routing change — turning on multi-objective routing, enabling autopilot, retuning hedging — is a bet that the new behaviour beats what you have today. The honest way to settle that bet is to run both on the *same* live traffic at the same time and measure the difference, rather than flip the change globally and hope the week-over-week numbers move for the right reason. That's what an experiment does: it holds one arm (**control**) on your current behaviour and sends a minority slice to the other (**variant**), so the two are compared under identical market conditions.
The design has two safety properties built in:
* **A guardrail.** If the variant's authorisation rate falls more than `guardrail_threshold_pp` percentage points below control, the experiment is flagged `GuardrailBreached` immediately — this is a deliberately eager point-estimate check, because no cost saving is worth an auth regression, and it trips without waiting for statistical significance (once past the minimum sample gate).
* **A significance test.** A winner is only declared when the difference is statistically real. Once each arm clears `min_sample_size`, results run a two-sample z-test on per-transaction economic value (which collapses to a plain two-proportion auth-rate test when no cost dimension is involved). Until then the verdict stays `CollectingData`; a positive-but-noisy gap stays `NotSignificant` rather than prematurely crowning the variant. Only a `p < 0.05` gap yields `VariantWins` / `VariantLoses`. See [A/B Testing: Results](/decision-engine-api-reference/api-reference/guides/ab-testing/ab-testing-results) for reading the verdict.
Because control and variant differ only in the routing behaviour you're testing, the measured delta is attributable to that change — which is exactly why you'd run an experiment before flipping a merchant-wide flag like [multi-objective routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective).
## algorithm.type = "ab\_test"
```bash theme={null}
curl --location "$BASE_URL/routing/create" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"name": "cost-vs-auth-test",
"description": "A/B test: 20% variant traffic",
"created_by": "merchant_demo",
"algorithm_for": "payment",
"metadata": {},
"algorithm": {
"type": "ab_test",
"data": {
"control_algorithm_id": "sr_routing",
"variant_algorithm_id": "sr_routing",
"variant_split_pct": 20,
"min_sample_size": 1000,
"guardrail_threshold_pp": 3.0,
"control_sr_config": { "enable_multi_objective": false, "use_autopilot": false },
"variant_sr_config": { "enable_multi_objective": true, "use_autopilot": false }
}
}
}'
```
Response is the standard routing-algorithm create response:
```json theme={null}
{
"rule_id": "routing_a1b2c3d4-1111-2222-3333-444455556666",
"name": "cost-vs-auth-test",
"created_at": "2026-07-16 10:00:00",
"modified_at": "2026-07-16 10:00:00"
}
```
## algorithm.data (ABTestData) Fields
| Field | Type | Meaning |
| - | - | - |
| `control_algorithm_id` | string | Algorithm the control arm uses. `"sr_routing"` for success-rate scoring, or the `rule_id` of an existing `single`/`priority`/`volume_split`/`advanced` algorithm. |
| `variant_algorithm_id` | string | Same, for the variant arm. |
| `variant_split_pct` | integer, 1–49 | Percentage of traffic sent to the variant arm. Capped below 50 so the variant is always the minority arm. |
| `min_sample_size` | integer | Transactions each arm needs before results are considered statistically meaningful. |
| `guardrail_threshold_pp` | number | Auto-pause guardrail: if the variant's auth rate drops this many percentage points below control, the experiment result is marked `GuardrailBreached`. |
| `control_sr_config` | object, optional | Per-arm SR override — see below. Only meaningful when the arm's algorithm is `sr_routing`. |
| `variant_sr_config` | object, optional | Same, for the variant arm. |
### SR Config Override
```json theme={null}
{
"hedging_percent": 5.0,
"elimination_threshold": 0.35,
"enable_multi_objective": true,
"margin": 0.2,
"use_autopilot": false
}
```
All fields are optional — set only the ones you want to override for that arm; anything omitted falls back to the merchant's live SR config. `enable_multi_objective` and `use_autopilot` are the same dials used by [multi-objective routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective) and [autopilot](/decision-engine-api-reference/api-reference/guides/autopilot/merchant-features), scoped to just this arm.
## Common Experiment Shapes
The dashboard's A/B test builder resolves its strategy dropdown into these four `sr_routing` + override combinations — useful presets when constructing the payload by hand:
| Arm preset | `variant_sr_config` |
| - | - |
| SR routing (auth based) | `{ "enable_multi_objective": false, "use_autopilot": false }` |
| SR routing (auth based, autopilot) | `{ "enable_multi_objective": false, "use_autopilot": true }` |
| SR routing (multi-objective, manual) | `{ "enable_multi_objective": true, "use_autopilot": false }` |
| SR routing (multi-objective, autopilot) | `{ "enable_multi_objective": true, "use_autopilot": true }` |
A `sr_config_tuning` experiment (compare two SR tunings rather than two strategies) uses `sr_routing` for both arms and only sets `hedging_percent`/`elimination_threshold` on the variant, leaving control on the live config.
## Activate The Experiment
Creating an experiment does not make it active — activate it like any other routing algorithm:
```bash theme={null}
curl --location "$BASE_URL/routing/activate" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"created_by": "merchant_demo",
"routing_algorithm_id": "routing_a1b2c3d4-1111-2222-3333-444455556666"
}'
```
## How Traffic Is Split
Arm assignment is deterministic per payment: `payment_id` is hashed and taken modulo 100 against `variant_split_pct`, so retries of the same payment always land in the same arm.
Two integration points use this assignment:
* **Real payments** — `/decide-gateway` / `/decision_gateway` route into the assigned arm. This only happens when the merchant feature `ab-test-real-payments` is enabled — see [Merchant Features](/decision-engine-api-reference/api-reference/guides/autopilot/merchant-features). Off by default so a newly created experiment doesn't affect live traffic until you opt in.
* **Simulation / Decision Explorer** — [`/routing/evaluate`](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-evaluate) previews what each arm would do for a given payment context, without a real transaction.
If an arm's algorithm id resolves to `sr_routing`, the payment proceeds through normal SR routing carrying that arm's `SrConfigOverride`. If it resolves to another algorithm's id, that algorithm's output is used directly and the response's `routing_approach` becomes `AB_TEST_STATIC_ALGORITHM`.
## Editing Or Removing An Experiment
Only an **inactive** experiment can be edited or deleted — see [Update & Delete Routing Algorithm](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-update-delete). Deactivate first with [`/routing/deactivate`](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-deactivate) if it's currently live.
## Related
* [A/B Testing: Results](/decision-engine-api-reference/api-reference/guides/ab-testing/ab-testing-results)
* [Merchant Features](/decision-engine-api-reference/api-reference/guides/autopilot/merchant-features) — enabling `ab-test-real-payments` and autopilot.
* [Multi-Objective Routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective)
* [Create Routing Algorithm](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-create)
# A/B Testing: Results
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/ab-testing/ab-testing-results
Curl examples for reading A/B test results, transaction logs, and enabling real-payment interception.
# A/B Testing: Results
Once an experiment (see [Create An Experiment](/decision-engine-api-reference/api-reference/guides/ab-testing/ab-testing-create)) is active and taking traffic, use these endpoints to monitor it. Both routes below live under `/analytics/` and require `$TENANT_HEADER` in addition to `$AUTH_HEADER` — see [Environment setup](/decision-engine-api-reference/api-reference/guides/api-ref#environment-setup).
## Experiment Results
Runs a statistical significance test (two-sample z-test on expected value, or plain auth-rate when the experiment is auth-only) between the control and variant arms.
```bash theme={null}
curl "$BASE_URL/analytics/experiment/routing_a1b2c3d4-1111-2222-3333-444455556666/results" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER"
```
Optional query parameters: `start_ms`, `end_ms`, `min_sample_size`, `guardrail_threshold_pp`, `evaluation_margin` — override the experiment's stored thresholds for an ad-hoc window or sensitivity check.
```json theme={null}
{
"experiment_id": "routing_a1b2c3d4-1111-2222-3333-444455556666",
"merchant_id": "merchant_demo",
"control": {
"arm": "control",
"transaction_count": 4820,
"success_count": 4531,
"failure_count": 289,
"auth_rate": 0.94,
"first_attempt_auth_rate": 0.91,
"total_cost_saved": null,
"avg_latency_ms": 6.2,
"avg_chosen_cost_bps": 182.4,
"avg_cost_saved_bps": null,
"net_ev_bps": 17660.0
},
"variant": {
"arm": "variant",
"transaction_count": 1204,
"success_count": 1101,
"failure_count": 103,
"auth_rate": 0.914,
"first_attempt_auth_rate": 0.887,
"total_cost_saved": 962.3,
"avg_latency_ms": 6.5,
"avg_chosen_cost_bps": 150.1,
"avg_cost_saved_bps": 32.3,
"net_ev_bps": 17944.0
},
"delta_pp": -2.6,
"p_value": 0.031,
"confidence_interval": [-4.9, -0.3],
"verdict": "variant_wins",
"min_sample_size": 1000,
"net_delta_bps": 284.0,
"evaluation_margin": 0.2
}
```
### Verdict Values
| Verdict | Meaning |
| - | - |
| `collecting_data` | At least one arm hasn't reached `min_sample_size` yet. |
| `not_significant` | Enough data, but the difference isn't statistically significant. |
| `variant_wins` | Variant significantly outperforms control on net expected value. |
| `variant_loses` | Variant significantly underperforms control. |
| `guardrail_breached` | Variant's auth rate dropped more than `guardrail_threshold_pp` below control — short-circuits before significance is even computed. |
For an auth-only experiment (no cost data / multi-objective involved on either arm), the significance test collapses to a pure auth-rate z-test and cost-related fields (`total_cost_saved`, `avg_cost_saved_bps`, `net_ev_bps`, `net_delta_bps`) are `null`.
## Experiment Transactions
Paginated per-transaction log — which arm each payment landed in and its outcome. Useful for spot-checking arm assignment or debugging a specific payment.
```bash theme={null}
curl "$BASE_URL/analytics/experiment/routing_a1b2c3d4-1111-2222-3333-444455556666/transactions?page=1&page_size=20" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER"
```
```json theme={null}
{
"experiment_id": "routing_a1b2c3d4-1111-2222-3333-444455556666",
"total": 6024,
"transactions": [
{
"payment_id": "pay_9f21",
"variant_arm": "variant",
"gateway": "adyen",
"status": "success",
"created_at_ms": 1784271600000
}
]
}
```
`page_size` is capped at 100. Optional `start_ms` narrows to a time window.
## Enabling Real-Payment Interception
A newly created experiment does not affect live traffic until real-payment interception is turned on for the merchant:
```bash theme={null}
curl --location "$BASE_URL/merchant-account/merchant_demo/features/ab-test-real-payments" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{ "enabled": true }'
```
See [Merchant Features](/decision-engine-api-reference/api-reference/guides/autopilot/merchant-features) for the full feature-flag reference. Until this is enabled, `/routing/evaluate` still previews both arms for simulation purposes even though `/decide-gateway` traffic is unaffected.
## Related
* [A/B Testing: Create An Experiment](/decision-engine-api-reference/api-reference/guides/ab-testing/ab-testing-create)
* [Merchant Features](/decision-engine-api-reference/api-reference/guides/autopilot/merchant-features)
* [Analytics Endpoints](/decision-engine-api-reference/api-reference/guides/analytics-audit/analytics-endpoints)
# Analytics Endpoints
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/analytics-audit/analytics-endpoints
Curl examples for ClickHouse-backed analytics, charts, payment audit, and decision trace.
# Analytics Endpoints
Analytics routes derive the merchant from the authenticated user/API key context and read from the analytics store. Use these endpoints for dashboard charts, payment audit, rule/volume decision inspection, and debit-routing audit.
Every route on this page also requires `x-tenant-id` (`$TENANT_HEADER` — see [Environment setup](/decision-engine-api-reference/api-reference/guides/api-ref#environment-setup)) in addition to `$AUTH_HEADER`. It has no fallback: omitting it fails with `TE_03: x-tenant-id not found in headers` even with a valid API key or JWT. This is the one header group most other Decision Engine routes (`/decide-gateway`, `/routing/*`, `/merchant-account/*`, etc.) don't need.
Common query parameters:
| Parameter | Values |
| - | - |
| `range` | `15m`, `1h`, `12h`, `1d`, `1w` |
| `start_ms`, `end_ms` | custom epoch-millisecond window |
| `page`, `page_size` | paginated list endpoints |
| `gateway`, `status`, `route`, `flow_type`, `routing_approach`, `exclude_routing_approach` | filters |
| `payment_id` | exact payment lookup for audit and trace views |
| `error_code` | failure filtering |
## Overview
High-level dashboard summary for the selected merchant and time window.
```bash theme={null}
curl "$BASE_URL/analytics/overview?range=1d" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER"
```
```json theme={null}
{
"request_count": 42,
"top_gateway": "adyen",
"gateway_share": [
{ "gateway": "adyen", "count": 22, "share": 52.4 }
]
}
```
## Gateway Scores
Auth-rate score snapshots and connector success-rate trend.
```bash theme={null}
curl "$BASE_URL/analytics/gateway-scores?range=1d&gateway=stripe,adyen" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER"
```
```json theme={null}
{
"latest": [
{ "gateway": "adyen", "score": 0.831 },
{ "gateway": "stripe", "score": 0.829 }
],
"series": [
{ "timestamp_ms": 1777136400000, "gateway": "adyen", "score": 0.831 }
]
}
```
## Decisions
Decision volume by connector and routing approach.
```bash theme={null}
curl "$BASE_URL/analytics/decisions?range=1d" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER"
```
```bash theme={null}
curl "$BASE_URL/analytics/decisions?range=1d&exclude_routing_approach=NTW_BASED_ROUTING" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER"
```
## Routing Stats
Connector share, rule hits, routing filter options, and chart data.
```bash theme={null}
curl "$BASE_URL/analytics/routing-stats?range=1d&payment_method_type=CARD" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER"
```
## Log Summaries
Failure aggregates and recent error samples.
```bash theme={null}
curl "$BASE_URL/analytics/log-summaries?range=1d&status=failure" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER"
```
## Payment Audit
Payment-level trail search. Prefer `payment_id` for exact lookup.
```bash theme={null}
curl "$BASE_URL/analytics/payment-audit?range=1d&page=1&page_size=12&payment_id=pay_001" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER"
```
```bash theme={null}
curl "$BASE_URL/analytics/payment-audit?range=1d&gateway=stripe&status=success&page=1&page_size=10" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER"
```
```json theme={null}
{
"summary": {
"matching_payments": 1,
"failures": 0,
"active_gateways": ["stripe"]
},
"payments": [
{
"payment_id": "pay_001",
"latest_status": "success",
"gateways": ["stripe"]
}
],
"timeline": [
{
"route": "decide_gateway",
"event_stage": "gateway_decided",
"gateway": "stripe",
"status": "success"
}
]
}
```
## Preview Trace
Rule/volume decisions captured from `/routing/evaluate`. The transport route remains `/analytics/preview-trace` even when the UI labels these as decisions.
```bash theme={null}
curl "$BASE_URL/analytics/preview-trace?range=1d&page=1&page_size=12&route=routing_evaluate" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER"
```
```bash theme={null}
curl "$BASE_URL/analytics/preview-trace?range=1d&payment_id=volume_decision_001" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER"
```
## Debit Routing Audit
```bash theme={null}
curl "$BASE_URL/analytics/payment-audit?range=1d&routing_approach=NTW_BASED_ROUTING" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER"
```
## Cost Savings
Rollup of savings attributed to [multi-objective routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective) — how much cheaper the chosen gateway was versus the plain SR head, trended over the window.
```bash theme={null}
curl "$BASE_URL/analytics/cost-savings?range=1w¤cy=USD" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER"
```
```json theme={null}
{
"merchant_id": "merchant_demo",
"range": "1w",
"currency": "USD",
"available_currencies": [
{ "currency": "USD", "decision_count": 4820 },
{ "currency": "EUR", "decision_count": 612 }
],
"trend": [
{ "bucket_ms": 1784112000000, "saved_value": 128.42 }
],
"totals": {
"saved_value": 962.3,
"cost_won_count": 341,
"total_decisions": 4820
}
}
```
`currency` is optional — omit it to aggregate across all currencies present in the window.
## Routing Events
Historical feed of routing-relevant state changes — SR leader changes, gateways entering/exiting the multi-objective auth band, and autopilot calibration runs. Powers the dashboard's routing timeline and the simulation UI's "Autopilot Actions" panel.
```bash theme={null}
curl "$BASE_URL/analytics/routing-events?range=1d&payment_method_type=CARD" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER"
```
```json theme={null}
{
"merchant_id": "merchant_demo",
"range": "1d",
"generated_at_ms": 1784271600000,
"events": [
{
"id": "evt_a1b2c3",
"event_type": "leader_changed",
"merchant_id": "merchant_demo",
"payment_method_type": "CARD",
"payment_method": "CREDIT",
"bucket_ms": 1784268000000,
"gateway": "adyen",
"previous_gateway": "stripe",
"score": 0.91,
"previous_score": 0.885,
"transaction_count": 214
}
]
}
```
`event_type` is one of `leader_changed`, `gateway_entered_auth_band`, `gateway_exited_auth_band`, or `calibration_applied` (an autopilot re-tune — see [Merchant Features](/decision-engine-api-reference/api-reference/guides/autopilot/merchant-features)). Auth-band events only fire when multi-objective routing is enabled for the merchant. Additional filters: `min_transaction_count`, `min_score_delta`, `tolerance_pp` (auth-band width override), `limit`.
## A/B Test Experiment Results
Statistical significance results and the per-transaction log for a routing A/B test. Full reference, including the verdict enum and guardrail behavior: [A/B Testing: Results](/decision-engine-api-reference/api-reference/guides/ab-testing/ab-testing-results).
```bash theme={null}
curl "$BASE_URL/analytics/experiment/routing_a1b2c3d4-1111-2222-3333-444455556666/results" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER"
```
```bash theme={null}
curl "$BASE_URL/analytics/experiment/routing_a1b2c3d4-1111-2222-3333-444455556666/transactions?page=1&page_size=20" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER"
```
## Notes
* Use `range` for preset windows and `start_ms`/`end_ms` for custom windows.
* Use `page` and `page_size` on list-heavy views such as payment audit and preview trace.
* Use `exclude_routing_approach=NTW_BASED_ROUTING` when auth-rate audit should hide debit-routing decisions.
* Freshly inserted analytics events may take a short moment to appear because writes are asynchronous.
# API Keys
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/auth-onboarding/api-keys
Curl examples for creating, listing, and revoking Decision Engine API keys.
# API Keys
API keys are intended for service-to-service traffic. Use the returned `api_key` value as `x-api-key` for protected endpoints.
## Create API Key
```bash theme={null}
curl --location "$BASE_URL/api-key/create" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchant_id": "merchant_demo",
"description": "backend integration key"
}'
```
```json theme={null}
{
"key_id": "018f...",
"api_key": "DE_...",
"key_prefix": "DE_abcd",
"merchant_id": "merchant_demo",
"description": "backend integration key",
"created_at": "2026-04-25 10:00:00"
}
```
## List API Keys
```bash theme={null}
curl "$BASE_URL/api-key/list/merchant_demo" \
--header "$AUTH_HEADER"
```
## Revoke API Key
```bash theme={null}
curl --request DELETE "$BASE_URL/api-key/018f-key-id" \
--header "$AUTH_HEADER"
```
# Auth And Onboarding
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/auth-onboarding/auth-and-onboarding
Curl examples for dashboard auth, merchant selection, and merchant onboarding.
# Auth And Onboarding
## Sign Up
```bash theme={null}
curl --location "$BASE_URL/auth/signup" \
--header "Content-Type: application/json" \
--data '{
"email": "operator@example.com",
"password": "StrongPass#123",
"merchant_id": "merchant_demo"
}'
```
## Login
```bash theme={null}
curl --location "$BASE_URL/auth/login" \
--header "Content-Type: application/json" \
--data '{
"email": "operator@example.com",
"password": "StrongPass#123"
}'
```
Response contains a dashboard JWT:
```json theme={null}
{
"token": "eyJ...",
"user_id": "user_123",
"email": "operator@example.com",
"merchant_id": "merchant_demo",
"role": "admin",
"merchants": []
}
```
## Current User
```bash theme={null}
curl "$BASE_URL/auth/me" \
--header "$AUTH_HEADER"
```
## List User Merchants
```bash theme={null}
curl "$BASE_URL/auth/merchants" \
--header "$AUTH_HEADER"
```
## Switch Merchant
```bash theme={null}
curl --location "$BASE_URL/auth/switch-merchant" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{ "merchant_id": "merchant_demo" }'
```
## Create Merchant From Dashboard
```bash theme={null}
curl --location "$BASE_URL/onboarding/merchant" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{ "merchant_name": "Demo Merchant" }'
```
## Logout
```bash theme={null}
curl --location "$BASE_URL/auth/logout" \
--header "$AUTH_HEADER" \
--request POST
```
## Verify Email
Public route — the link sent by the signup email-verification flow calls this with the token from the email.
```bash theme={null}
curl "$BASE_URL/auth/verify-email?token=vf_9f21a6c0..."
```
```json theme={null}
{ "message": "Email verified successfully." }
```
## Change Password
```bash theme={null}
curl --location "$BASE_URL/auth/change-password" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"current_password": "StrongPass#123",
"new_password": "EvenStrongerPass#456"
}'
```
```json theme={null}
{ "message": "Password updated successfully." }
```
## Team Management
Invite and manage members on the authenticated merchant account. Inviting requires the caller's JWT to carry the `admin` role.
### List Members
```bash theme={null}
curl "$BASE_URL/merchant/members" \
--header "$AUTH_HEADER"
```
```json theme={null}
[
{ "user_id": "user_123", "email": "operator@example.com", "role": "admin" },
{ "user_id": "user_456", "email": "teammate@example.com", "role": "member" }
]
```
### Invite A Member
```bash theme={null}
curl --location "$BASE_URL/merchant/members/invite" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{ "email": "teammate@example.com", "role": "member" }'
```
`role` is optional and defaults to `"member"`; the only other accepted value is `"admin"`.
```json theme={null}
{
"email": "teammate@example.com",
"is_new_user": true,
"password": "TempPass#8821",
"role": "member"
}
```
`password` is only present when the invite creates a brand-new user account — share it out of band so they can log in and change it. Inviting an email that's already a user omits `password` and just adds the membership.
# Merchant Features: Autopilot & Feature Flags
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/autopilot/merchant-features
Curl examples for reading and toggling merchant-level feature flags — including Autopilot and SR Auto-Calibration — and resetting gateway scores.
# Merchant Features: Autopilot & Feature Flags
Every merchant-level toggle — multi-objective routing, A/B test real-payment interception, elimination, and the two self-tuning features (Autopilot and SR Auto-Calibration) — is read and set through one small feature-flag API.
## List Feature Flags
```bash theme={null}
curl "$BASE_URL/merchant-account/merchant_demo/features" \
--header "$AUTH_HEADER"
```
```json theme={null}
{
"merchant_id": "merchant_demo",
"features": [
{ "feature": "gsm-scoring-filter", "enabled": false },
{ "feature": "explore-exploit-srv3", "enabled": false },
{ "feature": "ab-test-real-payments", "enabled": true },
{ "feature": "multi-objective-routing", "enabled": true },
{ "feature": "elimination", "enabled": true },
{ "feature": "auto-calibration", "enabled": true },
{ "feature": "autopilot", "enabled": true }
]
}
```
## Toggle A Feature
```bash theme={null}
curl --location "$BASE_URL/merchant-account/merchant_demo/features/autopilot" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{ "enabled": true }'
```
Response is the same shape as the list call, re-read after the change so you always see the current effective state of every flag.
## Known Features
| Slug | What it controls |
| - | - |
| `gsm-scoring-filter` | Filters gateway scoring using Gateway Status Mapper error-code classification. |
| `explore-exploit-srv3` | Explore/exploit hedging on the SRv3 scoring path. |
| `ab-test-real-payments` | Whether active A/B test experiments intercept real `/decide-gateway` traffic — see [A/B Testing: Results](/decision-engine-api-reference/api-reference/guides/ab-testing/ab-testing-results). |
| `multi-objective-routing` | Merchant-wide default for the cost-aware post-step — see [Multi-Objective Routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective). Per-request `enableMultiObjective` overrides this. |
| `elimination` | Gateway-level SR-based elimination (excluding gateways in downtime). |
| `auto-calibration` | Enables the self-tuning background job (see below). Must be on **together with** `autopilot` for the job to actually write changes. |
| `autopilot` | Master write-permission switch for the self-tuning job. With `auto-calibration` off, this alone does nothing. |
## What Autopilot & Auto-Calibration Do
The success-rate scorer has two knobs — **bucket size** (how many recent transactions each gateway's score is averaged over) and **hedging %** (how much traffic is explored away from the current leader). The right values depend on how much traffic a merchant sees and how many gateways it spreads across, and the ideal settings drift as that traffic changes through the day. Tuning them by hand is tedious and quickly goes stale.
**Autopilot is the self-tuning layer that sets those two knobs for you, continuously, from observed traffic.** Instead of a fixed configuration, it watches each merchant's real volume and gateway spread and re-derives the bucket size and hedging % that keep scoring both responsive (fast to notice a gateway degrading) and stable (not thrashing on noise). "Auto-Calibration" is the background job that does the deriving; "Autopilot" is the switch that lets it actually write its results back. The two are split so you can enrol a merchant for observation without granting write access until you're ready.
These two flags jointly control a background job — there is no separate "run autopilot" endpoint. `auto-calibration` gates whether the job considers a merchant at all; `autopilot` gates whether it's allowed to write. Both must be enabled for self-tuning to take effect.
Every polling interval (default 900s, configurable via `[sr_auto_calibration]` in `config/*.toml` or `SR_AUTO_CALIBRATION_INTERVAL_SECS`), the job:
1. Reads recent traffic volume from ClickHouse (default 3600s lookback).
2. Derives two SRv3 knobs purely from observed data — no merchant input:
* **Bucket size** — clamped between 100 and 2000, only rewritten on a meaningful (25-step) change.
* **Hedging %** — capped at 30%, with a 1.0pp minimum move before it updates.
3. Writes the result back into the merchant's SR config (readable via [`GET /config/routing-keys`](/decision-engine-api-reference/api-reference/guides/scoring-config/config-endpoints) and [`GET /config-sr-dimension/:merchant_id`](/decision-engine-api-reference/api-reference/guides/scoring-config/config-endpoints#get-sr-dimensions)), stamped with `"source": "autopilot"` so autopilot-written values are distinguishable from human-authored overrides.
Every calibration run also emits an analytics event (`flow_type: autopilot_calibration`) — this is what powers the "Autopilot Actions" panel in the simulation UI, and is queryable via [Routing Events](/decision-engine-api-reference/api-reference/guides/analytics-audit/analytics-endpoints#routing-events).
## Reset Gateway Scores
Flushes all SR v2/v3 score and queue keys for a merchant from Redis, and strips any autopilot-written (`source: "autopilot"`) sub-level config overrides — human-authored overrides are preserved. Used by the simulator's "Hard refresh" so a new simulation run starts from a clean slate.
Unlike the feature-flag calls above, this route requires `$TENANT_HEADER` in addition to `$AUTH_HEADER` — see [Environment setup](/decision-engine-api-reference/api-reference/guides/api-ref#environment-setup).
```bash theme={null}
curl --location "$BASE_URL/gateway-score/reset" \
--header "$AUTH_HEADER" \
--header "$TENANT_HEADER" \
--header "Content-Type: application/json" \
--data '{ "merchant_id": "merchant_demo" }'
```
```json theme={null}
{
"merchant_id": "merchant_demo",
"deleted_keys": 214,
"removed_overrides": 3
}
```
This does not disable routing or delete configuration — it only clears live scoring state so the next decisions start from a fresh baseline.
## Related
* [A/B Testing: Create An Experiment](/decision-engine-api-reference/api-reference/guides/ab-testing/ab-testing-create)
* [Multi-Objective Routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective)
* [Routing Config Endpoints](/decision-engine-api-reference/api-reference/guides/scoring-config/config-endpoints)
* [Analytics Endpoints](/decision-engine-api-reference/api-reference/guides/analytics-audit/analytics-endpoints)
# Advanced Routing Example
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/configure-routing/routing-advanced-example
Advanced Euclid rule tree examples for /routing/create, including AND, OR, nested rules, and value variants.
# Advanced Routing Example
Use `algorithm.type = advanced` when a merchant needs conditional rule-based routing instead of a fixed connector order. Advanced rules evaluate payment attributes, choose the first matching rule output, and fall back to `default_selection` when no rule matches.
## Advanced Program Shape
```json theme={null}
{
"globals": {},
"default_selection": {
"priority": [
{ "gateway_name": "stripe", "gateway_id": "mca_stripe" }
]
},
"rules": [],
"metadata": {}
}
```
| Field | Meaning |
| - | - |
| `globals` | Optional reusable value sets referenced by `global_ref`. |
| `default_selection` | Fallback `single`, `priority`, `volume_split`, or `volume_split_priority` output. |
| `rules[].routing_type` | Rule output behavior: `priority`, `volume_split`, or `volume_split_priority`. |
| `rules[].output` | Connector output returned when the rule matches. |
| `rules[].statements[].condition` | Conditions inside one statement. All conditions in the same array must match. |
| `rules[].statements[].nested` | Optional nested statements. Parent condition must match and then nested statements are evaluated. |
## Full Create Request
```bash theme={null}
curl --location "$BASE_URL/routing/create" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"name": "advanced card routing",
"created_by": "merchant_demo",
"description": "Route Visa card traffic by priority, otherwise fallback to stripe",
"algorithm_for": "payment",
"algorithm": {
"type": "advanced",
"data": {
"globals": {},
"default_selection": {
"priority": [
{ "gateway_name": "stripe", "gateway_id": "mca_stripe" }
]
},
"rules": [
{
"name": "visa_card_rule",
"routing_type": "priority",
"output": {
"priority": [
{ "gateway_name": "adyen", "gateway_id": "mca_adyen" },
{ "gateway_name": "stripe", "gateway_id": "mca_stripe" }
]
},
"statements": [
{
"condition": [
{
"lhs": "payment_method_type",
"comparison": "equal",
"value": { "type": "enum_variant", "value": "CARD" },
"metadata": {}
},
{
"lhs": "card_network",
"comparison": "equal",
"value": { "type": "enum_variant", "value": "Visa" },
"metadata": {}
}
],
"nested": null
}
]
}
],
"metadata": {}
}
}
}'
```
## Logic Variants
### AND Rule
Use one `condition` array when all conditions must match.
```json theme={null}
{
"name": "high_value_netherlands_rule",
"routing_type": "volume_split",
"output": {
"volume_split": [
{
"split": 60,
"output": { "gateway_name": "hdfc", "gateway_id": "mca_hdfc" }
},
{
"split": 40,
"output": { "gateway_name": "instamojo", "gateway_id": "mca_instamojo" }
}
]
},
"statements": [
{
"condition": [
{
"lhs": "amount",
"comparison": "greater_than",
"value": { "type": "number", "value": 100 },
"metadata": {}
},
{
"lhs": "billing_country",
"comparison": "equal",
"value": { "type": "enum_variant", "value": "Netherlands" },
"metadata": {}
}
],
"nested": null
}
]
}
```
### OR Rule
Use multiple statements when any statement can trigger the rule.
```json theme={null}
{
"name": "card_or_high_value_rule",
"routing_type": "priority",
"output": {
"priority": [
{ "gateway_name": "paytm", "gateway_id": "mca_paytm" },
{ "gateway_name": "adyen", "gateway_id": "mca_adyen" }
]
},
"statements": [
{
"condition": [
{
"lhs": "payment_method_type",
"comparison": "equal",
"value": { "type": "enum_variant", "value": "CARD" },
"metadata": {}
}
],
"nested": null
},
{
"condition": [
{
"lhs": "amount",
"comparison": "greater_than",
"value": { "type": "number", "value": 100 },
"metadata": {}
}
],
"nested": null
}
]
}
```
### Nested AND + OR Rule
Use `nested` when a parent condition must match and then one nested branch can match.
```json theme={null}
{
"name": "amount_and_card_network_or_country_rule",
"routing_type": "priority",
"output": {
"priority": [
{ "gateway_name": "rbl", "gateway_id": "mca_rbl" },
{ "gateway_name": "instamojo", "gateway_id": "mca_instamojo" }
]
},
"statements": [
{
"condition": [
{
"lhs": "amount",
"comparison": "greater_than",
"value": { "type": "number", "value": 10 },
"metadata": {}
}
],
"nested": [
{
"condition": [
{
"lhs": "card_network",
"comparison": "equal",
"value": { "type": "enum_variant", "value": "Visa" },
"metadata": {}
}
],
"nested": null
},
{
"condition": [
{
"lhs": "billing_country",
"comparison": "equal",
"value": { "type": "enum_variant", "value": "India" },
"metadata": {}
}
],
"nested": null
}
]
}
]
}
```
## Output Variants
### Priority Output
```json theme={null}
{
"routing_type": "priority",
"output": {
"priority": [
{ "gateway_name": "adyen", "gateway_id": "mca_adyen" },
{ "gateway_name": "stripe", "gateway_id": "mca_stripe" }
]
}
}
```
### Volume Split Output
```json theme={null}
{
"routing_type": "volume_split",
"output": {
"volume_split": [
{
"split": 70,
"output": { "gateway_name": "stripe", "gateway_id": "mca_stripe" }
},
{
"split": 30,
"output": { "gateway_name": "adyen", "gateway_id": "mca_adyen" }
}
]
}
}
```
### Volume Split Priority Output
Use `volume_split_priority` when each split should return a priority list rather than a single connector.
```json theme={null}
{
"routing_type": "volume_split_priority",
"output": {
"volume_split_priority": [
{
"split": 60,
"output": [
{ "gateway_name": "stripe", "gateway_id": "mca_stripe" },
{ "gateway_name": "adyen", "gateway_id": "mca_adyen" }
]
},
{
"split": 40,
"output": [
{ "gateway_name": "checkout", "gateway_id": "mca_checkout" },
{ "gateway_name": "stripe", "gateway_id": "mca_stripe" }
]
}
]
}
}
```
## Value Variants
### Enum Variant Array
```json theme={null}
{
"lhs": "card_network",
"comparison": "equal",
"value": {
"type": "enum_variant_array",
"value": ["Visa", "Mastercard"]
},
"metadata": {}
}
```
### Number Array
```json theme={null}
{
"lhs": "amount",
"comparison": "equal",
"value": {
"type": "number_array",
"value": [1000, 2000, 5000]
},
"metadata": {}
}
```
### Number Comparison Array
```json theme={null}
{
"lhs": "amount",
"comparison": "equal",
"value": {
"type": "number_comparison_array",
"value": [
{ "comparison_type": "greater_than", "number": 1000 },
{ "comparison_type": "less_than_equal", "number": 5000 }
]
},
"metadata": {}
}
```
## Notes
* Advanced algorithms require `statements`; top-level `single`, `priority`, and `volume_split` algorithms do not.
* Conditions in the same `condition` array behave like AND.
* Multiple statements behave like OR.
* `nested` allows a parent condition plus nested branch matching.
* `volume_split` percentages should add up to 100.
## Related
* [Create Routing Algorithm](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-create)
* [Evaluate Routing Algorithm](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-evaluate)
* [Priority Routing](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-priority-example)
* [Volume Split Routing](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-volume-split-example)
# Activate Routing Algorithm
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-activate
Curl example for activating a routing algorithm.
# Activate Routing Algorithm
At a given time, one algorithm for each `algorithm_for` value can be active for one merchant.
## Request
```bash theme={null}
curl --location "$BASE_URL/routing/activate" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"created_by": "merchant_demo",
"routing_algorithm_id": "routing_e641380c-6f24-4405-8454-5ae6cbceb7a0"
}'
```
## Response
Success returns HTTP `200` with an empty response body.
## Related
* [Deactivate Routing Algorithm](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-deactivate)
* [List Active Routing Algorithms](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-list-active)
# Create Routing Algorithm
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-create
Curl examples for /routing/create.
# Create Routing Algorithm
Use `/routing/create` to persist a merchant-scoped routing algorithm. Creating an algorithm does not make it active; call [`/routing/activate`](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-activate) after creation.
Supported `algorithm.type` values:
| Type | Use case | Full example |
| - | - | - |
| `single` | Always return one connector. | [Single connector](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-single-connector-example) |
| `priority` | Return connectors in the configured order. | [Priority routing](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-priority-example) |
| `volume_split` | Split decisions by percentage. | [Volume split](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-volume-split-example) |
| `advanced` | Evaluate AND/OR/nested conditions before returning an output. | [Advanced routing](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-advanced-example) |
| `ab_test` | Split traffic between a control and variant strategy with guardrails and significance testing. | [A/B testing](/decision-engine-api-reference/api-reference/guides/ab-testing/ab-testing-create) |
Use [`/routing/deactivate`](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-deactivate) to deactivate the currently active algorithm without deleting it, and [update or delete](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-update-delete) an inactive algorithm in place.
## Priority Rule
```bash theme={null}
curl --location "$BASE_URL/routing/create" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"name": "priority rule",
"created_by": "merchant_demo",
"description": "try stripe before adyen",
"algorithm_for": "payment",
"algorithm": {
"type": "priority",
"data": [
{ "gateway_name": "stripe", "gateway_id": "mca_111" },
{ "gateway_name": "adyen", "gateway_id": "mca_112" }
]
}
}'
```
## Single Connector Rule
```bash theme={null}
curl --location "$BASE_URL/routing/create" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"name": "single connector rule",
"created_by": "merchant_demo",
"description": "always route to stripe",
"algorithm_for": "payment",
"algorithm": {
"type": "single",
"data": { "gateway_name": "stripe", "gateway_id": "mca_111" }
}
}'
```
## Volume Split Rule
```bash theme={null}
curl --location "$BASE_URL/routing/create" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"name": "volume split rule",
"created_by": "merchant_demo",
"description": "split traffic between stripe and adyen",
"algorithm_for": "payment",
"algorithm": {
"type": "volume_split",
"data": [
{
"split": 70,
"output": { "gateway_name": "stripe", "gateway_id": "mca_111" }
},
{
"split": 30,
"output": { "gateway_name": "adyen", "gateway_id": "mca_112" }
}
]
}
}'
```
## Advanced Rule
Use `advanced` for conditional routing. The complete AND/OR/nested reference is in [Advanced Routing Example](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-advanced-example).
```bash theme={null}
curl --location "$BASE_URL/routing/create" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"name": "advanced card rule",
"created_by": "merchant_demo",
"description": "route Visa cards to adyen first",
"algorithm_for": "payment",
"algorithm": {
"type": "advanced",
"data": {
"globals": {},
"default_selection": {
"priority": [{ "gateway_name": "stripe", "gateway_id": "mca_111" }]
},
"rules": [
{
"name": "visa_card_rule",
"routing_type": "priority",
"output": {
"priority": [
{ "gateway_name": "adyen", "gateway_id": "mca_112" },
{ "gateway_name": "stripe", "gateway_id": "mca_111" }
]
},
"statements": [
{
"condition": [
{
"lhs": "card_network",
"comparison": "equal",
"value": { "type": "enum_variant", "value": "Visa" },
"metadata": {}
}
],
"nested": null
}
]
}
],
"metadata": {}
}
}
}'
```
## Response
```json theme={null}
{
"rule_id": "routing_e641380c-6f24-4405-8454-5ae6cbceb7a0",
"name": "priority rule",
"created_at": "2026-04-25 11:45:03",
"modified_at": "2026-04-25 11:45:03"
}
```
## Related
* [Activate Routing Algorithm](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-activate)
* [Update & Delete Routing Algorithm](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-update-delete)
* [List Routing Algorithms](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-list)
* [Evaluate Routing Algorithm](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-evaluate)
* [Advanced Routing Example](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-advanced-example)
* [A/B Testing: Create An Experiment](/decision-engine-api-reference/api-reference/guides/ab-testing/ab-testing-create)
# Deactivate Routing Algorithm
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-deactivate
Curl example for deactivating a routing algorithm.
# Deactivate Routing Algorithm
Use `/routing/deactivate` to remove the active mapping for a merchant-scoped routing algorithm without deleting the algorithm itself.
## Request
```bash theme={null}
curl --location "$BASE_URL/routing/deactivate" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"created_by": "merchant_demo",
"routing_algorithm_id": "routing_e641380c-6f24-4405-8454-5ae6cbceb7a0"
}'
```
## Response
Success returns HTTP `200` with an empty response body.
## Behavior
* If the routing algorithm exists and is active for the merchant, the active mapping is deleted.
* If the routing algorithm exists but is already inactive, the request still succeeds.
* If the routing algorithm ID does not exist, the request fails with `400`.
## Related
* [Create Routing Algorithm](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-create)
* [Activate Routing Algorithm](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-activate)
* [List Active Routing Algorithms](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-list-active)
# Evaluate Routing Algorithm
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-evaluate
Curl example for /routing/evaluate.
# Evaluate Routing Algorithm
`/routing/evaluate` evaluates the active routing algorithm for a payment context. It does not update SR scores.
## Request
```bash theme={null}
curl --location "$BASE_URL/routing/evaluate" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchantId": "merchant_demo",
"paymentInfo": {
"paymentId": "eval_001",
"amount": 1000,
"currency": "USD",
"paymentType": "ORDER_PAYMENT",
"paymentMethodType": "CARD",
"paymentMethod": "CREDIT",
"authType": "THREE_DS"
}
}'
```
## Response
```json theme={null}
{
"priority": [
{ "gateway_name": "stripe", "gateway_id": "mca_111" },
{ "gateway_name": "adyen", "gateway_id": "mca_112" }
]
}
```
# List Routing Algorithms
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-list
Curl example for listing routing algorithms.
# List Routing Algorithms
## Request
```bash theme={null}
curl --request POST "$BASE_URL/routing/list/merchant_demo" \
--header "$AUTH_HEADER"
```
## Response
```json theme={null}
[
{
"rule_id": "routing_e641380c-6f24-4405-8454-5ae6cbceb7a0",
"name": "priority rule",
"algorithm_for": "payment"
}
]
```
# List Active Routing Algorithms
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-list-active
Curl example for listing active routing algorithms.
# List Active Routing Algorithms
## Request
```bash theme={null}
curl --location --request POST "$BASE_URL/routing/list/active/merchant_demo" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json"
```
## Response
```json theme={null}
[
{
"rule_id": "routing_e641380c-6f24-4405-8454-5ae6cbceb7a0",
"name": "priority rule",
"algorithm_for": "payment"
}
]
```
# Update & Delete Routing Algorithm
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-update-delete
Curl examples for /routing/update and /routing/delete.
# Update & Delete Routing Algorithm
Edit or remove a previously created routing algorithm — including [A/B test experiments](/decision-engine-api-reference/api-reference/guides/ab-testing/ab-testing-create), which are stored the same way. Both operations only work on an **inactive** algorithm; deactivate it first with [`/routing/deactivate`](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-deactivate) if it's currently live.
## Update
Rewrites the name, description, and algorithm definition in place — the `rule_id` doesn't change.
```bash theme={null}
curl --location "$BASE_URL/routing/update" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"created_by": "merchant_demo",
"routing_algorithm_id": "routing_e641380c-6f24-4405-8454-5ae6cbceb7a0",
"name": "priority rule (v2)",
"description": "try adyen before stripe",
"algorithm": {
"type": "priority",
"data": [
{ "gateway_name": "adyen", "gateway_id": "mca_112" },
{ "gateway_name": "stripe", "gateway_id": "mca_111" }
]
}
}'
```
`algorithm` accepts the same `type` values as [`/routing/create`](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-create) — `single`, `priority`, `volume_split`, `advanced`, or `ab_test`.
```json theme={null}
{
"id": "routing_e641380c-6f24-4405-8454-5ae6cbceb7a0",
"name": "priority rule (v2)",
"algorithm_for": "payment",
"created_at": "2026-07-01 09:12:04",
"modified_at": "2026-07-16 10:00:00"
}
```
Returns an error if the algorithm is currently active, or if `created_by` doesn't own the algorithm.
## Delete
```bash theme={null}
curl --location "$BASE_URL/routing/delete" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"created_by": "merchant_demo",
"routing_algorithm_id": "routing_e641380c-6f24-4405-8454-5ae6cbceb7a0"
}'
```
```json theme={null}
{
"status": "deleted",
"routing_algorithm_id": "routing_e641380c-6f24-4405-8454-5ae6cbceb7a0"
}
```
## Related
* [Create Routing Algorithm](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-create)
* [Activate Routing Algorithm](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-activate)
* [Deactivate Routing Algorithm](/decision-engine-api-reference/api-reference/guides/configure-routing/routing-algorithm-deactivate)
* [A/B Testing: Create An Experiment](/decision-engine-api-reference/api-reference/guides/ab-testing/ab-testing-create)
# Hybrid Routing Evaluation
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/configure-routing/routing-hybrid
Curl example for /routing/hybrid.
# Hybrid Routing Evaluation
`/routing/hybrid` evaluates the active rule path together with runtime routing context.
```bash theme={null}
curl --location "$BASE_URL/routing/hybrid" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchantId": "merchant_demo",
"paymentInfo": {
"paymentId": "hybrid_eval_001",
"amount": 1000,
"currency": "USD",
"paymentType": "ORDER_PAYMENT",
"paymentMethodType": "CARD",
"paymentMethod": "CREDIT"
},
"eligibleGatewayList": ["stripe", "adyen"]
}'
```
```json theme={null}
{
"priority": [
{ "gateway_name": "stripe", "gateway_id": "mca_111" },
{ "gateway_name": "adyen", "gateway_id": "mca_112" }
]
}
```
# Priority Routing Example
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/configure-routing/routing-priority-example
Priority-list routing create example.
# Priority Routing Example
```bash theme={null}
curl --location "$BASE_URL/routing/create" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"name": "priority rule",
"created_by": "merchant_demo",
"algorithm_for": "payment",
"algorithm": {
"type": "priority",
"data": [
{ "gateway_name": "stripe", "gateway_id": "mca_111" },
{ "gateway_name": "adyen", "gateway_id": "mca_112" },
{ "gateway_name": "checkout", "gateway_id": "mca_113" }
]
}
}'
```
# Single Connector Example
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/configure-routing/routing-single-connector-example
Single-connector routing create example.
# Single Connector Example
```bash theme={null}
curl --location "$BASE_URL/routing/create" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"name": "single connector rule",
"created_by": "merchant_demo",
"algorithm_for": "payment",
"algorithm": {
"type": "single",
"data": { "gateway_name": "stripe", "gateway_id": "mca_111" }
}
}'
```
# Volume Split Example
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/configure-routing/routing-volume-split-example
Volume-split routing create example.
# Volume Split Example
```bash theme={null}
curl --location "$BASE_URL/routing/create" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"name": "volume split rule",
"created_by": "merchant_demo",
"algorithm_for": "payment",
"algorithm": {
"type": "volume_split",
"data": [
{
"split": 70,
"output": { "gateway_name": "stripe", "gateway_id": "mca_111" }
},
{
"split": 30,
"output": { "gateway_name": "adyen", "gateway_id": "mca_112" }
}
]
}
}'
```
# Cost Ingestion: Fees & Coverage
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-fees
Curl examples for reading fitted connector fees, setting manual overrides, inspecting top cost clusters, and checking cost-model coverage.
# Cost Ingestion: Fees & Coverage
Once settlement data has been ingested (see [Connector Setup](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-setup) and [Uploads](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-uploads)), Decision Engine fits a per-cluster cost model — the input to [multi-objective routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective)'s expected-value ranking. These endpoints read that model and let you override it manually.
Overrides take priority in this order: **cluster override** → **connector override** → **learned model**.
## Connector Fees
Per-connector blended fee (volume-weighted over trustworthy clusters), any manual override, and which one is effective.
```bash theme={null}
curl "$BASE_URL/merchant-account/merchant_demo/connector-fees" \
--header "$AUTH_HEADER"
```
```json theme={null}
[
{
"connector": "adyen",
"account": "YOUR_ADYEN_MERCHANT_ACCOUNT_CODE",
"has_credentials": true,
"model_pct_bps": 182.4,
"model_fixed": 0.1,
"good_gross": 1284302.55,
"override_pct_bps": null,
"override_fixed": null,
"override_updated_at": null,
"effective_pct_bps": 182.4,
"effective_fixed": 0.1,
"source": "model"
}
]
```
`source` is `"override"`, `"model"`, or `"none"` (configured but no fitted data yet).
### Set A Connector Fee Override
Replaces the learned model for every expected-value calculation on this connector.
```bash theme={null}
curl --request PUT \
"$BASE_URL/merchant-account/merchant_demo/connectors/adyen/fee-override" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{ "pct_bps": 175.0, "fixed": 0.1 }'
```
### Delete A Connector Fee Override
```bash theme={null}
curl --request DELETE \
"$BASE_URL/merchant-account/merchant_demo/connectors/adyen/fee-override" \
--header "$AUTH_HEADER"
```
Both `pct_bps` and `fixed` must be finite and non-negative. Setting or clearing an override refreshes this merchant's served cost model immediately rather than waiting for the periodic refresh.
## Cost Clusters
The highest-traffic fitted clusters (by GMV) — the fine-grained segments underneath a connector's blended fee, and the target for surgical per-cluster overrides.
```bash theme={null}
curl "$BASE_URL/merchant-account/merchant_demo/cost-clusters?limit=10" \
--header "$AUTH_HEADER"
```
Narrow to one connector's latest snapshot, or one exact ingestion:
```bash theme={null}
curl "$BASE_URL/merchant-account/merchant_demo/cost-clusters?connector=adyen&account=YOUR_ADYEN_MERCHANT_ACCOUNT_CODE" \
--header "$AUTH_HEADER"
```
```json theme={null}
[
{
"key": "adyen|visa|credit|credit|us|usd|domestic",
"connector": "adyen",
"card_network": "visa",
"variant": "credit",
"funding": "credit",
"issuer_country": "us",
"currency": "usd",
"ic_category": "domestic",
"n": 18422,
"gross_sum": 512300.2,
"model_pct_bps": 178.2,
"model_fixed": 0.1,
"override_pct_bps": null,
"override_fixed": null,
"override_updated_at": null,
"effective_pct_bps": 178.2,
"effective_fixed": 0.1,
"source": "model"
}
]
```
`key` is the opaque `connector|network|variant|funding|issuer|currency|ic_category` identifier used for the override calls below. `limit` defaults to 10, capped at 50.
### Set A Cluster Fee Override
```bash theme={null}
curl --request PUT \
"$BASE_URL/merchant-account/merchant_demo/cost-clusters/adyen%7Cvisa%7Ccredit%7Ccredit%7Cus%7Cusd%7Cdomestic/fee-override" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{ "pct_bps": 165.0, "fixed": 0.1 }'
```
### Delete A Cluster Fee Override
```bash theme={null}
curl --request DELETE \
"$BASE_URL/merchant-account/merchant_demo/cost-clusters/adyen%7Cvisa%7Ccredit%7Ccredit%7Cus%7Cusd%7Cdomestic/fee-override" \
--header "$AUTH_HEADER"
```
The `|` separators in `key` must be URL-encoded (`%7C`) when used as a path segment.
## Cost Coverage
Cost-aware routing is only as good as the cost data behind it. A fitted model is trustworthy for some clusters and shaky for others, and routing decisions made on a shaky estimate can do more harm than good. **Cost coverage is the honesty check**: it tells you what fraction of a merchant's real volume actually has a cost model solid enough to route on, so you know whether to lean on multi-objective routing or hold off until more settlement data arrives.
Every fitted cluster is graded with one of three verdicts:
* **`GOOD`** — enough transactions (`n ≥ 200`) and a tight linear fit (per-transaction error `bps_rmse ≤ 15`). These are the clusters cost routing trusts.
* **`THIN`** — too little settlement volume to fit confidently yet. More data over time promotes these to `GOOD`.
* **`NON_LINEAR`** — plenty of data, but the fee doesn't follow a clean `pct × amount + fixed` line (tiered pricing, surcharges, mixed assessments), so the linear estimate isn't reliable.
Coverage is reported by **volume (money), not by cluster count**, because that's what matters economically: a merchant can have hundreds of tiny `THIN` clusters that together carry a rounding error of GMV. `good_gross_pct` — the share of settled *value* sitting in `GOOD` clusters — is therefore the headline number. Everything outside a `GOOD` cluster simply falls back to plain success-rate routing, so a low coverage figure doesn't break routing; it just means fewer payments get the cost lens. As a rule of thumb, wait for `good_gross_pct` to climb into a comfortable range before flipping the merchant-wide multi-objective flag.
The raw fields:
Answers "is cost estimation actually working for this merchant?" — the dashboard health-card summary. `good_gross_pct` (share of settled *volume* with a trustworthy model) is the headline number; everything not covered falls back to plain success-rate routing.
```bash theme={null}
curl "$BASE_URL/merchant-account/merchant_demo/cost-coverage" \
--header "$AUTH_HEADER"
```
```json theme={null}
{
"total_clusters": 214,
"good_clusters": 178,
"thin_clusters": 28,
"non_linear_clusters": 8,
"total_txns": 96430,
"good_txns": 88112,
"thin_txns": 6900,
"non_linear_txns": 1418,
"good_txn_pct": 91.4,
"total_gross": 3182004.11,
"good_gross": 2984502.9,
"thin_gross": 154002.4,
"non_linear_gross": 43498.81,
"good_gross_pct": 93.79,
"bps_rmse_p50": 2.1,
"bps_rmse_p90": 6.4,
"report_date": "2026-07-01"
}
```
* `GOOD` clusters have enough consistent data to trust; `THIN` have too little volume; `NON_LINEAR` have a fee structure the linear fit can't capture well.
* `bps_rmse_p50`/`p90` are the fit accuracy (basis-point error) of the `GOOD` clusters.
## Related
* [Cost Ingestion: Connector Setup](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-setup)
* [Cost Ingestion: Uploads](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-uploads)
* [Multi-Objective Routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective)
* [Analytics Endpoints](/decision-engine-api-reference/api-reference/guides/analytics-audit/analytics-endpoints) — see Cost Savings for the merchant-facing rollup.
# Cost Ingestion: Connector Setup
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-setup
Curl examples for registering connector settlement credentials and receiving settlement webhooks — the entry point for cost data ingestion.
# Cost Ingestion: Connector Setup
Cost ingestion learns each connector's *actual* per-transaction fee (percentage + flat component) from real settlement reports and invoices, at a fine-grained cluster level (connector × card network × card variant × funding × issuer country × currency × interchange category). That fitted cost model is what [multi-objective routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective) ranks gateways on.
### Why it's learned, not configured
Processor pricing is rarely a single number. The effective cost of a transaction depends on the card network, whether the card is credit or debit, where it was issued, the currency, and the interchange category — and published rate cards drift from what actually lands on the settlement statement once assessments, downgrades, and blended tiers are applied. Rather than ask a merchant to enter fee schedules by hand (which go stale the moment a processor re-prices), Decision Engine **reads the money that actually moved.** For each cluster it fits a simple linear model against real settlements — `fee ≈ pct_bps × amount + fixed` — using ordinary least squares. The slope becomes the percentage component (in basis points) and the intercept the flat per-transaction fee. That fitted `(pct_bps, fixed)` pair is the cost estimate every expected-value calculation uses.
Because the fit is per-cluster, the model captures that (say) Visa credit issued in the US costs a different amount than a domestic debit card — precisely the differences that make one gateway cheaper for one slice of traffic and pricier for another. How much of a merchant's volume has a *trustworthy* fit (versus too little data, or a fee structure the linear model can't capture) is what [cost coverage](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-fees#cost-coverage) reports.
Before any report or invoice can be ingested, register the connector account's settlement credentials.
## Data Sources
Settlement data reaches Decision Engine through three paths, all feeding the same `cost_ingestion` pipeline:
| Source | How it works | Docs |
| - | - | - |
| Webhook push | The connector calls Decision Engine when a report is ready. Verified via the stored `webhook_secret`, then queued. | This page |
| Scheduled poll | A background job polls the connector's reporting API for ready reports. No merchant action needed once credentials are set. | This page |
| Manual upload | Upload a report or invoice file directly — useful before webhooks are wired, for backfills, or testing. | [Uploads](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-uploads) |
## Register Connector Credentials
```bash theme={null}
curl --location "$BASE_URL/merchant-account/merchant_demo/connectors/adyen/credentials" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"account": "YOUR_ADYEN_MERCHANT_ACCOUNT_CODE",
"webhook_secret": "whsec_...",
"download_auth": "report_user:report_password"
}'
```
* `account` — the connector-side account (e.g. Adyen's `merchantAccountCode`).
* `webhook_secret` — used to verify inbound webhook signatures for this account.
* `download_auth` — credential used to authenticate report downloads for the scheduled poller. Either `"user:password"` for Basic auth, or a bare API key (sent as `X-API-Key`).
Response:
```json theme={null}
{
"merchant_id": "merchant_demo",
"connector": "adyen",
"account": "YOUR_ADYEN_MERCHANT_ACCOUNT_CODE",
"status": "saved"
}
```
Secrets are encrypted at rest and never returned by the API — subsequent reads only return masked hints.
## List Configured Connectors
```bash theme={null}
curl "$BASE_URL/merchant-account/merchant_demo/connectors" \
--header "$AUTH_HEADER"
```
```json theme={null}
[
{
"connector": "adyen",
"account": "YOUR_ADYEN_MERCHANT_ACCOUNT_CODE",
"webhook_secret_hint": "••••af31",
"download_auth_hint": "report_user:••••"
}
]
```
## Remove Credentials
```bash theme={null}
curl --request DELETE \
"$BASE_URL/merchant-account/merchant_demo/connectors/adyen/credentials/YOUR_ADYEN_MERCHANT_ACCOUNT_CODE" \
--header "$AUTH_HEADER"
```
Returns `204 No Content`. Deleting a source that isn't configured also returns success (idempotent).
## Settlement Webhook (Connector → Decision Engine)
Once credentials are registered, point the connector's settlement-report notification at:
```
POST /webhooks/settlement/:connector
```
This route is **public** (no `AUTH_HEADER`) — the connector authenticates itself via its own signature, which Decision Engine verifies against the `webhook_secret` stored for that `(connector, account)` pair. Adyen is the first supported connector (`:connector = adyen`).
```bash theme={null}
curl --location "$BASE_URL/webhooks/settlement/adyen" \
--header "Content-Type: application/json" \
--data @adyen-settlement-notification.json
```
The handler ACKs immediately and enqueues the report for background processing — download, parse, and re-fit all happen asynchronously in the ingest worker, so the connector always gets a fast response. A bad signature returns `401`; an unrecognized connector or malformed payload returns `400`.
## Notes
* Manual and webhook/poll-based ingestions share the same pipeline and history — see [Uploads](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-uploads) for the manual path and ingestion history.
* Once enough settlement data has been fitted, check [Cost Coverage](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-fees#cost-coverage) to see what share of volume has a trustworthy cost model.
## Related
* [Cost Ingestion: Uploads](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-uploads)
* [Cost Ingestion: Fees & Coverage](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-fees)
* [Multi-Objective Routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective)
# Cost Ingestion: Uploads
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-uploads
Curl examples for manually uploading settlement reports and invoices, and inspecting ingestion history.
# Cost Ingestion: Uploads
Use manual upload when webhooks aren't wired yet, for backfilling historical data, or for testing. Manual uploads share the same `cost_ingestion` pipeline and history as webhook- and poll-based ingestion (see [Connector Setup](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-setup)).
## Upload A Settlement Report
Settlement reports can run to several GB, so the request body is streamed straight to disk and processed in the background — the request returns immediately with a job id to poll.
```bash theme={null}
curl --location "$BASE_URL/merchant-account/merchant_demo/connectors/adyen/report?account=YOUR_ADYEN_MERCHANT_ACCOUNT_CODE" \
--header "$AUTH_HEADER" \
--header "Content-Type: text/csv" \
--data-binary @settlement-report.csv
```
Returns `202 Accepted` immediately:
```json theme={null}
{
"id": "ing_8f21a6c0",
"status": "processing"
}
```
Upload is capped at 8 GiB per file.
## Check Ingestion History
Poll to see history and in-flight progress, newest first:
```bash theme={null}
curl "$BASE_URL/merchant-account/merchant_demo/cost-ingestions" \
--header "$AUTH_HEADER"
```
```json theme={null}
[
{
"id": "ing_8f21a6c0",
"connector": "adyen",
"account": "YOUR_ADYEN_MERCHANT_ACCOUNT_CODE",
"source": "manual",
"status": "completed",
"staged_rows": 48213,
"report_date": "2026-07-01",
"period_start": "2026-06-01",
"period_end": "2026-06-30",
"currency_count": 3,
"currencies": ["USD", "EUR", "GBP"],
"country_count": 12,
"countries": ["US", "GB", "DE"],
"total_gross": 1284302.55,
"total_clusters": 214,
"good_clusters": 178,
"last_error": null,
"created_at": "2026-07-01T03:12:44Z"
}
]
```
`source` is `"manual"`, `"webhook"`, or `"poll"` depending on how the report arrived. `status` is `"processing"`, `"completed"`, or `"failed"` (see `last_error`).
## Delete An Ingestion
Removes the transactions that ingestion contributed, re-fits the affected connector/account so the served cost model reflects the deletion, and deletes the history row.
```bash theme={null}
curl --request DELETE \
"$BASE_URL/merchant-account/merchant_demo/cost-ingestions/ing_8f21a6c0" \
--header "$AUTH_HEADER"
```
Returns `204 No Content`. Returns `409 Conflict` if the ingestion is still `processing`.
## Detect Price Changes
Surfaces fee-regime changes detected by diffing each cluster's two most recent fits — useful for noticing when a connector silently repriced.
```bash theme={null}
curl "$BASE_URL/merchant-account/merchant_demo/cost-price-changes" \
--header "$AUTH_HEADER"
```
## Upload An Invoice
Invoices are small (a few hundred lines) and processed synchronously — the computed cost add-on is returned directly in the response. Use this to recover invoice-only fees (e.g. periodic/flat fees) that a settlement report alone doesn't capture.
```bash theme={null}
curl --location "$BASE_URL/merchant-account/merchant_demo/connectors/adyen/invoice?account=YOUR_ADYEN_MERCHANT_ACCOUNT_CODE&invoice_ref=INV-2026-06" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/pdf" \
--data-binary @adyen-invoice-june.pdf
```
```json theme={null}
{
"merchant_id": "merchant_demo",
"connector": "adyen",
"account": "YOUR_ADYEN_MERCHANT_ACCOUNT_CODE",
"pct_addon_bps": 2.4,
"fixed_addon": 0.01,
"total_addon_per_txn": 0.034,
"subtotal_ex_tax": 4820.55,
"card_volume": 1284302.55,
"txn_count": 48213,
"currency": "EUR",
"lines": 6,
"breakdown": [
{
"description": "Monthly platform fee",
"kind": "flat_per_txn",
"added": true,
"amount": 500.0,
"per_txn": 0.0104
},
{
"description": "Interchange (already in settlement data)",
"kind": "already_modeled",
"added": false,
"amount": 3200.0,
"per_txn": 0.0
}
]
}
```
Invoice uploads are capped at 32 MiB. `breakdown[].added` is `true` for fee lines this add-on newly captures, `false` for lines already reflected in the settlement-report model (e.g. interchange) or ignored (volume-only lines).
## List Invoice Add-Ons
```bash theme={null}
curl "$BASE_URL/merchant-account/merchant_demo/invoice-addons" \
--header "$AUTH_HEADER"
```
## Delete An Invoice Add-On
Reverts the merchant's served cost model to the learned-only (settlement-report-based) cost.
```bash theme={null}
curl --request DELETE \
"$BASE_URL/merchant-account/merchant_demo/connectors/adyen/invoice-addon" \
--header "$AUTH_HEADER"
```
Returns `204 No Content`.
## Invoice Reconciliation
Ties each stored invoice add-on back to coverage before/after, so you can see how much of the invoice's cost is now explained by the model.
```bash theme={null}
curl "$BASE_URL/merchant-account/merchant_demo/invoice-reconciliation" \
--header "$AUTH_HEADER"
```
## Related
* [Cost Ingestion: Connector Setup](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-setup)
* [Cost Ingestion: Fees & Coverage](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-fees)
# Update Gateway Score
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/feedback-scoring/update-gateway-score
Curl example for /update-gateway-score.
# Update Gateway Score
Call this after non-debit runtime payments so SR data stays current. Do not call it for `NTW_BASED_ROUTING` debit runs where `decided_gateway` is not the selected network.
## Request
```bash theme={null}
curl --location "$BASE_URL/update-gateway-score" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchantId": "merchant_demo",
"gateway": "stripe",
"gatewayReferenceId": null,
"status": "CHARGED",
"paymentId": "sr_001",
"enforceDynamicRoutingFailure": null
}'
```
## Response
```text theme={null}
Success
```
# Health Checks
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/health-status/health-check
Curl examples for /health, /health/ready, and /health/diagnostics.
# Health Checks
Health routes are public and do not require `AUTH_HEADER`. `/health/diagnostics` is the one exception — it needs `x-tenant-id`, see below.
## Liveness
```bash theme={null}
curl "$BASE_URL/health"
```
```json theme={null}
{ "message": "Health is good" }
```
## Readiness
```bash theme={null}
curl "$BASE_URL/health/ready"
```
```json theme={null}
{ "message": "Up" }
```
## Diagnostics
Unlike `/health` and `/health/ready`, this route resolves a tenant and requires `x-tenant-id` — omitting it fails with `TE_03: x-tenant-id not found in headers` even though no `AUTH_HEADER` is needed. `public` is the only tenant the shipped config files define.
```bash theme={null}
curl "$BASE_URL/health/diagnostics" \
--header "x-tenant-id: public"
```
```json theme={null}
{
"key_custodian_locked": false,
"database": {
"database_connection": "Working",
"database_read": "Working",
"database_write": "Working",
"database_delete": "Working"
}
}
```
# Legacy Decision Gateway
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/legacy/decision-gateway-legacy
Compatibility example for the legacy /decision_gateway route.
# Legacy Decision Gateway
`/decision_gateway` is retained for compatibility with older integrations. New integrations should use [`/decide-gateway`](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-sr-based).
```bash theme={null}
curl --location "$BASE_URL/decision_gateway" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchantId": "merchant_demo",
"eligibleGatewayList": ["stripe", "adyen"],
"rankingAlgorithm": "SR_BASED_ROUTING",
"paymentInfo": {
"paymentId": "legacy_001",
"amount": 1000,
"currency": "USD",
"paymentType": "ORDER_PAYMENT",
"paymentMethodType": "CARD",
"paymentMethod": "CREDIT"
}
}'
```
# Legacy Update Score
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/legacy/update-score-legacy
Compatibility example for the legacy /update-score route.
# Legacy Update Score
`/update-score` is retained for compatibility. New integrations should use [`/update-gateway-score`](/decision-engine-api-reference/api-reference/guides/feedback-scoring/update-gateway-score).
```bash theme={null}
curl --location "$BASE_URL/update-score" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchantId": "merchant_demo",
"gateway": "stripe",
"paymentId": "pay_001",
"status": "CHARGED"
}'
```
# Create Merchant Account
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/merchant-accounts/merchant-account-create
Curl example for creating a merchant account.
# Create Merchant Account
This public bootstrap route requires the configured admin secret.
## Request
```bash theme={null}
curl --location "$BASE_URL/merchant-account/create" \
--header "x-admin-secret: " \
--header "Content-Type: application/json" \
--data '{
"merchant_id": "merchant_demo",
"gateway_success_rate_based_decider_input": null
}'
```
## Response
```json theme={null}
{
"message": "Merchant account created successfully",
"merchant_id": "merchant_demo",
"gateway_success_rate_based_decider_input": null,
"api_key": "DE_..."
}
```
# Delete Merchant Account
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/merchant-accounts/merchant-account-delete
Curl example for deleting a merchant account.
# Delete Merchant Account
## Request
```bash theme={null}
curl --request DELETE "$BASE_URL/merchant-account/merchant_demo" \
--header "$AUTH_HEADER"
```
## Response
```json theme={null}
{
"message": "Merchant account deleted successfully",
"merchant_id": "merchant_demo"
}
```
# Get Merchant Account
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/merchant-accounts/merchant-account-get
Curl example for retrieving a merchant account.
# Get Merchant Account
## Request
```bash theme={null}
curl "$BASE_URL/merchant-account/merchant_demo" \
--header "$AUTH_HEADER"
```
## Response
```json theme={null}
{
"merchant_id": "merchant_demo",
"gateway_success_rate_based_decider_input": null
}
```
# Merchant Debit Routing Flag
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/merchant-accounts/merchant-debit-routing
Curl examples for reading and updating the merchant debit-routing feature flag.
# Merchant Debit Routing Flag
Debit/network routing is gated per merchant. Missing config defaults to disabled. Enable this flag before calling `/decide-gateway` with `NTW_BASED_ROUTING` or `NTW_SR_HYBRID_ROUTING`.
## Read Flag
```bash theme={null}
curl "$BASE_URL/merchant-account/merchant_demo/debit-routing" \
--header "$AUTH_HEADER"
```
```json theme={null}
{
"merchant_id": "merchant_demo",
"debit_routing_enabled": false
}
```
## Enable Flag
```bash theme={null}
curl --location "$BASE_URL/merchant-account/merchant_demo/debit-routing" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{ "enabled": true }'
```
```json theme={null}
{
"merchant_id": "merchant_demo",
"debit_routing_enabled": true
}
```
## Disable Flag
```bash theme={null}
curl --location "$BASE_URL/merchant-account/merchant_demo/debit-routing" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{ "enabled": false }'
```
## Run Debit Routing Transaction
After enabling the flag, send a debit card transaction through `/decide-gateway`. The debit router expects `paymentInfo.metadata` to be a JSON string containing `merchant_category_code`, `acquirer_country`, and `co_badged_card_data`.
```bash theme={null}
curl --location "$BASE_URL/decide-gateway" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchantId": "merchant_demo",
"eligibleGatewayList": ["stripe", "adyen"],
"rankingAlgorithm": "NTW_BASED_ROUTING",
"paymentInfo": {
"paymentId": "debit_001",
"amount": 1000,
"currency": "USD",
"country": "US",
"paymentType": "ORDER_PAYMENT",
"paymentMethodType": "CARD",
"paymentMethod": "DEBIT",
"authType": "THREE_DS",
"metadata": "{\"merchant_category_code\":\"merchant_category_code_0001\",\"acquirer_country\":\"US\",\"co_badged_card_data\":{\"card_type\":\"debit\",\"issuer_country\":\"US\",\"is_regulated\":false,\"regulated_name\":null,\"card_networks\":[\"VISA\",\"NYCE\",\"PULSE\",\"STAR\"]}}"
}
}'
```
```json theme={null}
{
"decided_gateway": "stripe",
"routing_approach": "NTW_BASED_ROUTING",
"debit_routing_output": {
"co_badged_card_networks_info": [
{ "network": "NYCE", "saving_percentage": 1.2 },
{ "network": "PULSE", "saving_percentage": 0.8 }
],
"issuer_country": "US",
"is_regulated": false,
"card_type": "debit"
}
}
```
## Notes
* Use backend enum strings: `NTW_BASED_ROUTING` and `NTW_SR_HYBRID_ROUTING`.
* `co_badged_card_data.card_type` must be lowercase `debit` or `credit` inside metadata.
* If the flag is disabled, debit-routing transactions should fail with a debit-routing-not-enabled error.
## Related
* [Debit Gateway Transaction](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-debit-routing)
* [Network + SR Hybrid Routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-hybrid-routing)
* [Payment Audit](/decision-engine-api-reference/api-reference/guides/analytics-audit/analytics-endpoints)
# Decide Gateway: Debit Routing
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-debit-routing
Curl example for /decide-gateway using NTW_BASED_ROUTING.
# Decide Gateway: Debit Routing
Enable the merchant debit-routing flag before this call. The backend reads debit inputs from `paymentInfo.metadata`, so `metadata` must be a JSON string with `co_badged_card_data`.
## Request
```bash theme={null}
curl --location "$BASE_URL/decide-gateway" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchantId": "merchant_demo",
"eligibleGatewayList": ["stripe", "adyen"],
"rankingAlgorithm": "NTW_BASED_ROUTING",
"eliminationEnabled": false,
"enableMultiObjective": false,
"paymentInfo": {
"paymentId": "debit_001",
"amount": 1000,
"currency": "USD",
"paymentType": "ORDER_PAYMENT",
"paymentMethodType": "CARD",
"paymentMethod": "DEBIT",
"authType": "THREE_DS",
"metadata": "{\"merchant_category_code\":\"merchant_category_code_0001\",\"acquirer_country\":\"US\",\"co_badged_card_data\":{\"co_badged_card_networks\":[\"VISA\",\"NYCE\",\"PULSE\",\"STAR\"],\"issuer_country\":\"US\",\"is_regulated\":false,\"regulated_name\":null,\"card_type\":\"debit\"}}"
}
}'
```
## Response
```json theme={null}
{
"decided_gateway": "stripe",
"gateway_priority_map": null,
"filter_wise_gateways": null,
"priority_logic_tag": null,
"routing_approach": "NTW_BASED_ROUTING",
"gateway_before_evaluation": null,
"priority_logic_output": null,
"debit_routing_output": {
"co_badged_card_networks_info": [
{ "network": "NYCE", "saving_percentage": 1.2 },
{ "network": "PULSE", "saving_percentage": 0.9 },
{ "network": "VISA", "saving_percentage": 0.1 }
],
"issuer_country": "US",
"is_regulated": false,
"regulated_name": null,
"card_type": "debit"
},
"reset_approach": "NO_RESET",
"routing_dimension": null,
"routing_dimension_level": null,
"is_scheduled_outage": false,
"is_dynamic_mga_enabled": false,
"gateway_mga_id_map": null,
"is_rust_based_decider": true,
"multi_objective_info": null
}
```
## Multi-Objective Option
When multi-objective routing is enabled (request field `enableMultiObjective`, or the `multi_objective_routing_enabled` merchant feature flag), a cost-aware post-step may re-rank the SR result and the response gains a `multi_objective_info` block. Details and examples: [Multi-objective routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective).
# Decide Gateway: Network + SR Hybrid
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-hybrid-routing
Curl example for /decide-gateway using NTW_SR_HYBRID_ROUTING.
# Decide Gateway: Network + SR Hybrid
`NTW_SR_HYBRID_ROUTING` combines debit/network metadata with SR-based gateway scoring.
```bash theme={null}
curl --location "$BASE_URL/decide-gateway" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchantId": "merchant_demo",
"eligibleGatewayList": ["stripe", "adyen"],
"rankingAlgorithm": "NTW_SR_HYBRID_ROUTING",
"eliminationEnabled": false,
"enableMultiObjective": false,
"paymentInfo": {
"paymentId": "hybrid_001",
"amount": 1000,
"currency": "USD",
"paymentType": "ORDER_PAYMENT",
"paymentMethodType": "CARD",
"paymentMethod": "DEBIT",
"authType": "THREE_DS",
"metadata": "{\"merchant_category_code\":\"merchant_category_code_0001\",\"acquirer_country\":\"US\",\"co_badged_card_data\":{\"co_badged_card_networks\":[\"VISA\",\"NYCE\",\"PULSE\",\"STAR\"],\"issuer_country\":\"US\",\"is_regulated\":false,\"regulated_name\":null,\"card_type\":\"debit\"}}"
}
}'
```
```json theme={null}
{
"decided_gateway": "stripe",
"routing_approach": "NTW_BASED_ROUTING",
"debit_routing_output": {
"co_badged_card_networks_info": [
{ "network": "NYCE", "saving_percentage": 1.2 },
{ "network": "PULSE", "saving_percentage": 0.9 }
],
"issuer_country": "US",
"is_regulated": false,
"regulated_name": null,
"card_type": "debit"
},
"multi_objective_info": null
}
```
## Multi-Objective Option
When multi-objective routing is enabled (request field `enableMultiObjective`, or the `multi_objective_routing_enabled` merchant feature flag), a cost-aware post-step may re-rank the SR result and the response gains a `multi_objective_info` block. Details and examples: [Multi-objective routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective).
# Decide Gateway: Multi-Objective Routing
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective
Curl example for /decide-gateway with the multi-objective (cost-aware) post-step and the multi_objective_info response block.
# Decide Gateway: Multi-Objective Routing
## What multi-objective routing is
Plain success-rate (SR) routing optimises a single objective: send each payment to the gateway most likely to authorise it. But the *cheapest* path to a successful payment is not always the one with the highest auth rate — a gateway that is one point worse on auth but materially cheaper per transaction can leave the merchant with more money in hand. Multi-objective routing balances **two** objectives at once — authorisation *and* processing cost — so routing maximises the merchant's economic outcome, not just the raw approval odds.
It is implemented as a **cost-aware post-step layered on top of SR scoring**, not a replacement for it. The SR scorer runs first and produces its usual ranking; the post-step then takes those scores, attaches a per-gateway fee estimate to each, and re-ranks the candidates on expected value. Because it only ever runs *after* SR scoring, everything SR gives you (dimension-level buckets, elimination, hedging) is preserved — cost is simply an additional lens applied at the end.
## How the ranking works
After the success-rate scorer picks its head gateway, the engine fetches per-PSP fee estimates and re-ranks every gateway that has cost data on economic value:
```
Economic value (EV) = auth rate × settlement value
settlement value = txn amount − cost of payment processing (acquirer, issuer & network fee)
```
The settlement value is derived from the merchant's `margin` and the per-PSP cost estimate (see the `margin` field on [Create success-rate config](/decision-engine-api-reference/api-reference/guides/scoring-config/success-rate-config-create)).
If a cheaper PSP has a strictly higher expected value than the SR head, it is promoted (`outcome: COST_WON`) and `routing_approach` becomes `SR_SELECTION_MULTI_OBJECTIVE`. Otherwise the SR head is kept (`outcome: AUTH_WON`) and `routing_approach` keeps its normal SR value. Either way, the response carries a `multi_objective_info` block explaining the decision — which gateway SR would have picked, which one cost analysis chose, and by how much — so every cost-driven override is auditable.
## Enablement
| Switch | Scope | Behaviour |
| - | - | - |
| `multi_objective_routing_enabled` feature flag | Merchant | Primary rollout switch. Used whenever the request omits `enableMultiObjective`. |
| `enableMultiObjective` request field | Per request | Optional boolean override. `true` forces the post-step on, `false` forces it off, omitted falls back to the merchant flag. |
Notes:
* The post-step only runs on SR-scored decisions and is skipped while hedging (exploration) is active for the transaction.
* `margin` (fraction of ticket, e.g. `0.20`) comes from the merchant's success-rate config — see [Create success-rate config](/decision-engine-api-reference/api-reference/guides/scoring-config/success-rate-config-create). It defaults to `1.0` when unset.
* This post-step re-ranks the SR scores it is handed; it does not tune them. [Autopilot](/decision-engine-api-reference/api-reference/guides/autopilot/merchant-features) is the separate self-tuning job that calibrates SR hedging and bucket size, and can run alongside this post-step (they are independent dials — `enableMultiObjective` and `use_autopilot`).
* Gateways without fee data cannot be ranked on expected value and never win on cost; if the SR head itself has no fee data, the SR order is kept.
* Per-gateway fee data comes from [cost ingestion](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-setup) — settlement reports and invoices fitted into a per-cluster cost model. Check [cost coverage](/decision-engine-api-reference/api-reference/guides/cost-ingestion/cost-ingestion-fees#cost-coverage) to see what share of volume actually has a trustworthy fee estimate before relying on this post-step.
* To compare cost-aware routing against a plain auth-rate baseline on live traffic before flipping the merchant flag, run it as an [A/B test experiment](/decision-engine-api-reference/api-reference/guides/ab-testing/ab-testing-create) arm (`enable_multi_objective: true` on one arm only).
## Request
```bash theme={null}
curl --location "$BASE_URL/decide-gateway" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchantId": "merchant_demo",
"eligibleGatewayList": ["stripe", "adyen", "checkout"],
"rankingAlgorithm": "SR_BASED_ROUTING",
"eliminationEnabled": true,
"enableMultiObjective": true,
"paymentInfo": {
"paymentId": "mo_001",
"amount": 1000,
"currency": "USD",
"country": "US",
"paymentType": "ORDER_PAYMENT",
"metadata": null,
"paymentMethodType": "CARD",
"paymentMethod": "CREDIT",
"authType": "THREE_DS",
"cardIsin": "424242"
}
}'
```
## Response: cost won
`adyen` is promoted over the SR head `stripe` because its expected value is higher at the configured margin; fallbacks are re-ordered by descending expected value (gateways without fee data follow, ordered by auth rate).
```json theme={null}
{
"decided_gateway": "adyen",
"fallback_gateways": ["stripe", "checkout"],
"gateway_priority_map": {
"stripe": 0.94,
"adyen": 0.91,
"checkout": 0.88
},
"filter_wise_gateways": null,
"priority_logic_tag": null,
"routing_approach": "SR_SELECTION_MULTI_OBJECTIVE",
"gateway_before_evaluation": "stripe",
"reset_approach": "NO_RESET",
"routing_dimension": "ORDER_PAYMENT,CARD,CREDIT,UNKNOWN",
"routing_dimension_level": "CARD_LEVEL",
"is_scheduled_outage": false,
"is_dynamic_mga_enabled": false,
"gateway_mga_id_map": null,
"is_rust_based_decider": true,
"multi_objective_info": {
"outcome": "COST_WON",
"reason": "Promoted 'adyen' over 'stripe' on expected value — saves 80.00 bps for 3.00pp auth.",
"srHead": { "psp": "stripe", "authRate": 0.94, "costBps": 180.0 },
"chosen": { "psp": "adyen", "authRate": 0.91, "costBps": 100.0 },
"costSavedBps": 80.0,
"qualifiedCount": 3,
"margin": 0.2,
"evGapTop2": 0.00182
}
}
```
## Response: auth won
The post-step ran but the SR head was already the highest expected-value gateway, so nothing moves and `routing_approach` keeps its normal SR value. Note `margin: 1` — the default applied when the merchant's success-rate config sets no `margin`.
```json theme={null}
{
"decided_gateway": "adyen",
"fallback_gateways": [
"stripe",
"checkout"
],
"gateway_priority_map": {
"adyen": 0.65,
"checkout": 0.58,
"stripe": 0.65
},
"filter_wise_gateways": null,
"priority_logic_tag": null,
"routing_approach": "SR_SELECTION_V3_ROUTING",
"gateway_before_evaluation": "adyen",
"priority_logic_output": {
"isEnforcement": false,
"gws": [
"stripe",
"adyen",
"checkout"
],
"priorityLogicTag": null,
"gatewayReferenceIds": {},
"primaryLogic": null,
"fallbackLogic": null
},
"debit_routing_output": null,
"reset_approach": "NO_RESET",
"routing_dimension": "ORDER_PAYMENT, CARD, DEBIT, DEBIT",
"routing_dimension_level": "CARD_LEVEL",
"is_scheduled_outage": false,
"is_dynamic_mga_enabled": false,
"gateway_mga_id_map": null,
"is_rust_based_decider": true,
"latency": 3,
"multi_objective_info": {
"outcome": "AUTH_WON",
"reason": "SR head retained — it is the highest expected-value PSP (3 ranked on EV).",
"srHead": {
"psp": "adyen",
"authRate": 0.65,
"costBps": 156.94736842105263
},
"chosen": {
"psp": "adyen",
"authRate": 0.65,
"costBps": 156.94736842105263
},
"costSavedBps": null,
"qualifiedCount": 3,
"margin": 1,
"evGapTop2": 0.013780000000000014
}
}
```
## multi\_objective\_info Fields
| Field | Type | Meaning |
| - | - | - |
| `outcome` | `COST_WON` \| `AUTH_WON` | Terminal outcome of the post-step. `COST_WON` means a higher-EV PSP was promoted above the SR head. |
| `reason` | string | Human-readable explanation of the decision. |
| `srHead` | object \| null | The PSP the SR scorer would have picked (`psp`, `authRate`, `costBps`). |
| `chosen` | object \| null | The PSP the post-step actually chose. Equals `srHead` when auth won. |
| `costSavedBps` | number \| null | Fee saved in bps when `outcome == COST_WON` (`srHead.costBps − chosen.costBps`). |
| `qualifiedCount` | integer | Number of PSPs that had cost data and were ranked on expected value. |
| `margin` | number | Merchant margin (fraction of ticket) applied for this transaction. |
| `evGapTop2` | number \| null | Expected-value gap between the top-two EV-ranked PSPs, as a fraction of ticket. Small values mean the decision was close. `null` when fewer than two PSPs had cost data. |
The block is absent (`null`) when the post-step did not run at all — feature off, hedging active, or a non-SR routing flavour.
# Decide Gateway: Priority List Based
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-pl-based
Curl example for /decide-gateway using PL_BASED_ROUTING.
# Decide Gateway: Priority List Based
`PL_BASED_ROUTING` evaluates active priority logic and returns the selected connector order.
```bash theme={null}
curl --location "$BASE_URL/decide-gateway" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchantId": "merchant_demo",
"eligibleGatewayList": ["stripe", "adyen", "checkout"],
"rankingAlgorithm": "PL_BASED_ROUTING",
"eliminationEnabled": false,
"enableMultiObjective": false,
"paymentInfo": {
"paymentId": "pl_001",
"amount": 1000,
"currency": "USD",
"country": "US",
"paymentType": "ORDER_PAYMENT",
"paymentMethodType": "CARD",
"paymentMethod": "CREDIT",
"authType": "THREE_DS"
}
}'
```
```json theme={null}
{
"decided_gateway": "stripe",
"routing_approach": "PRIORITY_LOGIC",
"priority_logic_output": {
"isEnforcement": false,
"gws": ["stripe", "adyen", "checkout"],
"gatewayReferenceIds": {}
},
"reset_approach": "NO_RESET",
"multi_objective_info": null
}
```
## Multi-Objective Option
When multi-objective routing is enabled (request field `enableMultiObjective`, or the `multi_objective_routing_enabled` merchant feature flag), a cost-aware post-step may re-rank the SR result and the response gains a `multi_objective_info` block. Details and examples: [Multi-objective routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective).
# Decide Gateway: SR Based Routing
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-sr-based
Curl example for /decide-gateway using SR_BASED_ROUTING.
# Decide Gateway: SR Based Routing
`SR_BASED_ROUTING` uses auth-rate history, downtime state, and eligible gateway filters to choose a connector.
## Request
```bash theme={null}
curl --location "$BASE_URL/decide-gateway" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchantId": "merchant_demo",
"eligibleGatewayList": ["stripe", "adyen", "checkout"],
"rankingAlgorithm": "SR_BASED_ROUTING",
"eliminationEnabled": true,
"enableMultiObjective": false,
"paymentInfo": {
"paymentId": "sr_001",
"amount": 1000,
"currency": "USD",
"country": "US",
"paymentType": "ORDER_PAYMENT",
"metadata": null,
"paymentMethodType": "CARD",
"paymentMethod": "CREDIT",
"authType": "THREE_DS",
"cardIsin": "424242"
}
}'
```
## Response
```json theme={null}
{
"decided_gateway": "stripe",
"gateway_priority_map": {
"stripe": 0.94,
"adyen": 0.91,
"checkout": 0.88
},
"filter_wise_gateways": null,
"priority_logic_tag": null,
"routing_approach": "SR_SELECTION_V3_ROUTING",
"gateway_before_evaluation": "stripe",
"priority_logic_output": {
"isEnforcement": false,
"gws": ["stripe", "adyen", "checkout"],
"priorityLogicTag": null,
"gatewayReferenceIds": {},
"primaryLogic": null,
"fallbackLogic": null
},
"reset_approach": "NO_RESET",
"routing_dimension": "ORDER_PAYMENT,CARD,CREDIT,UNKNOWN",
"routing_dimension_level": "CARD_LEVEL",
"is_scheduled_outage": false,
"is_dynamic_mga_enabled": false,
"gateway_mga_id_map": null,
"is_rust_based_decider": true,
"multi_objective_info": null
}
```
## Routing Approach Values
* `SR_SELECTION_V3_ROUTING`: best eligible gateway from SR score at the active routing dimension.
* `SR_V3_DOWNTIME_ROUTING`: some eligible gateways were deprioritized due to downtime.
* `SR_V3_ALL_DOWNTIME_ROUTING`: all eligible gateways are in downtime and the best degraded option is selected.
* `SR_V3_HEDGING`: exploration mode across eligible gateways.
* `SR_V3_DOWNTIME_HEDGING`: hedging with partial downtime.
* `SR_V3_ALL_DOWNTIME_HEDGING`: hedging while all eligible gateways are down.
* `SR_SELECTION_MULTI_OBJECTIVE`: the multi-objective post-step promoted a cheaper gateway over the SR head on expected value — see [Multi-objective routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective).
## Multi-Objective Option
When multi-objective routing is enabled (request field `enableMultiObjective`, or the `multi_objective_routing_enabled` merchant feature flag), a cost-aware post-step may re-rank the SR result and the response gains a `multi_objective_info` block. Details and examples: [Multi-objective routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective).
# Routing Config Endpoints
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/scoring-config/config-endpoints
Curl examples for routing key metadata and SR dimension configuration.
# Routing Config Endpoints
## Routing Keys
The dashboard uses this route to discover valid rule builder keys.
```bash theme={null}
curl "$BASE_URL/config/routing-keys" \
--header "$AUTH_HEADER"
```
## Configure SR Dimensions
```bash theme={null}
curl --location "$BASE_URL/config-sr-dimension" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchant_id": "merchant_demo",
"dimensions": ["payment_method_type", "payment_method", "currency"]
}'
```
## Get SR Dimensions
Read back the SR scoring dimensions currently configured for a merchant.
```bash theme={null}
curl "$BASE_URL/config-sr-dimension/merchant_demo" \
--header "$AUTH_HEADER"
```
```json theme={null}
{
"merchant_id": "merchant_demo",
"paymentInfo": {
"udfs": [],
"fields": ["payment_method_type", "payment_method", "currency"]
}
}
```
Returns an empty default (`fields: null`) when nothing has been configured for the merchant yet.
## GSM Options
Gateway Status Mapper rule catalog — the error-code classification options used by the `gsm-scoring-filter` merchant feature (see [Merchant Features](/decision-engine-api-reference/api-reference/guides/autopilot/merchant-features)).
```bash theme={null}
curl "$BASE_URL/gsm/options" \
--header "$AUTH_HEADER"
```
```json theme={null}
{
"rules": [
{
"connector": "stripe",
"flow": "authorize",
"subFlow": "card",
"errorCode": "card_declined",
"errorMessage": "Your card was declined.",
"errorCategory": "soft_decline",
"unifiedCode": "UE_001",
"unifiedMessage": "Card declined by issuer",
"decision": "retry"
}
]
}
```
# Create Elimination Config
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/scoring-config/elimination-config-create
Curl example for creating elimination config.
# Create Elimination Config
```bash theme={null}
curl --location "$BASE_URL/rule/create" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchant_id": "merchant_demo",
"config": {
"type": "elimination",
"data": {
"bucketSize": 5,
"eliminationThreshold": 0.2
}
}
}'
```
```json theme={null}
{ "merchant_id": "merchant_demo", "config": { "type": "elimination" } }
```
# Delete Elimination Config
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/scoring-config/elimination-config-delete
Curl example for deleting elimination config.
# Delete Elimination Config
```bash theme={null}
curl --location "$BASE_URL/rule/delete" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchant_id": "merchant_demo",
"algorithm": "elimination"
}'
```
```json theme={null}
{ "message": "Rule config deleted successfully" }
```
# Get Elimination Config
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/scoring-config/elimination-config-get
Curl example for reading elimination config.
# Get Elimination Config
```bash theme={null}
curl --location "$BASE_URL/rule/get" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchant_id": "merchant_demo",
"algorithm": "elimination"
}'
```
```json theme={null}
{ "merchant_id": "merchant_demo", "config": { "type": "elimination" } }
```
# Update Elimination Config
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/scoring-config/elimination-config-update
Curl example for updating elimination config.
# Update Elimination Config
```bash theme={null}
curl --location "$BASE_URL/rule/update" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchant_id": "merchant_demo",
"config": {
"type": "elimination",
"data": {
"bucketSize": 10,
"eliminationThreshold": 0.15
}
}
}'
```
```json theme={null}
{ "merchant_id": "merchant_demo", "config": { "type": "elimination" } }
```
# Create Success Rate Config
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/scoring-config/success-rate-config-create
Curl example for creating success-rate scoring config.
# Create Success Rate Config
Success-rate (SR) routing is Decision Engine's default scoring strategy: for each payment it estimates how likely every eligible gateway is to authorise *right now* and sends the payment to the strongest one. The estimate is not a static number — it is learned continuously from the live outcomes (success/failure) the engine observes, so the routing follows real-time gateway health instead of a fixed priority list. The success-rate config is where you tune how that learning behaves.
Three knobs do most of the work:
* **`defaultBucketSize`** — how many of the most recent transactions per gateway the score is computed over. A small bucket reacts fast to a gateway going down but is noisier; a large bucket is stable but slower to notice change. This is a sliding window: new outcomes push old ones out, so the score always reflects recent behaviour.
* **`defaultHedgingPercent`** — the share of traffic deliberately *explored* away from the current best gateway. Without exploration the engine would starve non-leading gateways of traffic and never learn that they have recovered; hedging keeps every candidate's score fresh. (This is the same dial [Autopilot](/decision-engine-api-reference/api-reference/guides/autopilot/merchant-features) tunes automatically.)
* **`defaultLatencyThreshold`** — optional latency ceiling used when penalising slow gateways.
You can override any of these per traffic segment via **`subLevelInputConfig`** — keyed by dimensions such as `paymentMethodType`, card network, currency, or country — so a merchant can, for example, run a larger bucket for high-volume card traffic and a smaller one for a thin wallet segment. Anything not overridden falls back to the `default*` values.
```bash theme={null}
curl --location "$BASE_URL/rule/create" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchant_id": "merchant_demo",
"config": {
"type": "successRate",
"data": {
"defaultBucketSize": 20,
"defaultLatencyThreshold": null,
"defaultHedgingPercent": null,
"margin": 0.20,
"subLevelInputConfig": {
"paymentMethodType": {
"CARD": { "bucketSize": 30, "hedgingPercent": 0.05 }
}
}
}
}
}'
```
```json theme={null}
{ "merchant_id": "merchant_demo", "config": { "type": "successRate" } }
```
`margin` is the merchant margin as a fraction of ticket (e.g. `0.20` for 20%). It feeds the [multi-objective routing](/decision-engine-api-reference/api-reference/guides/run-transactions/decide-gateway-multi-objective) economic-value ranking `EV = auth rate × settlement value` (settlement value = txn amount − cost of payment processing) by setting the merchant's share of the ticket, and defaults to `1.0` when unset.
# Delete Success Rate Config
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/scoring-config/success-rate-config-delete
Curl example for deleting success-rate scoring config.
# Delete Success Rate Config
```bash theme={null}
curl --location "$BASE_URL/rule/delete" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchant_id": "merchant_demo",
"algorithm": "successRate"
}'
```
```json theme={null}
{ "message": "Rule config deleted successfully" }
```
# Get Success Rate Config
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/scoring-config/success-rate-config-get
Curl example for reading success-rate scoring config.
# Get Success Rate Config
```bash theme={null}
curl --location "$BASE_URL/rule/get" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchant_id": "merchant_demo",
"algorithm": "successRate"
}'
```
```json theme={null}
{ "merchant_id": "merchant_demo", "config": { "type": "successRate" } }
```
# Update Success Rate Config
Source: https://api-reference.hyperswitch.io/decision-engine-api-reference/api-reference/guides/scoring-config/success-rate-config-update
Curl example for updating success-rate scoring config.
# Update Success Rate Config
```bash theme={null}
curl --location "$BASE_URL/rule/update" \
--header "$AUTH_HEADER" \
--header "Content-Type: application/json" \
--data '{
"merchant_id": "merchant_demo",
"config": {
"type": "successRate",
"data": {
"defaultBucketSize": 30,
"defaultLatencyThreshold": 2500,
"defaultHedgingPercent": 0.1
}
}
}'
```
```json theme={null}
{ "merchant_id": "merchant_demo", "config": { "type": "successRate" } }
```