Supported billing engines
Payrails works with any billing engine that:- Creates invoices for subscription charges
- Sends invoice lifecycle webhooks (for example, “invoice ready to pay”)
- Exposes an API to record external payments against invoices
User journeys
- Sign-up and first payment
- Manage payment instruments
- Renewals and MITs
- Dunning and recovery
End-user experience:
- Pay with a preferred payment method, whether card or local payment method
- Your billing engine creates a customer and subscription and generates an invoice.
- Payrails Drop-in or Elements collects and stores a payment instrument.
- Your backend records the successful payment in your billing engine and links the stored instrument for future renewals.

Integration details
This guide uses a fictional subscription business called Needle & Groove. The examples are in TypeScript, but the API calls apply in any language.Understand the identifiers
Align these identifiers across your frontend, backend, Payrails, and billing engine:holderReference: Your customer identifier. Make sure your billing engine contains a reference from the customer object to this identifier.invoiceId: The invoice you need to pay (created by your billing engine).paymentInstrumentId: The stored Payrails instrument to charge for renewals.paymentId: ThePayrailspayment transaction identifier for an attempt. Store it against the invoice to reconcile billing-engine invoice attempts with Payrails outcomes.merchantReference: A unique identifier for the payment attempt. A common choice isinvoiceIdplus the attempt number.
25.00 for €25.00) and use ISO 4217 currencies.
Set up server-side Payrails access
Make Payrails API calls from your server and keep credentials off the client.
Use these Payrails docs to set up authentication and mutual TLS:
The server endpoints in this guide follow this recommended pattern:
POST /api/payrails/initcallsPayrailsPOST /merchant/client/initusing mTLS + OAuth.POST /api/payrails/executioncallsPayrailsPOST /merchant/workflows/{workflowCode}/executions.GET /api/payrails/instruments?holderReference=...lists instruments for a customer.
Accept the first subscription payment
This guide creates the invoice in your billing engine first. Then initializes Payrails with the invoice amount and collect a payment method. Authorize the payment first and only create the invoice once you are sure a payment has been successful to not have unused subscriptions.- Create a subscription and invoice in your billing engine
invoiceIdamountcurrency
TypeScript
Python
Java
- Initialize the Payrails Web SDK (server-side)
TypeScript
Python
Java
- Mount Drop-in or Elements (client-side)
- Read the Payrails Web SDK overview
- Use Drop-in for a pre-built payment UI:
- Use Elements for individual UI building blocks
onSuccess handler triggers the backend to do two things:
- Resolve the stored
paymentInstrumentIdand attach it to the billing providercustomer - Record the successful payment against the invoice in your billing engine
Achieve the same result by using webhooks with
Payrails and waiting for a successful payment. Ensure all information required by the handler is included as meta for that execution.Record the payment in your billing engine
After Payrails authorization succeeds, record the external payment against your invoice. Some billing engines support this logic for failed payments as well. At minimum, your billing engine update typically:- Marks the invoice as paid (or records a successful attempt)
- Associates a “default payment method” reference with the customer for renewals
- Stores the Payrails
paymentInstrumentIdandholderReferenceto charge it off-session
Example: Record a successful payment (adapter shape)
Use a backend endpoint that takes your invoice fields plus the Payrails instrument reference. This page shows adapter-shaped examples. In your integration, implement these endpoints in your own backend:POST /api/stripe/record-payment(creates a payment method with metadata and records a payment)POST /api/chargebee/record-payment(offline collection example shape)
TypeScript
Python
Java
- Store
instrumentIdon the customer (or payment method) - Record the invoice payment using your billing engine’s external payments API
Run renewals and off-session attempts
For renewals, your billing engine typically emits a webhook when an invoice is ready to be paid. Your backend then:- Loads invoice details (amount, currency,
holderReference,paymentInstrumentId) - Calls Payrails to execute an off-session payment attempt
- Records the attempt result back into the billing engine
Example: Billing engine webhook handler
Your billing-engine webhook handler typically:- Verifies webhook signatures
- Retrieves the invoice and associated details
- Calls
POST /api/payrails/execution - Reports the outcome back into the billing engine
Create a workflow execution (server-side)
Expose a server endpoint that creates a Payrails workflow execution (a thin wrapper around PayrailsPOST /merchant/workflows/{workflowCode}/executions).
To learn more about creating executions, read the Payrails Create a workflow execution overview.
TypeScript
Python
Java
Implement retries and dunning
Define who owns the retry schedule:- If your billing engine schedules retries, record each attempt result and wait for the next webhook.
- If your billing engine does not schedule retries, schedule attempts in your backend (job queue or cron).
- One billing-engine attempt triggers one Payrails workflow execution
- One Payrails execution can include multiple cascaded provider attempts (managed by Payrails)
Manage instruments
Use Payrails as your source of truth for instruments.- List instruments for a customer:
TypeScript
Python
Java
- Delete an instrument:
TypeScript
Python
Java
Implementation checklist
- Decide billing integration model: 3rd party billing engine or in‑house. Confirm event model and available webhooks
- Pilot scope and KPIs: Select one or two markets, define first‑payment vs renewal KPIs, baseline metrics, and success thresholds
- Provisioning and security: Create Payrails workspace, set up mTLS credentials, create default test workflow, connect first PSP in sandbox
- Webhooks and events: Configure invoice and payment events from the engine (e.g., invoice.created, invoice.finalized, payment_intent.succeeded/failed) and Payrails outcome webhooks
- Signup and first payment flow: Integrate Payrails Elements/Drop‑in for tokenization, associate instrument to customer in billing engine, call charge API, handle callbacks
- Renewals (MIT) setup: Store instrument IDs, set correct COF/MIT flags, implement renewal charge path from engine invoice notifications
- Customer portal flow: Update instrument IDs, see payment history, generate payment links
- Dunning ownership: Define email cadence and retry schedule. Wire Payrails attempt outcomes to engine or backend retry logic
- Routing configuration: Start with market‑based routing, enable failover and smart retries. Add BIN, brand, and method rules as needed
- Payment methods and geography: Enable required APMs and local acquiring per pilot markets; verify SCA and exemptions policy
- Reporting and reconciliation: Build unified payments view. Map Payrails events to ERP/finance systems for settlement and invoice matching
- Go‑live checklist: Production credentials, webhook signatures verified, idempotency keys, error handling and retries tested, monitoring and alerts configured


