General Card H2H
Collect card data on your own form and post it server-to-server, then send card payouts. Requires PCI DSS scope.
When to use it
General Card H2H (host-to-host) is for merchants who collect card data on their own form and post it to us server-to-server. You own the checkout UI; we route the card to an acquirer and return the result. If 3-D Secure is required, we hand back a URL to send the cardholder to.
Because raw PAN/CVV pass through your servers, your backend must be PCI DSS compliant and the call must be server-to-server over TLS — never from a browser or mobile app. If you don't want that scope, use the General Card Gate (hosted form) instead — the pay-out half of this page is identical to it.
Signing credentials from Getting started and a
cascade_id enabled for card pay-in (and one for card pay-out, which may be
the same or different).
Pay-in — post card data directly
There is no invoice and no hosted page. You send the card and customer in one signed request.
- Collect card data on your form PAN, expiry month/year, cardholder name, and CVV.
-
POST it server-to-server
Call the card pay-in endpoint with your
cascade_id. -
Handle 3-D Secure if needed
If the response carries a
payment_url, redirect the cardholder there to complete the challenge; otherwise the result is final. - Receive the result Track via callback and/or the payment status endpoint.
/api/payment/payin/card{
"cascade_id": "card-h2h-eu",
"payment": {
"payment_id": "order-2026-000123",
"currency": "USD",
"amount": 2599,
"description": "Order #98765 - Premium subscription"
},
"card": {
"pan": "4111111111111111",
"year": 2032,
"month": 11,
"card_holder": "JANE SUBSCRIBER",
"cvv": "123"
},
"customer": {
"id": "cust-4451",
"full_name": "Jane Subscriber",
"email": "[email protected]",
"ip_address": "198.51.100.24"
},
"workflow_hooks": {
"callback_url": "https://merchant.example.com/mp/callbacks",
"return_success_url": "https://merchant.example.com/orders/98765/thank-you",
"return_decline_url": "https://merchant.example.com/orders/98765/retry"
}
}
Card field rules: cvv matches ^[0-9]{3,4}$; month is
1–12; year is the 4-digit year. Send the cardholder ip_address when
you have it — it improves risk screening.
resp = signed_post("/api/payment/payin/card", {
"cascade_id": "card-h2h-eu",
"payment": {
"payment_id": "order-2026-000123",
"currency": "USD",
"amount": 2599, # $25.99
"description": "Order #98765 - Premium subscription",
},
"card": {
"pan": "4111111111111111",
"year": 2032,
"month": 11,
"card_holder": "JANE SUBSCRIBER",
"cvv": "123",
},
"customer": {
"id": "cust-4451",
"full_name": "Jane Subscriber",
"email": "[email protected]",
"ip_address": "198.51.100.24",
},
"workflow_hooks": {
"callback_url": "https://merchant.example.com/mp/callbacks",
"return_success_url": "https://merchant.example.com/orders/98765/thank-you",
"return_decline_url": "https://merchant.example.com/orders/98765/retry",
},
})
payment = resp.json()
if payment.get("payment_url"):
# 3-D Secure or other redirect step required — send the cardholder here.
redirect_to(payment["payment_url"])
Response
{
"request_status": "success",
"payment_id": "4b77cec4-3f7a-4568-9b1c-7d2c4f1df7a2",
"merchant_payment_id": "order-2026-000123",
"payment_status": "processing",
"payment_url": "https://stage.example-mp.com/public/payment/4b77cec4-.../3ds",
"message": "Payment (PayIn) with internal uid=4b77cec4-... has been created.",
"error_code": null,
"error_message": null
}
A non-null payment_url means a redirect step (typically 3-D Secure) is pending. Don't treat
processing as failure — wait for the callback or poll status to reach a terminal state.
Tracking the pay-in
/api/payment/statusresp = signed_post("/api/payment/status", {
"merchant_payment_id": "order-2026-000123"
})
payment = resp.json()
# payment["status"] -> "success" | "processing" | "decline" | "error"
# payment["processing_info"]["amount_acquired"] -> settled amount (minor units)
Pay-out — to a card
Card payouts are identical to the General Card Gate — the hosted form only affects pay-ins. The destination is the card number.
/api/payment/payout/cardresp = signed_post("/api/payment/payout/card", {
"cascade_id": "card-payout-eu",
"payment": {
"payment_id": "payout-2026-000045",
"currency": "EUR",
"amount": 15_000, # €150.00
"description": "Affiliate payout May 2026",
},
"card": {
"pan": "5555555555554444",
"year": 2032,
"month": 11,
"card_holder": "ACME AFFILIATES",
},
"customer": {"id": "partner-2391", "full_name": "Acme Affiliates OÜ"},
"workflow_hooks": {"callback_url": "https://merchant.example.com/mp/callbacks"},
})
payout_uid = resp.json()["payment_id"]
Tracking the pay-out
Same as any payment — poll /api/payment/status by merchant_payment_id, or wait
for the callback.
Testing & go-live
- Use scheme test cards from your account manager to exercise approval, decline, and a 3-D Secure challenge.
- Confirm you redirect to
payment_urlwhenever it's present and resume cleanly afterwards. - Never log full PAN/CVV. Confirm your callback handler verifies the signature and is idempotent.
- Have your PCI attestation in order before going live; then swap base URL + credentials to production.