Hyperswitch is composable, open-source payments infrastructure written in Rust. It sits between your application and 100+ payment processors (Stripe, Adyen, Braintree, Worldpay, Checkout.com, Cybersource, PayPal, and more), giving you one API and one dashboard to accept payments, route transactions intelligently, save payment methods, issue refunds and payouts, and observe everything — without rebuilding an integration for each processor or locking yourself to a single vendor.
This guide shows you how to run Hyperswitch, connect a payment processor, and process payments end to end using the REST API, the Control Center dashboard, and the checkout SDKs. It documents only what exists in the source at the referenced commit.
Note
Hyperswitch is the "app server" — the core payments engine. It works alongside companion services (a PCI card vault, an encryption service, a merchant dashboard, and client SDKs) that are described throughout this guide. You can run just the app server, or the full suite.
1. Quick Start
The fastest way to try Hyperswitch is the one-click local setup, which runs the app server and Control Center in Docker.
Important
Prerequisites: Docker or Podman installed and running,
git, and roughly 4 GB of free RAM for the standard profile. The setup script detects your container engine automatically.
macOS / Linux
git clone --depth 1 --branch latest https://github.com/juspay/hyperswitch
cd hyperswitch
scripts/setup.sh
Windows (WSL2)
# Run inside a WSL2 Ubuntu shell with Docker Desktop's WSL integration enabled
git clone --depth 1 --branch latest https://github.com/juspay/hyperswitch
cd hyperswitch
bash scripts/setup.sh
The script prompts you to choose a deployment profile:
1) Standard Setup: [Recommended] App server + Control Center. Ideal for a quick trial.
2) Full Stack Setup: Everything in Standard, plus Monitoring and Scheduler.
3) Minimal Setup: Standalone App server only.
When it finishes, it prints access links. The defaults are:
| Service | URL | What it is |
|---|---|---|
| App server (API) | http://localhost:8080 |
The REST API you integrate against |
| Health check | http://localhost:8080/health |
Liveness probe |
| Control Center | http://localhost:9000 |
Merchant dashboard (configure connectors, view payments) |
| Web checkout demo | http://localhost:9060 |
A sample checkout page using the web SDK |
Tip
Verify the server is up before integrating:
curl http://localhost:8080/healthhealth is good
To stop the standard stack:
docker compose down
If you chose Full Stack, stop it with the full profile list (the script prints the exact command):
docker compose --profile scheduler --profile monitoring --profile olap --profile full_setup down
2. What You Can Do with Hyperswitch
Hyperswitch is modular — adopt the whole payment suite, or integrate only the modules you need on top of an existing stack.
| Module | What it gives you |
|---|---|
| Unified payments API | One API to authorize, capture, void, refund, and sync payments across 100+ processors. |
| Intelligent Routing | Route each transaction to the processor with the best predicted success rate; fall back and retry automatically across processors. |
| Vault | PCI-compliant storage for cards, tokens, wallets, and bank credentials. Supports bring-your-own-vault (VGS, TokenEx) without re-tokenizing. |
| Alternate Payment Methods (APMs) | Drop-in support for PayPal, Apple Pay, Google Pay, Samsung Pay, Pay by Bank, and BNPL providers such as Klarna. |
| Payouts | Send money out (disbursements, refunds-to-source) through supported payout processors. |
| Subscriptions | Create and manage recurring billing subscriptions. |
| Revenue Recovery | Smart retry strategies tuned by card BIN, region, and method to combat passive churn. |
| Reconciliation | Automated 2-way and 3-way reconciliation with scheduled, customizable outputs. |
| Cost Observability | Dashboards to audit and optimize payment costs, downgrades, and penalties. |
Note
Each module is independent. A common starting point is moving from a single Stripe or Braintree integration to multi-processor routing, while keeping your existing vault intact.
3. Installation & Deployment Options
You have several ways to run Hyperswitch depending on whether you want to trial it, develop against it, or run it yourself in production.
3.1 Hosted Sandbox (no setup)
Sign up for the fully hosted sandbox — no installation required. You get the full Control Center, can configure connectors, and can test payments from the UI or API.
| Environment | Base URL |
|---|---|
| Hosted sandbox | https://sandbox.hyperswitch.io |
| Hosted production | https://api.hyperswitch.io |
Dashboard: https://app.hyperswitch.io.
3.2 Local Docker (self-hosted trial / development)
Use scripts/setup.sh as shown in Quick Start. Under the hood it runs docker compose with one or more profiles:
| Profile | Adds |
|---|---|
| (none) | App server, PostgreSQL, Redis, Control Center, web SDK, migrations runner |
scheduler |
Producer + consumer (deferred task processing) |
monitoring |
Grafana, Loki, Tempo, Prometheus, OpenTelemetry collector, RedisInsight |
olap |
Analytics stack: Kafka, ClickHouse, OpenSearch, Kafka UI |
full_setup |
Mailhog (email testing) and related extras |
clustered_redis |
Redis cluster nodes instead of a single Redis |
full_kv |
Key-value (KV) mode services for the write-through cache |
Tip
To bring up everything at once without the interactive menu:
docker compose --profile scheduler --profile monitoring --profile olap --profile full_setup up -d
3.3 Cloud (Kubernetes / Terraform)
For production, deploy to AWS, GCP, or Azure:
- Helm charts —
hyperswitch-helmdeploys the stack to any Kubernetes cluster. - Terraform suite —
hyperswitch-suitewires together the core, vault, Control Center, and web SDK as a full-suite deployment. This is the recommended starting point for the complete stack.
Important
Production deployment, configuration hardening, secrets/KMS, and the card vault are covered in depth in the Hyperswitch Admin Guide. This section is only an orientation.
3.4 The Hyperswitch ecosystem
The app server in this repository is the center of gravity. These companion repositories extend it:
| Repository | Role |
|---|---|
hyperswitch (this repo) |
App server: routing, retries, vaulting, observability. Rust. |
hyperswitch-card-vault |
PCI-compliant card storage. Rust. |
hyperswitch-encryption-service |
Encryption, decryption, key management. Rust. |
hyperswitch-control-center |
Full merchant dashboard. ReScript. |
hyperswitch-web |
Primary web checkout SDK. ReScript → React, distributed on npm. |
hyperswitch-sdk-android / -ios / react-native-hyperswitch / flutter_hyperswitch |
Mobile checkout SDKs. |
hyperswitch-prism |
Standalone unified connector library (use processors directly without running the full switch). |
4. Core Concepts
A few objects appear throughout the API. Understanding them makes the rest of the guide straightforward.
Merchant account : Your top-level account on a Hyperswitch deployment. Holds API keys, connectors, and profiles. Created with an Admin API key.
Connector (Merchant Connector Account) : A configured link to one payment processor (e.g. your Stripe credentials). You can attach many connectors and route between them.
Profile (Business Profile) : A logical grouping under a merchant — for example, one per brand, region, or business unit. Routing rules, webhooks, and settings can differ per profile.
Customer : An end user you bill. Customers can have saved payment methods.
Payment : A payment object (sometimes called the payment intent) that moves through a lifecycle from creation to a terminal state. Each processing try is a payment attempt.
Payment method
: How the customer pays — card, wallet, bank_transfer, pay_later, etc. A specific instance (a saved card) can be tokenized in the vault for reuse.
Note
Hyperswitch exposes two API versions. v1 (paths like
/payments) is the established, widely used API and powers the hosted sandbox. v2 (paths like/v2/payments) is a newer, more resource-oriented API that splits intent creation from confirmation. This guide focuses on v1 and flags v2 where it differs.
5. Authentication
Hyperswitch authenticates API requests with keys. There are five key types; you mostly use the first three.
| Key type | Example prefix | Where you use it |
|---|---|---|
| Secret (API) key | snd_…, prod_… |
Server-to-server requests, in the api-key header. Keep it secret. |
| Admin API key | (deployment config value) | System operations: creating merchant and connector accounts. |
| Publishable key | pk_snd_… |
Client-side (web/mobile) code. Safe to expose. |
| Ephemeral key | (short-lived) | Temporary, scoped access to a single customer object. |
| JWT bearer | (Authorization: Bearer …) | Control Center sessions and user authentication. Issued during login. |
Server-side requests pass the secret key in the api-key header:
curl http://localhost:8080/payments \
-H 'api-key: snd_your_secret_key' \
-H 'Content-Type: application/json' \
-d '{"amount": 6540, "currency": "USD"}'
Caution
Never expose your secret key or admin key in browser or mobile code. Use the publishable key for any client-side call.
The Admin API key is not generated from the dashboard — it is a value you set when you deploy. For Docker Compose it lives in config/docker_compose.toml:
# config/docker_compose.toml
admin_api_key = "your_admin_key_here"
For Helm, set it in your values.yaml:
# values.yaml
adminApiKey: your_admin_key_here
Important
On the hosted sandbox/production environments, admin API keys are managed by Juspay and are not provided publicly. The admin key matters when you self-host and need to bootstrap merchant and connector accounts via the API.
6. Your First Payment (API)
A payment moves through a predictable lifecycle. These are the statuses you will see:
| Status | Meaning |
|---|---|
requires_payment_method |
Payment created; no payment method attached yet. |
requires_confirmation |
A payment method is attached; awaiting confirmation. |
requires_customer_action |
Confirmed, but the customer must complete authentication (e.g. 3DS redirect). |
requires_capture |
Authorized; awaiting a separate capture (manual capture mode). |
processing |
Being processed by the connector (automatic capture). |
succeeded |
Completed successfully. |
failed |
The processor reported a processing failure. |
Additional terminal/partial states include partially_captured, partially_captured_and_capturable, conflicted (an amount/currency discrepancy, possible with crypto or EU bank-transfer flows), and expired.
6.1 Create a payment
The minimal request needs only an amount (in the currency's minor unit — e.g. cents) and a currency:
curl http://localhost:8080/payments \
-H 'api-key: snd_your_secret_key' \
-H 'Content-Type: application/json' \
-d '{
"amount": 6540,
"currency": "USD"
}'
You can include customer details, a description, and metadata in the same call:
curl http://localhost:8080/payments \
-H 'api-key: snd_your_secret_key' \
-H 'Content-Type: application/json' \
-d '{
"amount": 6540,
"currency": "USD",
"customer": {
"id": "cus_abcdefgh",
"email": "[email removed]",
"name": "John Dough",
"phone": "9123456789"
},
"description": "My first payment request",
"metadata": { "udf1": "some-value" }
}'
The response contains the payment payment_id, a client_secret (used by the SDK on the client side), the current status, and the list of available payment methods.
Tip
amountis always an integer in the minor unit of the currency:6540means USD 65.40. Hyperswitch never uses floating-point amounts.
6.2 Confirm the payment
Attach a payment method and confirm. The example below confirms with raw card data (only do this from a PCI-compliant server; otherwise use the SDK):
curl http://localhost:8080/payments/{payment_id}/confirm \
-H 'api-key: snd_your_secret_key' \
-H 'Content-Type: application/json' \
-d '{
"payment_method": "card",
"payment_method_data": {
"card": {
"card_number": "4242424242424242",
"card_exp_month": "10",
"card_exp_year": "25",
"card_cvc": "123",
"card_holder_name": "Joseph Doe"
}
}
}'
Note
You can collapse create + confirm into one call by adding
"confirm": true(and the payment method fields) to the create request. Separating them is useful when the client attaches the payment method.
If the connector requires customer authentication (such as 3D Secure), the payment moves to requires_customer_action and the response includes a redirect URL. After the customer completes it, they return to your return_url with query parameters:
?status=succeeded&payment_intent_client_secret=pay_..._secret_...&amount=10000&manual_retry_allowed=false&signature=...&signature_algorithm=HMAC-SHA512
Tip
Verify the
signatureparameter using your profile'spayment_response_hash_keybefore trusting the redirect result. Never treat the redirect query string as authoritative without verifying the HMAC.
6.3 Capture (manual capture mode)
If you created the payment with "capture_method": "manual", authorize now and capture later. Capture the full amount with an empty body, or a partial amount:
# Partial capture
curl http://localhost:8080/payments/{payment_id}/capture \
-H 'api-key: snd_your_secret_key' \
-H 'Content-Type: application/json' \
-d '{ "amount_to_capture": 654 }'
# Full capture
curl http://localhost:8080/payments/{payment_id}/capture \
-H 'api-key: snd_your_secret_key' \
-H 'Content-Type: application/json' \
-d '{}'
6.4 Retrieve / sync a payment
curl http://localhost:8080/payments/{payment_id} \
-H 'api-key: snd_your_secret_key'
Use the /payments/{payment_id} GET to fetch the latest known state. To force a status refresh from the connector, use the sync endpoint (POST /payments/sync).
6.5 Make a 3DS payment
Request 3D Secure explicitly at creation:
curl http://localhost:8080/payments \
-H 'api-key: snd_your_secret_key' \
-H 'Content-Type: application/json' \
-d '{
"amount": 6540,
"currency": "USD",
"authentication_type": "three_ds"
}'
7. Refunds
Refund a succeeded payment. refund_type: "instant" attempts an immediate refund; omit amount to refund the whole payment.
# Partial refund
curl http://localhost:8080/refunds \
-H 'api-key: snd_your_secret_key' \
-H 'Content-Type: application/json' \
-d '{
"payment_id": "pay_the_payment_id",
"amount": 654,
"refund_type": "instant",
"reason": "Customer returned product"
}'
Retrieve a refund:
curl http://localhost:8080/refunds/{refund_id} \
-H 'api-key: snd_your_secret_key'
Note
A deployment limits refunds per payment via the
refund.max_attemptssetting (default 10) and the maximum refundable age viarefund.max_age(default 365 days). See the Admin Guide.
8. Connectors (Payment Processors)
A connector is your configured credentials for one processor. Hyperswitch ships integrations for 100+ processors including Stripe, Adyen, PayPal, Checkout.com, Cybersource, Bank of America, Worldpay, Braintree, and Global Payments.
The easiest way to add a connector is the Control Center (http://localhost:9000): open Connectors → Add a payment processor, choose the processor, and enter its credentials. You can also create one through the API using an Admin API key (the MerchantConnectorAccount endpoints).
Important
When you self-host, every connector you intend to use must have a valid base URL configured in the server config. The
[connectors]section ofconfig/config.example.tomllists the sandbox base URLs for each processor (for exampleadyen.base_url,stripe.base_url). Empty or invalid base URLs cause requests to that connector to fail.
Restricting payment methods per connector
You can limit which payment methods a connector offers based on currency and country using payment method filters ([pm_filters.<connector>]):
[pm_filters.stripe]
paypal = { currency = "USD,INR", country = "US" }
This restricts Stripe's PayPal method to USD/INR in the US. If you omit currency or country, all values are accepted. See the Admin Guide for the full filter reference.
9. Routing
Routing decides which connector processes a transaction. Hyperswitch supports static and dynamic strategies, configured per profile through the API (or the Control Center's visual workflow builder).
Common routing operations (under /routing):
| Operation | Endpoint |
|---|---|
| Create a routing config | POST /routing |
| List routing configs | GET /routing |
| Activate a config | POST /routing/{algorithm_id}/activate |
| Retrieve the active config | GET /routing/active |
| Set the default config | POST /routing/default |
| Decision manager (3DS / surcharge rules) | PUT/GET/DELETE /routing/decision, /routing/decision/surcharge |
| Evaluate a routing rule | POST /routing/rule/evaluate |
Tip
Intelligent (success-rate-based) routing continuously sends transactions to the processor with the highest predicted authorization rate and retries failures on alternates. Enable and tune it from the Control Center; the underlying configuration is exposed through these endpoints.
10. Other Everyday Tasks
10.1 Saving payment methods and mandates
- Save a payment method for a customer so they can pay again without re-entering details (vaulted via the card vault). Pass
customer_acceptanceon confirm to record consent. - Mandates authorize recurring or merchant-initiated transactions. Manage them under
/mandates(retrieve, revoke) and via a customer's mandates (GET /customers/{customer_id}/mandates).
10.2 Payouts
Send money out (if your deployment is built with the payouts feature and a payout-capable connector):
| Operation | Endpoint |
|---|---|
| Create a payout | POST /payouts/create |
| Confirm / fulfill | POST /payouts/{payout_id}/confirm, /fulfill |
| Cancel | POST /payouts/{payout_id}/cancel |
| Retrieve | GET /payouts/{payout_id} |
| List | GET /payouts/list |
10.3 Subscriptions
Recurring billing under /subscriptions:
| Operation | Endpoint |
|---|---|
| Create | POST /subscriptions/create |
| Create & confirm | POST /subscriptions |
| Confirm | POST /subscriptions/{subscription_id}/confirm |
| Pause / resume / cancel | POST /subscriptions/{subscription_id}/pause · /resume · /cancel |
| Estimate | GET /subscriptions/estimate |
10.4 Webhooks (receiving events)
Hyperswitch sends outgoing webhooks to your server for payment, refund, dispute, and other events when webhooks.outgoing_enabled is on. Configure your webhook endpoint per profile in the Control Center. Incoming webhooks from connectors are received at the /webhooks endpoints.
Tip
Webhook deliveries can be inspected and replayed via the webhook-events endpoints, and the dashboard surfaces delivery attempts. Always verify webhook signatures before acting on an event.
10.5 Disputes and fraud
- Disputes (chargebacks) are tracked under
/disputes(list, retrieve, submit evidence). - Blocklist lets you block specific cards/fingerprints (
/blocklist). - If built with the fraud (
frm) feature, fraud-management checks run inline on payments.
11. Accepting Payments in a Browser or App (SDKs)
For most integrations you should not send raw card data to your own server. Instead, collect payment details with a Hyperswitch checkout SDK, which tokenizes them directly:
- On your server, create a payment (
POST /payments) and return itsclient_secretto your front end. - On the client, initialize the SDK (
hyperswitch-webfor browsers; the Android/iOS/React Native/Flutter SDKs for mobile) with your publishable key and theclient_secret. - The SDK renders a unified checkout, collects and tokenizes the payment method, and confirms the payment.
- Handle the result (and any 3DS redirect) via the SDK callbacks.
Note
The
react-demo-appbundled in the local setup (http://localhost:9060) is a working example of this flow against your local server.
12. Troubleshooting
Error: health endpoint not responding
Cause: The app server container is still starting, failed to start, or the database/Redis dependencies are not ready.
Solution: Check container status with docker compose ps and logs with docker compose logs hyperswitch-server. The server depends on PostgreSQL and Redis being healthy first.
Prevention: Wait for the migrations runner to finish on first boot; the database schema must be applied before the server accepts traffic.
Error: {"error":{"type":"api","message":"Failed to fetch currency exchange rate","code":"HE_00"}} — Could not acquire the lock for cache entry
Cause: A stale forex cache lock in Redis after enabling currency conversion. Solution: Remove the lock key, then restart the application:
redis-cli del "{forex_cache}_lock"
Prevention: This typically appears only right after first enabling forex. It is self-resolving once the lock clears.
Error: requests to a connector fail immediately
Cause: The connector's base_url is empty or invalid in your config, or the connector credentials are wrong.
Solution: Confirm the [connectors].<connector>.base_url value is set (the [connectors] section of config.example.toml lists valid sandbox URLs), and re-check the credentials you entered in the Control Center.
Prevention: Connector base URLs are not optional when self-hosting — set every one you use.
Error: payment stuck in requires_customer_action
Cause: The customer has not completed the required authentication (e.g. a 3DS challenge), or your return_url was not reachable.
Solution: Ensure the customer is redirected to the URL returned on confirm, and that your return_url is publicly reachable. Retrieve the payment to see the latest status.
Prevention: Always supply a valid return_url for flows that may require authentication.
Error: payment created but no connector attempted it
Cause: No connector is configured/enabled for the requested payment method, currency, or country, or a pm_filters rule excluded it.
Solution: Add or enable a connector for that method in the Control Center, and check your [pm_filters.<connector>] rules.
Prevention: Review payment-method filters when onboarding a new connector or currency.
Error: 401/403 on an API call
Cause: Wrong key for the operation — using a publishable key for a server call, or a regular API key where an admin key is required (creating merchant/connector accounts).
Solution: Use the secret api-key for server requests; use the admin API key for account-creation endpoints.
Prevention: See the key reference in Authentication.
13. FAQ
Q: Is Hyperswitch free and open source? Yes — it is licensed under the Apache 2.0 License. You can self-host it at no license cost.
Q: Do I need a PCI certification to use it? To send raw card numbers to your own server, yes. If you do not hold PCI certification, collect card data with the Hyperswitch checkout SDK (Unified Checkout) so card data never touches your server.
Q: How many payment processors does it support? 100+ out of the box, including Stripe, Adyen, PayPal, Checkout.com, Cybersource, Worldpay, Braintree, Bank of America, and Global Payments.
Q: What's the difference between the v1 and v2 APIs?
v1 (/payments) is the established API used by the hosted sandbox. v2 (/v2/payments) is newer and splits intent creation (/create-intent) from confirmation (/confirm-intent). Pick one and stay consistent; this guide uses v1.
Q: Are amounts in dollars or cents?
Always the minor unit (cents for USD). 6540 = USD 65.40.
Q: Can I run only the payment API without the dashboard, analytics, and scheduler?
Yes — choose the Minimal profile in scripts/setup.sh (or build the server with only the oltp feature) to run a standalone app server.
Q: Do I have to send card data through Hyperswitch's API? No. The recommended path is the SDK, which tokenizes on the client. Server-side raw-card confirm exists for PCI-certified integrators.
Q: How do I save a card for future payments?
Confirm the payment with a customer_acceptance object and a customer.id. The card is vaulted and can be reused via the customer's saved payment methods.
Q: Where do I configure routing rules?
In the Control Center's routing workflow builder, or via the /routing API endpoints. Rules are scoped per business profile.
Q: How do I move from sandbox to production?
Switch the base URL to https://api.hyperswitch.io (hosted) or your production deployment, and use prod_-prefixed keys with live connector credentials. Review the go-live checklist in the official API reference.
Q: Can I send money out, not just collect it?
Yes, if your deployment is built with the payouts feature and a payout-capable connector. See Payouts.
Q: Where are the full request/response schemas?
In the OpenAPI specification shipped with the project (api-reference/v1/openapi_spec_v1.json and the v2 spec) and the hosted API reference.
14. Reference
14.1 Default local ports
| Port | Service |
|---|---|
8080 |
App server (REST API) |
9000 |
Control Center dashboard |
9050 |
Web checkout SDK |
9060 |
React demo checkout app |
5432 |
PostgreSQL |
6379 |
Redis |
8025 |
Mailhog (email testing UI) |
3000 |
Grafana (monitoring profile) |
8123 |
ClickHouse (olap profile) |
9200 |
OpenSearch (olap profile) |
8090 |
Kafka UI (olap profile) |
14.2 Key payment endpoints (v1)
| Method | Path | Purpose |
|---|---|---|
POST |
/payments |
Create a payment (optionally confirm). |
POST |
/payments/{payment_id}/confirm |
Attach a payment method and confirm. |
POST |
/payments/{payment_id}/capture |
Capture an authorized payment (full or partial). |
POST |
/payments/{payment_id}/cancel |
Cancel/void a payment. |
GET |
/payments/{payment_id} |
Retrieve a payment. |
POST |
/payments/sync |
Force a status sync from the connector. |
GET |
/payments/list |
List payments. |
POST |
/payments/{payment_id}/incremental_authorization |
Increase an authorization. |
POST |
/refunds |
Create a refund. |
GET |
/refunds/{refund_id} |
Retrieve a refund. |
POST |
/customers |
Create a customer. |
GET |
/customers/{customer_id} |
Retrieve a customer. |
POST |
/payouts/create |
Create a payout. |
POST |
/routing |
Create a routing configuration. |
GET |
/health |
Liveness check. |
GET |
/health/ready |
Readiness (deep health) check. |
Note
v2 equivalents live under
/v2/...(for examplePOST /v2/payments/create-intentandPOST /v2/payments/{payment_id}/confirm-intent). The full, version-specific surface is in the bundled OpenAPI specs.
14.3 Where to go next
- Self-hosting, configuration, security, and operations: the Hyperswitch Admin Guide.
- Full request/response schemas: the bundled OpenAPI specifications.
- Connector-specific setup: the official connector guides linked from the project README.