General Card Gate
Accept card pay-ins on the MagicPayments hosted card form (no PCI scope on your side) and send card payouts.
When to use it
The General Card Gate accepts card pay-ins on the MagicPayments-hosted card form. The cardholder enters their PAN, expiry and CVV on our page — so the card data never touches your servers and your PCI scope stays minimal (SAQ-A). 3-D Secure, if required, is handled on the hosted page too. Use it for any card currency the gate supports (e.g. USD, EUR).
If you operate your own PCI-compliant card form and want to post raw card data yourself, use General Card H2H instead.
| Operation | Rail | How the integration looks |
|---|---|---|
| Pay-in | Card (hosted form) | Create an invoice, redirect the cardholder to the hosted form. |
| Pay-out | Card | Server-to-server call to the card payout endpoint. |
Signing credentials from Getting started, a pay-in
gate_id for the card gate, and a pay-out
cascade_id enabled for card payouts.
Pay-in — hosted card form
-
Create the invoice
Call the gate endpoint with your
gate_id, the amount and currency. -
Redirect the cardholder
Send the browser to
invoice_url. They enter card details and pass any 3-D Secure challenge on our page. -
Receive the result
On completion we call your
callback_urland redirect the browser to yourreturn_success_url/return_decline_url.
/api/invoice{
"gate_id": "card-gate-eu",
"invoice": {
"invoice_id": "order-2026-000777",
"currency": "EUR",
"amount": 4999,
"description": "Annual subscription",
"ttl_minutes": 20
},
"customer": {
"id": "cust-4451",
"full_name": "Jane Subscriber",
"email": "[email protected]"
},
"workflow_hooks": {
"callback_url": "https://merchant.example.com/mp/callbacks",
"return_success_url": "https://merchant.example.com/orders/777/thank-you",
"return_decline_url": "https://merchant.example.com/orders/777/retry"
}
}
Python
resp = signed_post("/api/invoice", {
"gate_id": "card-gate-eu",
"invoice": {
"invoice_id": "order-2026-000777",
"currency": "EUR",
"amount": 4999, # €49.99
"description": "Annual subscription",
"ttl_minutes": 20,
},
"customer": {
"id": "cust-4451",
"full_name": "Jane Subscriber",
"email": "[email protected]",
},
"workflow_hooks": {
"callback_url": "https://merchant.example.com/mp/callbacks",
"return_success_url": "https://merchant.example.com/orders/777/thank-you",
"return_decline_url": "https://merchant.example.com/orders/777/retry",
},
})
redirect_url = resp.json()["invoice_url"]
Response
{
"request_status": "success",
"invoice_id": "1c3e5a90-7b21-4d6f-8a44-9e0c2b5d7f31",
"merchant_invoice_id": "order-2026-000777",
"invoice_status": "unpaid",
"invoice_url": "https://stage.example-mp.com/public/invoice/1c3e5a90-.../gate",
"message": "Invoice (Gate PayIn) with internal uid=1c3e5a90-... has been created."
}
Tracking the pay-in
/api/invoice/statusresp = signed_post("/api/invoice/status", {
"merchant_invoice_id": "order-2026-000777"
})
invoice = resp.json()
# invoice["status"] -> "paid" | "payment_failed" | "declined_by_payer" | "expired"
# invoice["actual_payment"]["processing_info"]["amount_credited"] -> net to your wallet
With the hosted form, sensitive card data and the 3-D Secure dance live entirely on our side. You get the smallest possible PCI footprint and don't have to build or certify a card-entry UI.
Pay-out — to a card
Card payouts (original credit transactions) go server-to-server. The destination is the card number; an expiry is included when the scheme requires it.
/api/payment/payout/card{
"cascade_id": "card-payout-eu",
"payment": {
"payment_id": "payout-2026-000045",
"currency": "EUR",
"amount": 15000,
"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Ü",
"email": "[email protected]"
},
"workflow_hooks": {
"callback_url": "https://merchant.example.com/mp/callbacks"
}
}
Python
resp = 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"]
Sending a raw destination PAN means that request handles cardholder data, so it must run on a PCI-compliant backend over TLS — never from a browser or app. The hosted form keeps pay-ins out of scope, but a card payout by PAN is server-side by nature.
Tracking the pay-out
/api/payment/statusresp = signed_post("/api/payment/status", {
"merchant_payment_id": "payout-2026-000045"
})
# resp.json()["status"] -> "success" | "processing" | "decline" | "error"
Testing & go-live
- Use the test
gate_id/cascade_idand scheme test cards from your account manager. - Exercise an approval, a decline, and a 3-D Secure challenge on the hosted form.
- Confirm your callback handler verifies the signature, is idempotent, and reads
amount_acquired/amount_creditedcorrectly. - Switch base URL + credentials to production; request shapes are unchanged.