payment-gateway.app Docs
API Reference

Main Backend Public Endpoints

Buyer-facing and provider-facing endpoints used by hosted checkout, portal, and webhook flows.

Main Backend Public Endpoints

Base URL: https://<your-main-backend-host>/api/v1 — your deployment sets the host via MAIN_BACKEND_DOMAIN. Self-hosted examples often use webhook.yourcompany.com or webhook.example.com; hosted production uses https://webhook.payment-gateway.appHostnames & DNS conventions, Self-Hosted Installation.

The Main Backend handles buyer-facing runtime operations: serving checkout sessions, processing transaction submissions, powering the customer portal, validating VAT IDs, and receiving incoming provider webhooks.

[!IMPORTANT] This is not the primary merchant integration surface. Merchants should create and manage checkouts through the Admin API using Organization API keys or System API keys where appropriate. The endpoints below are mainly consumed by the hosted checkout UI, portal UI, and payment-provider infrastructure.


Checkouts

Get Checkout Session

GET /api/v1/checkouts/:id

Retrieves a checkout session by its public ID. Used by the Main Frontend to render the payment page.

When the response includes checkoutSettings.vatIdValidation, the value is the effective runtime mode exposed to checkout, not just the raw merchant preference. If checkout is configured for vies but organization tax settings do not currently allow VIES-backed tax handling, the Main Backend downgrades the session response to format so buyer-facing validation stays aligned with backend tax behavior.

Authentication: No API key/JWT required. License enforcement applies (requests are denied when license state is BLOCKED or NOT_ACTIVATED).

Browser access (CORS): This endpoint enforces an Origin allow-list derived from the Site/Organization frontend domains plus MPG_MAIN_FRONTEND_DOMAIN. Requests without a valid Origin (or Referer) will be rejected with 403.

Path Parameters:

ParameterTypeDescription
idstringPublic checkout session ID

Response 200:

{
  "id": "abc123",
  "currency": "EUR",
  "status": "pending",
  "lineItems": [
    {
      "name": "Professional Plan",
      "quantity": 1,
      "unitAmount": 4900
    }
  ],
  "providers": ["stripe"],
  "branding": {
    "logo": "https://...",
    "primaryColor": "#3b82f6"
  },
  "expiresAt": "2026-03-08T14:00:00Z"
}

Preview Checkout Tax

POST /api/v1/checkouts/:id/tax-preview

Returns backend-calculated checkout totals for the current billing details before the buyer submits payment. The response is used by the hosted checkout UI to display net, tax, gross, and tax breakdown values while preserving the final calculation for transaction creation.

The endpoint uses organization tax settings, effective-dated tax rates, tax rules, gross/net price mode, rounding, shipping destination overrides for goods/shipping lines, and VIES-backed buyer type only when the effective checkout VAT validation mode allows VIES.

Request Body:

{
  "billingAddress": {
    "country": "DE",
    "postcode": "10115",
    "vatId": "DE123456789"
  }
}

Response 200:

{
  "taxIncluded": true,
  "totalNet": 4118,
  "totalTax": 782,
  "totalGross": 4900,
  "taxBreakdown": [
    {
      "taxRate": 19,
      "taxRateCode": "DE_STANDARD",
      "taxableBase": 4118,
      "taxAmount": 782
    }
  ]
}

Checkout Handoff

Cross-domain checkout flows can store provider and billing selections behind a short-lived opaque token before the buyer completes payment on the hosted checkout domain.

Create Handoff Token

POST /api/v1/checkouts/:id/handoff
Content-Type: application/json

Request Body:

{
  "providerId": "507f1f77bcf86cd799439011",
  "billingAddress": {
    "name": "Jane Smith",
    "email": "jane@example.com",
    "line1": "123 Main St",
    "city": "Berlin",
    "postalCode": "10115",
    "country": "DE"
  }
}

billingAddress is optional. The :id path parameter is the checkout session public ID.

Response 200:

{
  "handoffToken": "opaque_token_value",
  "expiresInSeconds": 600
}

Consume Handoff Token

POST /api/v1/checkouts/:id/handoff/:token/consume

Returns the stored provider and billing payload and deletes the token (single use). The :id path parameter is the checkout session public ID; :token is the value from Create Handoff Token.

Response 200:

{
  "providerId": "507f1f77bcf86cd799439011",
  "billingAddress": {
    "name": "Jane Smith",
    "email": "jane@example.com",
    "line1": "123 Main St",
    "city": "Berlin",
    "postalCode": "10115",
    "country": "DE"
  },
  "createdAt": "2026-03-08T14:00:00Z"
}

Transactions

Create Transaction

POST /api/v1/transactions/create

Initiates a transaction for a checkout session. Called by the Main Frontend when the customer submits payment.

Authentication: No API key/JWT required. License enforcement applies (requests are denied when license state is BLOCKED or NOT_ACTIVATED).

Request Body:

{
  "sessionPublicId": "sess_pub_abc123xyz",
  "providerId": "507f1f77bcf86cd799439011",
  "billingAddress": {
    "name": "Jane Smith",
    "email": "jane@example.com",
    "line1": "123 Main St",
    "city": "Berlin",
    "postalCode": "10115",
    "country": "DE"
  }
}

Response 200:

{
  "transactionId": "67c8e2f7d6ef0dc8a3fa2011",
  "status": 0
}

Get Transaction Status

GET /api/v1/transactions/:id/status

Polls transaction status. Used by the success/return page to confirm payment outcome.

Response 200:

{
  "status": 1,
  "externalReference": "order_12345",
  "amount": 4900,
  "currency": "EUR",
  "returnUrl": "https://yourapp.com/success?txId={transactionId}",
  "createdAt": "2026-03-08T14:00:00Z"
}

status is a numeric transaction status code (same integer codes used elsewhere in the gateway). externalReference and returnUrl are omitted when empty.

Cancel Transaction

POST /api/v1/transactions/:id/cancel

Cancels a pending transaction (before provider capture).

Mark Transaction as Pending

POST /api/v1/transactions/:id/mark-pending

Transitions a transaction to pending_provider state. Used for asynchronous payment flows (GoCardless, Wire Transfer).


VAT Validation

Validate VAT ID

POST /api/v1/vat/validate

Validates a VAT ID via the EU VIES system. No authentication required.

Hosted checkout only calls this endpoint when the effective checkoutSettings.vatIdValidation mode resolves to vies for the current session.

Request Body:

{
  "vatId": "DE123456789"
}

Response 200:

{
  "valid": true,
  "companyName": "Example GmbH",
  "address": "Musterstraße 1, 10115 Berlin"
}

Check EU Country

GET /api/v1/vat/eu-country/:code

Returns whether a country code is an EU member state.


Customer Portal

The portal API allows buyers to self-serve invoice and subscription management. All portal endpoints except auth endpoints require a valid portal session token.

Request OTP

POST /api/v1/portal/auth/request-otp

Sends a one-time password to the customer's email address.

Request Body:

{
  "email": "jane@example.com"
}

Verify OTP

POST /api/v1/portal/auth/verify-otp

Exchanges an OTP for a portal session token.

Request Body:

{
  "email": "jane@example.com",
  "code": "123456"
}

Response 200:

{
  "token": "portal_session_token",
  "expiresAt": "2026-03-08T16:00:00Z"
}

Upon OTP verification, the backend issues a signed portal session token (opaque bearer token). It is not a JWT; treat it as an opaque credential and send it as:

Authorization: Bearer <portal_session_token>
POST /api/v1/portal/auth/magic-link

Exchanges a one-time magic-link token for the same portal session response as OTP verification. Magic-link tokens are single-use; replayed, expired, or malformed tokens return an authentication error.

Request Body:

{
  "token": "portal_magic_link_token"
}

Refresh Portal Session

POST /api/v1/portal/auth/refresh

Rotates the HTTP-only portal refresh cookie and returns a fresh portal session token. The frontend calls this endpoint when a portal API request receives 401 Unauthorized.

Logout Portal Session

POST /api/v1/portal/auth/logout

Clears the portal refresh cookie. The frontend also removes the in-memory portal bearer token.

Get Portal Session

GET /api/v1/portal/session

Returns authenticated portal metadata for UI bootstrapping.

Response 200:

{
  "email": "jane@example.com",
  "hasSubscriptions": true
}

All subsequent portal requests include:

Authorization: Bearer portal_session_token

List Documents

GET /api/v1/portal/documents

Returns portal-visible billing documents for the authenticated customer: standard invoices in draft or issued state and issued credit notes. Pro forma invoices are excluded from the document list.

Download Document PDF

GET /api/v1/portal/documents/:id/pdf?type=invoice
GET /api/v1/portal/documents/:id/pdf?type=credit-note

Returns the invoice or credit-note PDF as application/pdf. If type is omitted, the backend treats the document as an invoice.

Download E-Invoice (XML)

GET /api/v1/portal/documents/:id/einvoice?format=xrechnung

Returns the requested e-invoice XML when that format is enabled for both organization eInvoice generation and portal downloads. Supported format values are xrechnung, peppol, and zugferd; peppol returns Peppol BIS 3.0 XML generated against Peppol BIS Billing 3.0.20-hotfix, and zugferd returns standalone Factur-X/ZUGFeRD CII XML. Readiness failures return 422 EINVOICE_READINESS_FAILED. Standard invoice PDFs are downloaded through /api/v1/portal/documents/:id/pdf.

Peppol portal downloads use the seller and buyer Peppol routing addresses stored on the invoice snapshot. XRechnung and ZUGFeRD do not require Peppol routing addresses. If a Peppol snapshot is missing or invalid, fix the organization/client setup for future documents and use the admin invoice correction workflow for already issued documents. Credit notes are available through the portal as PDF documents; the portal e-invoice endpoint is invoice-only.

List Subscriptions

GET /api/v1/portal/subscriptions

Returns visible recurring subscriptions for the authenticated buyer.

Response 200:

{
  "subscriptions": [
    {
      "id": "67c8e2f7d6ef0dc8a3fa2011",
      "name": "Annual software renewal",
      "status": "cancel_requested",
      "cadence": "Every 1 year",
      "currency": "EUR",
      "nextChargeDate": null,
      "effectiveAt": "2026-09-01T00:00:00Z",
      "estimatedNextAmount": 0,
      "upcomingChargesCount": 0
    }
  ],
  "total": 1,
  "page": 1,
  "limit": 20
}

Get Subscription Upcoming Charges

GET /api/v1/portal/subscriptions/:id/upcoming?count=6

Returns the current recurring state, the next scheduled charge if billing is still active, and upcoming charge estimates. For scheduled or finalized cancellations, the response also includes the stored cancellation reason and requested timestamp when present.

Response 200:

{
  "subscriptionId": "67c8e2f7d6ef0dc8a3fa2011",
  "name": "Annual software renewal",
  "status": "active",
  "cadence": "Every 1 year",
  "currency": "EUR",
  "nextChargeDate": "2026-09-01T00:00:00Z",
  "effectiveAt": null,
  "cancellationReason": null,
  "cancellationRequestedAt": null,
  "upcoming": [
    {
      "id": "67c8e2f7d6ef0dc8a3fa2011-1",
      "scheduledDate": "2026-09-01T00:00:00Z",
      "dueDate": "2026-09-15T00:00:00Z",
      "currency": "EUR",
      "baseAmount": 149000,
      "usageAmount": 0,
      "taxEstimate": 0,
      "estimatedTotal": 149000,
      "proformaAvailable": true,
      "proformaPreviewId": "next",
      "proformaPreviewLabel": "Proforma preview"
    }
  ]
}

Download Subscription Proforma Preview PDF

GET /api/v1/portal/subscriptions/:id/upcoming/:upcomingId/proforma/pdf

Downloads the optional PDF preview for the first upcoming recurring charge when proforma previews are enabled.

Cancel Subscription

POST /api/v1/portal/subscriptions/:id/cancel

Allows a customer to cancel a recurring schedule. The operation is idempotent and uses future-cycle semantics when the schedule still has a next run date.

Request Body:

{
  "reason": "Switching to annual billing"
}

reason is optional. When provided, the backend trims the value, caps it at 500 characters, and stores it on the recurring schedule for operator records. Repeated cancellation calls keep the existing cancellation state instead of creating a second mutation.

Response 200:

{
  "subscriptionId": "67c8e2f7d6ef0dc8a3fa2011",
  "status": "cancel_requested",
  "alreadyCancelled": false,
  "effectiveAt": "2026-09-01T00:00:00Z",
  "cancellationReason": "Switching to annual billing",
  "cancellationRequestedAt": "2026-06-09T12:00:00Z",
  "message": "Subscription cancellation scheduled for future cycles"
}

Billing Requests (GoCardless)

Create Billing Request

POST /api/v1/billing-requests/create

Initiates a GoCardless billing request mandate. Called during the direct debit checkout flow.


Webhooks (Inbound)

Registered on the Main Backend HTTP root (not under /api/v1):

POST /hooks/:type/:providerId

Receives inbound webhook events from payment providers. Not called by your code — configure the full URL (including your Main API host) in the provider dashboard.

typeProvider
stripeStripe payment events
mollieMollie payment events
gocardlessGoCardless mandate and payment events
paypalPayPal order and payment events

See Webhooks & IPN for event types and payload schemas.

On this page