Hosted payment page quickstart
This guide walks you through generating a Hosted payment page (HPP) link, redirecting your customer to it, and handling the payment result. By the end, you'll have a working end-to-end HPP integration.
The HPP handles all card input, 3DS authentication, and payment processing on Centrobill's side. Card data never touches your servers.
Before you begin
Make sure you have the following:
- A Centrobill merchant account. Contact [email protected] to request access.
- Your API key (the
Authorizationheader value), available in the Merchant Portal. - A site ID or SKU name (product identifier): created in the Merchant Portal or via the Site API and SKU API respectively. You need only one of these to initiate a payment.
Note: All examples in this guide use the Stage environment at
https://stage.api.centrobill.com. Replace withhttps://api.centrobill.comwhen you're ready to go live.
How the flow works
- Your server sends a
POST /paymentPagerequest to the Gateway API with the SKU, consumer, and URL details - The gateway returns a unique one-time payment page URL
- You redirect the customer's browser to that URL
- The customer enters payment details on the Centrobill-hosted page
- If required, the customer completes 3DS authentication with their bank
- Centrobill sends the final payment status to your
ipnUrlvia IPN callback and redirects the customer to yourredirectUrl
Step 1: Generate the payment page URL
Send a POST request to /paymentPage from your server. This call requires your API key in the Authorization header.
curl --request POST \
--url https://stage.api.centrobill.com/paymentPage \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"sku": [
{
"title": "Premium Monthly",
"siteId": "983759353",
"price": [
{
"offset": "0d",
"amount": 29.99,
"currency": "USD",
"repeat": false
}
],
"url": {
"ipnUrl": "https://your-server.example.com/webhooks/centrobill",
"redirectUrl": "https://your-server.example.com/payment/success"
}
}
],
"consumer": {
"id": "user-00123",
"email": "[email protected]",
"firstName": "Jonny",
"lastName": "Sonny"
},
"payment": {
"method": ["card", "sepa"],
"selected": "card",
"secure": true
},
"ttl": 1200,
"metadata": {
"orderId": "ord_9182"
},
"emailOptions": {
"send": true
}
}'Request fields
sku (required)
The sku field is an array. Each SKU object can be defined in one of three ways:
| Approach | Required fields | When to use |
|---|---|---|
| SKU with SKU name | name, url | You have a pre-configured SKU in the Merchant Portal |
| SKU with SKU name and custom prices | name, price, url | You want to override a SKU's prices at runtime |
| SKU with site ID | siteId, price, url | You don't have a named SKU and want to define everything inline |
Each SKU object also accepts:
| Field | Description |
|---|---|
url.ipnUrl | Your IPN endpoint. Centrobill posts the final payment status here |
url.redirectUrl | The URL the customer is redirected to after payment |
title | Display title shown on the payment page |
domainName | Domain name override for the site |
xsell | Cross-sell display state: checked or unchecked |
action.type | Retry type for retrying a transaction with the same order ID after an SCA decline |
action.id | Order ID to retry |
consumer (optional)
Pre-fill customer data on the payment page. consumer.ip is required if payment.selected or payment.method are set.
| Field | Description |
|---|---|
id | Centrobill gateway consumer ID |
externalId | Your internal user ID |
email | Customer email |
firstName / lastName | Customer name |
country, state, city, address, zip | Billing address |
phone | Customer phone number |
birthday | Date of birth |
ip | Customer IP address. Required if payment.method or payment.selected are set |
deviceId | Device fingerprint |
payment (optional)
Controls which payment methods are shown and how the page behaves.
| Field | Description |
|---|---|
method | Array of payment methods to display (e.g. ["card", "sepa"]) |
selected | Payment method pre-selected when the page loads |
secure | If true, the gateway attempts 3DS verification. Defaults to true |
test | If true, processes in test mode |
terminalMode | Disables consumer tracking, one-clicks, and antifraud checks |
mid | Specific MID to route the payment through |
bin | BIN used for pre-routing decisions |
domain | Custom domain displayed in the link instead of the default |
template (optional)
Customises the appearance of the payment page.
| Field | Description |
|---|---|
language | ISO2 language code (e.g. "DE"). Determined automatically if omitted |
layout | Page layout (theme). Falls back to the default theme if omitted |
templateParameters | Key–value pairs passed to the layout |
Other fields
| Field | Description |
|---|---|
ttl | Payment page lifetime in seconds. Defaults to 600 |
metadata | Arbitrary key–value pairs attached to the transaction. Returned in the IPN |
emailOptions.send | If true, Centrobill sends a payment confirmation email to the customer |
Step 2: Handle the response
A successful request returns HTTP 201 with a single url field:
{
"url": "https://pay.centrobill.com/unique-hash"
}This is the unique, one-time payment page URL. It expires after the ttl you specified (default 600 seconds). If the customer doesn't complete payment before it expires, you'll need to generate a new URL.
Step 3: Redirect the customer
Redirect the customer's browser to the URL returned in Step 2. You can do this with a standard HTTP redirect from your server.
// Server-side redirect example (Node.js / Express)
res.redirect(paymentPageUrl);The customer lands on the Centrobill-hosted payment page, enters their payment details, and, if required, completes a 3DS challenge with their bank. Non-EU transactions and frictionless EU transactions are completed without a 3DS challenge.
Step 4: Handle the IPN callback
After the payment completes, Centrobill sends an HTTP POST to your ipnUrl with the final payment status. Don't rely on the customer returning to your redirectUrl as confirmation — always use the IPN as the source of truth.
{
"payment": {
"code": "0",
"description": "APPROVED",
"action": "charge",
"mode": "sale",
"status": "success",
"amount": 29.99,
"currency": "USD",
"orderId": "235324530",
"transactionId": "12345",
"descriptor": "centrohelp.com",
"source": {
"method": "card",
"number": "402400****6348",
"brand": "visa",
"paymentAccountId": "ae853c41-2d85-4c8a-9a61-3a5daeea311d"
}
},
"consumer": {
"id": "cb-gateway-id",
"externalId": "user-00123",
"email": "[email protected]",
"firstName": "Jonny",
"lastName": "Sonny"
},
"subscription": {
"id": "sub-abc123",
"status": "active",
"renewalDate": "2025-02-17 13:43:02",
"cancelDate": null,
"cycle": 0
},
"metadata": {
"orderId": "ord_9182"
},
"timestamp": {
"dateTime": "2025-01-17 13:43:02",
"timezone": "UTC+00.00",
"unixTime": "1737116582"
}
}Respond with HTTP 200, 201, or 202 to acknowledge receipt. Respond as quickly as possible — do any heavy processing asynchronously after acknowledging. If Centrobill doesn't receive an acknowledgement, it retries the IPN according to the documented retry schedule.
Check payment.status to determine the outcome:
payment.status | Meaning | Next action |
|---|---|---|
success | Payment approved | Provision access, save transactionId and paymentAccountId |
pending | Awaiting async confirmation | Wait for a follow-up IPN callback |
fail | Payment declined | Do not provision access |
Save the following values from the IPN — you'll need them if you want to charge the customer again without the HPP using stored data:
payment.source.paymentAccountId— the stored card identifierconsumer.id— the Centrobill gateway consumer ID
Step 5: Handle the customer redirect
After payment, Centrobill redirects the customer to your redirectUrl. Use this to show a confirmation or error page. Do not use the redirect as confirmation of payment — rely on the IPN instead, as the customer may close the browser before the redirect completes.
Before you go live
Before switching to the Production environment, complete the following steps:
- Test your integration in the Staging environment. Use synthetic payment credentials to simulate approvals, declines, and 3DS flows.
- Confirm account activation with the Merchant Support team. Your profile must be activated before production payments are processed. Contact [email protected] to confirm.
- Switch the base URL from
https://stage.api.centrobill.comtohttps://api.centrobill.comin all requests.
Troubleshooting
400 Bad Request
A required field is missing or invalid. The sku array is required. Each SKU object must include either name or siteId, and a url object with at least ipnUrl and redirectUrl.
401 Unauthorized
Your API key is missing or incorrect. Verify the Authorization header matches your key exactly as it appears in the Merchant Portal.
403 Forbidden
Your account doesn't have permission for this operation, or the request IP isn't on the allowlist. Contact Centrobill support.
Payment page URL expired
HPP URLs are short-lived. If the customer tries to use an expired link, generate a new URL and redirect them again. Increase ttl in your request, if customers regularly fail to complete payment within the default 600 seconds.
Customer returned to redirectUrl but IPN hasn't arrived
The IPN is delivered asynchronously and may arrive slightly after the redirect. Don't provision access immediately on redirect, wait for the IPN with payment.status = "success" before fulfilling the order.
payment.status is pending
Some flows, particularly 3DS, resolve asynchronously. Wait for the follow-up IPN callback before fulfilling the order.
