Guides
Integration Guides
Step-by-step workflows with sequence diagrams for the most common payment integration patterns.
The most common integration pattern: create a checkout session server-side, redirect your customer to the PaymentHooks-hosted page, and receive a webhook confirmation once the payment succeeds. Your server never handles raw card data, keeping you outside PCI scope.
- 1Create a checkout session server-side by calling POST /v1/checkout-sessions with the amount, currency, and redirect URLs.
- 2Return the session_url from the API response and redirect your customer's browser to it.
- 3The customer is presented with the PaymentHooks-hosted payment page and enters their card details.
- 4PaymentHooks tokenises the card and sends an authorisation request to the selected gateway.
- 5On success, PaymentHooks fires a payment.succeeded webhook to your configured endpoint.
- 6Verify the webhook signature, fulfil the order, and update your database.
- 7The customer is automatically redirected to your success_url.
const session = await paymentHooks.checkoutSessions.create({amount: 5000, // in smallest currency unit (e.g. cents)currency: 'usd',success_url: 'https://example.com/success?session_id={{CHECKOUT_SESSION_ID}}',cancel_url: 'https://example.com/cancel',metadata: { order_id: 'ord_123' },});// Redirect the customerres.redirect(303, session.url);
Tokenization lets you securely store a customer's card for future charges without ever passing raw card numbers through your servers. Create a setup session, let the customer enter their card, and receive a reusable payment method token.
- 1Create a setup session via POST /v1/setup-sessions, passing the customer ID and a return URL.
- 2Redirect the customer to the setup_url — they enter their card once on the hosted form.
- 3PaymentHooks tokenises the card through the gateway's network tokenization service.
- 4A payment_method token (pm_...) is created and attached to the customer record.
- 5You receive a setup.completed webhook containing the payment_method ID.
- 6Store the payment_method ID in your database alongside the customer.
- 7For future charges call POST /v1/payments with payment_method: 'pm_...' — no re-entry required.
// Retrieved pm_... from the setup.completed webhookconst payment = await paymentHooks.payments.create({amount: 2499,currency: 'usd',customer: 'cus_abc123',payment_method: 'pm_xyz789',confirm: true,});
The subscription lifecycle covers product and price creation, customer onboarding, automatic invoicing on each billing cycle, dunning logic for failed renewals, and graceful cancellation. PaymentHooks handles the scheduling — your server reacts to webhook events.
- 1Create a Product (POST /v1/products) representing what you sell, e.g. 'Pro Plan'.
- 2Create a Price (POST /v1/prices) attached to the product with interval (month/week/year) and unit_amount.
- 3Create a Customer (POST /v1/customers) — store the returned customer ID in your database.
- 4Create a Subscription (POST /v1/subscriptions) linking the customer to the price. Required fields: customerId, priceId. Optional: gatewayConnectionId, trialEndAt, metadata.
- 5PaymentHooks creates the subscription in active status, computes the first billing period from the price interval, and dispatches subscription.created.
- 6On each billing cycle, PaymentHooks auto-generates an invoice and charges the default gateway.
- 7Handle invoice.paid to provision access and invoice.payment_failed to trigger dunning (retry emails).
- 8After max retries, subscription moves to past_due; handle subscription.cancelled to revoke access.
// 1. Create product & price (run once during setup)const price = await paymentHooks.prices.create({productId: 'prod_abc',amount: 2900,currency: 'usd',interval: 'month',});// 2. Subscribe the customerconst subscription = await paymentHooks.subscriptions.create({customerId: 'cus_abc123',priceId: price.id,trialEndAt: '2026-07-22T00:00:00.000Z',metadata: { plan: 'pro' },});
Strong Customer Authentication (SCA) regulations in the EU and UK require 3D Secure challenges for many card transactions. PaymentHooks detects when a challenge is required and surfaces an action_required status with a redirect URL — your integration handles this with a single conditional redirect.
- 1Initiate a payment via POST /v1/payments with confirm: true and your return_url.
- 2If 3DS is not required, the payment succeeds immediately — handle the payment.succeeded webhook.
- 3If 3DS is required, the response returns status: 'action_required' and next_action.redirect_url.
- 4Redirect your customer's browser to the redirect_url — PaymentHooks handles the 3DS flow.
- 5After the customer completes the challenge, they are redirected back to your return_url.
- 6Query GET /v1/payments/:id or rely on the payment.succeeded / payment.failed webhook to confirm outcome.
- 7Never assume success based on the redirect alone — always verify via the API or webhook.
const payment = await paymentHooks.payments.create({amount: 8500,currency: 'eur',payment_method: 'pm_xyz789',confirm: true,return_url: 'https://example.com/payment/complete',});if (payment.status === 'action_required') {// Redirect customer to complete 3DS challengeres.redirect(303, payment.next_action.redirect_url);}