Skip to main content

Init and Verify endpoints

Request format, authentication schemes, responses, and error bodies for the payment endpoints.

reference4 min readUpdated September 11, 2026

Every gateway exposes three endpoints under its own slug. This page covers their request formats, authentication, responses, and errors.

Endpoints

MethodPathPurposeRate limit
POST/api/pg/{slug}/initStart a payment120 / minute
GET/api/pg/{slug}/verify/{paymentId}Read a payment's state
POST/api/pg/{slug}/oauth2/tokenTrade credentials for a Bearer token120 / minute

The slug and API key are on the gateway's Integration tab.

Authentication

The scheme is set per gateway. Templates inherit whichever one the provider they copy uses.

SchemeHow to send itChecked against
bearerAuthorization: Bearer <key>The gateway's API key
basicAuthorization: Basic <base64>Configured username and password
api_key_headerA header, X-API-Key unless renamedThe gateway's API key
api_key_queryA query parameter, api_key unless renamedThe gateway's API key
noneNothing

A token from the gateway's own OAuth endpoint is accepted on every call, whatever the configured scheme. That is what makes two-step flows work.

Token exchange

POST /api/pg/{slug}/oauth2/token
Authorization: Basic <base64 of client_id:secret>
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials

Any other grant_type returns 400 with {"error":"unsupported_grant_type"}.

Starting a payment

The fields init accepts come from the gateway's schema. Every gateway needs an amount and a currency; the names depend on the template.

POST /api/pg/{slug}/init
Authorization: Bearer sk_test_XXXXXXXX
Content-Type: application/json

{
  "amount": 4999,
  "currency": "USD"
}

Some templates want the amount as a whole number and reject decimals. The Stripe template is one of them.

A gateway with no response template replies with the default body:

{
  "payment_url": "https://mockgateway.com/pg/pay/9f8c2a1e-...",
  "payment_id": "9f8c2a1e-..."
}

With a template set, you get whatever that template produces. Send the customer to the payment URL inside it.

Reading a payment

GET /api/pg/{slug}/verify/{paymentId}
Authorization: Bearer sk_test_XXXXXXXX

The default reply, when no verify template is set:

{
  "payment_id": "9f8c2a1e-...",
  "status": "pending",
  "amount": "4999.00",
  "currency": "USD",
  "created_at": "2026-08-08T09:12:44.000000Z"
}

The identifier can be the internal one or the one your init reply advertised. Templates that mint provider-shaped identifiers hand you the second kind, and that is all a server-to-server integration has, so both resolve to the same payment.

Errors

StatusBodyCause
401 {"error":"Unauthorized","message":"Invalid or missing Bearer token."} Credentials missing or wrong. The wording names the scheme in use.
422 {"error":"Validation failed","message":"The request payload does not match the required schema."} Body does not satisfy the schema
422 {"error":"Validation failed","message":"Amount and currency are required."} One of the two is missing
422 {"error":"Validation failed","message":"The amount must be a number."} The amount field is not numeric
400 {"error":"Gateway Setup Incomplete","message":"This payment gateway is not fully configured. Please complete the setup before using the API."} The gateway is missing something it needs to reply
404 {"error":"Not found","message":"No payment with that id."} No payment on this gateway matches
429 Rate limit passed on init or the token endpoint

Gateways carrying their own error bodies return those instead, at whatever status they specify. The above are the defaults. Templates that copy a provider's error format return that format — the Stripe template, for example, answers a bad amount with a Stripe-shaped invalid_request_error.

Repeated requests

A gateway can name a header to treat as an idempotency key. When it does, a repeat carrying the same key gets exactly the body the first request received instead of starting a second payment.

Hosted pages

These are browser URLs, not API endpoints. They need no credentials.

PathShows
/pg/pay/{paymentId}The hosted page with the gateway's scenarios
/pg/result/{paymentId}The result page shown afterwards

Was this page helpful?