Skip to main content

Build a custom gateway from scratch

Define your own request schema, response templates, and scenarios when no template matches the provider you are integrating with.

howto3 min readUpdated September 11, 2026

A custom gateway lets you copy an API that has no template here — a regional processor, an internal payments service, or something still being designed. You set the request fields, the responses, and the results yourself.

The builder runs as a four-step wizard, and you can move back before launching.

Before you start

  • The provider's API docs, or a sample request and response to copy
  • A confirmed email address on your account

Build it

  1. Open Payment Gateways and click Create Gateway. This opens the Payment Gateway Simulator.
  2. On step 1, Request, set the name, currency, and default redirect URL. All three are required.
  3. Add your request fields under Request Schema, giving each a type such as INTEGER or STRING and marking the required ones. If you have a sample body, click Import from JSON and let it read the fields out.
  4. On step 2, Response, write the JSON that init and verify return. Use {{ }} placeholders for values that change per payment.
  5. On step 3, Payment Scenario, add the results the hosted page will offer. Each takes a name, a label, and a status code.
  6. On step 4, Review, check the summary and create the gateway.
Payment Gateway Simulator on step 1 of 4, showing name, currency and default redirect URL fields above a request schema builder with typed fields.
Step 1. The schema builder gives each field a type and a set of rules.

Values you can put in a template

Response and webhook templates read placeholders from the payment and from the request that started it. Alongside the amount, currency, and identifier, every gateway generates these:

FieldHolds
statusCurrent state of the payment
payment_idIdentifier for the payment
invoice_noGenerated invoice number
payment_methodMethod recorded against it
payment_request_atWhen it started
payment_completion_atWhen it finished
error_codeCode for a failed result
error_messageMessage for a failed result
remarksFree-text note

Fields from the original request are available too, so a template can echo back an order reference the caller sent.

Scenarios are the point

A gateway with one success result proves the happy path and nothing more. The reason to build a mock is the other paths: a decline carrying the provider's real error code, a payment left processing, a customer who walks away.

Each scenario has its own status code, redirect template, and webhook payload. So a decline can send a genuinely different notification, not a success body with one flag flipped.

Check it worked

Post to the init endpoint using your own field names. The reply should match your template. Open the payment URL and confirm every scenario you defined is listed on the page.

If it didn't work

{"error":"Validation failed","message":"The request payload does not match the required schema."}
The body does not satisfy your schema. Compare what you sent against the Schema tab.

{"error":"Validation failed","message":"The amount must be a number."}
The amount field arrived as something other than a number. A formatted string with a currency symbol is the usual cause.

The amount is ignored.
The amount mapping does not name the field you are sending.

A response shows literal {{ }} text.
The placeholder does not match any available value. Check it against the table above.

Limits worth knowing

Templates fill in values. They do not run logic. There are no conditionals and no arithmetic inside a response. Anything that should change with the result belongs in a scenario.

Was this page helpful?