Server-to-Server Processing
The Payment API used in this guide performs authorization and capture in a single step. If you need to separate authorization from capture, use the Authorize API followed by the Capture API instead.
This guide gives you a step-by-step instruction to get started:
- How to access your API credentials
- How to authenticate to the API
- How to create a Payment API request
- How to receive postback notifications (webhooks)
1. Accessing your API credentials
Contact your onboarding manager to get access to the Dashboards, where you will find your API credentials for authentication.
After logging in, navigate to My Company to find your Integration Data and API Passwords.
| Environment | Dashboard | API Base URL |
|---|---|---|
| Test | https://testdashboard.betterpayment.de | https://testapi.betterpayment.de |
| Production | https://dashboard.betterpayment.de | https://api.betterpayment.de |
Start your integration with the Test environment. Once validated, you will be granted access to Production.
2. Authentication
Before making any API requests, make sure you have your API Key and API Password from the API credentials above available.
Basic Authentication
The API uses Basic Authentication, a simple and widely supported authentication method built into the HTTP protocol.
With Basic Auth, the system making the request sends an authorization header that includes the word Basic followed by a space and a Base64-encoded string in the format: username:password.
In this case:
username → your API Key
password → your API Password
For example, to authorize as demo / p@55w0rd, then the encoded header would look like this:
Authorization: Basic ZGVtbzpwQDU1dzByZA==
You don’t need to calculate the Base64 string manually — most HTTP libraries (such as curl, Postman, or your SDK) handle it automatically.
Content-Type Headers
All API requests use Basic Authentication and must include the following HTTP header:
Content-Type: application/json
Every request that sends data (for example, POST or PUT) must include a valid JSON body.
3. Idempotency
Our API supports idempotency to ensure safe retries of requests without unintended side effects. To use this feature, include a unique UUID in one of the following HTTP headers when making POST requests:
X-Idempotency-Key
Idempotency-Key
When a request is received with an idempotency key, the response is cached for 1 hour. Subsequent requests with the same idempotency key within this timeframe will return the cached response, preventing duplicate operations.
Best Practice: We recommend using RFC 4122 compliant UUIDs (version 4) for idempotency keys.
POST https://{testapi|api}.betterpayment.de/rest/payment
Authorization: Basic <base64(api_key:api_password)>
Content-Type: application/json
Idempotency-Key: 9d8f5715-2e7c-4e64-8e34-35f510c12e66
{
"payment_type": "cardecom",
"order_id": "12345678",
"amount": "15.90",
"currency": "EUR",
"additional_transaction_data": "customer_id=123ABC, billing_info=12345678",
"postback_url": "https://your-postback.url.com",
"success_url": "https://your-success.url.com",
"error_url": "https://your-error.url.com",
"card_number": "4761070000000509",
"card_holder": "John Doe",
"card_cvv": "196",
"card_expiry_month": "12",
"card_expiry_year": "2026"
}
4. Create a Payment API request
All requests must:
- Use HTTPS
- Include the Authorization header (with Basic Auth)
- Include the
Content-Type: application/jsonheader if you are sending data - Use valid test or production URLs depending on your environment
The Server-to-Server Processing integration allows merchants or processors to send payment data directly to the Payment API without redirection to a payment page.
Example: Card ECOM
In the following example your system receives cardholder data (PAN, CVV, expiry date, cardholder name) and sends it directly to our API.
This integration requires that you have the required PCI DSS compliance, since cardholder data is handled directly by your infrastructure.
Payment API Request
payment_typeStringrequiredcardecomorder_idStringrequiredamountFloatrequiredcurrencyStringrequiredpostback_urlStringrequiredsuccess_urlStringrequirederror_urlStringrequiredcard_numberStringrequiredcard_holderStringrequiredcard_cvvStringrequiredcard_expiry_monthStringrequiredcard_expiry_yearStringrequiredadditional_transaction_dataStringpostback_url as part of the postback data.POST /rest/payment
Authorization: Basic <base64(api_key:api_password)>
Content-Type: application/json
{
"payment_type": "cardecom",
"order_id": "12345678",
"amount": "15.90",
"currency": "EUR",
"postback_url": "https://your-postback.url.com",
"success_url": "https://your-success.url.com",
"error_url": "https://your-error.url.com",
"card_number": "4761070000000509",
"card_holder": "John Doe",
"card_cvv": "196",
"card_expiry_month": "12",
"card_expiry_year": "2026"
}
Implementation Flow
- Make a Payment API request with card data.
- Receive API response.
- If the response contains a
client_action, handle it accordingly:postForm: Build a form on your frontend and POST thefieldsfromaction_datato the providedurl. This redirects the customer to the 3DS authentication page.redirect: Redirect the customer to theurlinaction_data.
- After 3DS is completed, the customer is returned to your
success_urlorerror_url. - Receive asynchronous postback notification to
postback_urlwith the final transaction status.
Payment API Response
Direct Response (with own MPI)
When threeds_authentication_value and threeds_directory_server_trans_id are provided in the request, the gateway uses the merchant's 3DS results and returns a direct response:
transaction_idStringpayment_typeStringstatus_codeIntegerstatusStringorder_idStringmessageStringadditional_transaction_dataStringpostback_url as part of the postback data.amountFloatincluded_feesStringerror_codeInteger{
"transaction_id": "938834bc-769f-44e7-ab25-da9aeaad5346",
"payment_type": "cardecom",
"status_code": 3,
"status": "completed",
"order_id": "12345678",
"message": null,
"additional_transaction_data": "",
"amount": 15.90,
"included_fees": "0.00",
"error_code": 0
}
3DS Required Response (without own MPI)
When no 3DS authentication values are provided, the gateway triggers its own 3DS flow. The response will have status: "pending" and a client_action that the merchant must handle:
client_actionStringaction_data) or redirect (redirect to the url in action_data). When not returned, no client-side action is required.action_dataObjectclient_action is specified. Contains: url (target URL of the action) and, in case of a postForm, fields (key/value pairs of the data to be posted).{
"transaction_id": "25634b4d-c3dd-4242-afe3-e7962c33138c",
"payment_type": "cardecom",
"status_code": 2,
"status": "pending",
"order_id": "12345678",
"message": null,
"additional_transaction_data": null,
"amount": 15.90,
"included_fees": "0.00",
"error_code": 0,
"client_action": "postForm",
"action_data": {
"url": "https://3ds-acs-url.example.com/v1/acs/challenge-initiate",
"fields": {
"creq": "eyJ0aHJlZURTU2VydmVyVHJ..."
}
}
}
This example shows a minimal request. For the complete list of supported parameters (billing address, recurring payments, and more), see the Payment API Reference. For integration details on other payment methods, see Payment Methods.
5. Receive postback notifications
After a transaction is processed, the API will send asynchronous HTTP POST notifications (postbacks) to the postback_url you provided in the payment request. This is how your system stays informed about the final result of each transaction — even if the customer does not return to your website.
Payment Postback — Completed
transaction_idStringpayment_typeStringstatus_codeIntegerstatusStringorder_idStringmessageStringremittance_infoStringwallet_activity_referenceStringwallet_account_referenceStringpayer_locationStringadditional_transaction_dataStringamountFloatincluded_feesStringexternal_transaction_idStringchecksumString{
"transaction_id": "d1bf9fdf-7268-406f-9e08-8d5a9540ab97",
"payment_type": "wero",
"status_code": 3,
"status": "completed",
"order_id": "12345678",
"message": "CAPTURE SETTLED",
"remittance_info": "12345678 - Test Shop",
"wallet_activity_reference": "WARf47ac10b58cc",
"wallet_account_reference": "WAC50000aW12",
"payer_location": "DE",
"additional_transaction_data": "customer_id=123ABC, billing_info=12345678",
"amount": 15.90,
"included_fees": "0.00",
"external_transaction_id": "0I66TOoXap2bNLZ2m89tm1",
"checksum": "73a93b8a2d5260f592d98e386c4e5784ee551d1c"
}
Payment Postback — Declined
transaction_idStringpayment_typeStringstatus_codeIntegerstatusStringorder_idStringmessageStringreason_codeStringwallet_activity_referenceStringwallet_account_referenceStringpayer_locationStringadditional_transaction_dataStringamountFloatincluded_feesStringchecksumString{
"transaction_id": "bfe9cff7-8cd9-4976-9236-21253c1f40c1",
"payment_type": "wero",
"status_code": 6,
"status": "declined",
"order_id": "123010",
"message": "CAPTURE REJECTED",
"reason_code": "AC01",
"wallet_activity_reference": "WARf47ac10b58cc",
"wallet_account_reference": "WAC50000aW12",
"payer_location": "DE",
"additional_transaction_data": "customer_id=123ABC, billing_info=12345678",
"amount": 10.00,
"included_fees": "0.00",
"checksum": "d56fe31a1a38e06337672ca781e4cb6f3b83fd11"
}
For retry policy and signature verification, see Postbacks.