Skip to main content
This guide shows how to pair a billing engine with Payrails for sign-up, renewals, retries, and instrument management.

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
Examples include an in-house billing engine or third-party systems such as Stripe, Chargebee, Metronome, Recurly, Lago, and others.

User journeys

End-user experience:
  • Pay with a preferred payment method, whether card or local payment method
Recommended approach:
  1. Your billing engine creates a customer and subscription and generates an invoice.
  2. Payrails Drop-in or Elements collects and stores a payment instrument.
  3. Your backend records the successful payment in your billing engine and links the stored instrument for future renewals.
Sequence diagram of signup and first payment: the customer pays with the Payrails SDK, the server creates the customer and subscription in the billing engine, then attaches the instrument and records the payment

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: The Payrails payment 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 is invoiceId plus the attempt number.
In Payrails, represent amounts in major units strings (for example, 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/init calls Payrails POST /merchant/client/init using mTLS + OAuth.
  • POST /api/payrails/execution calls Payrails POST /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.
  1. Create a subscription and invoice in your billing engine
Return at least these fields to your frontend:
  • invoiceId
  • amount
  • currency
Example request to your billing engine adapter:
TypeScript
Python
Java
  1. Initialize the Payrails Web SDK (server-side)
Call your backend to create a Payrails client session.
TypeScript
Python
Java
  1. Mount Drop-in or Elements (client-side)
Use the Payrails init response to mount payment UI: Your onSuccess handler triggers the backend to do two things:
  • Resolve the stored paymentInstrumentId and attach it to the billing provider customer
  • 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 paymentInstrumentId and holderReference to 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)
Example request body:
TypeScript
Python
Java
If you use a different billing engine, keep the same intent:
  • Store instrumentId on 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:
  1. Loads invoice details (amount, currency, holderReference, paymentInstrumentId)
  2. Calls Payrails to execute an off-session payment attempt
  3. 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
Adapt the same pattern to your billing engine’s webhook format and security model.

Create a workflow execution (server-side)

Expose a server endpoint that creates a Payrails workflow execution (a thin wrapper around Payrails POST /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).
Keep the mapping simple:
  • 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.
  1. List instruments for a customer:
TypeScript
Python
Java
  1. Delete an instrument:
TypeScript
Python
Java
If your customer portal allows changing the default payment method, update your billing engine’s default reference and keep the Payrails instrument link on the billing-engine side.

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
Last modified on September 28, 2026