Download OpenAPI specification:
API for depositing and withdrawal
You can easily and securely process payments from your customers using either the:
The Payments API helps you to process payments of your customers using a variety of payment methods and a single API Endpoint.
Merchants can also access your transaction analytics and manage accounts within the merchant portal.
All requests must use HTTPS. Authentication is achieved using an API Key, passed headers, namely X-Api-Key.
Get your API and Secret Keys
The API’s use a dedicated Merchant API key for all requests. You can create an API under the merchant portal.
The API’s can be generated under Settings - Credentials
We use HTTP statuses for our response as per the HTTP specification
| Status range | Description |
|---|---|
| 2xx | indicates a successful request |
| 4xx | indicates there is a problem with the client's request |
| 5xx | indicates there is a problem with our servers/infrastructure. In this case it is our responsibility to fix the issue |
If you receive a 4xx HTTP status response, it is safe to retry the request after fixing the root cause of the problem (either your request parameters or your account configuration).
If you receive a 5xx HTTP status response, please contact our support with the request information so we can investigate.
Gateway specific codes
For a 400 Bad Request we will provide specific codes and descriptions in the body of the response.
| Error code | Message |
|---|---|
| 1009 | User hasn't confirm bank details yet |
| 1016 | Credential not found |
| 1018 | Transaction ID is invalid |
| 1021 | Transaction ID is missing |
| 1025 | An error has occurred. Please try again later. |
| 1026 | API Key is missing |
| 1027 | API Key not found |
| 1028 | API Key has expired |
| 1036 | Mode is not valid. Please use 'test' or 'prod' mode. |
| 1037 | Tracking Id is missing |
| 1039 | This transaction does not exists in our database |
| 1051 | Email is missing |
| 1052 | Country Code is missing |
| 1062 | User Id is missing |
| 1063 | First name is missing |
| 1064 | Last name is missing |
| 1065 | Phone Country is invalid. Use ISO 3166-1 alpha-2 codes |
| 1066 | Phone number is missing |
| 1067 | Prefix number is missing |
| 1068 | Missing Body |
| 1069 | Currency is missing |
| 1070 | This currency is not supported |
| 1074 | IP is missing |
| 1075 | Amount is required and should be greater than 0 |
| 1076 | You can't change this transaction |
| 1086 | KYC status is invalid |
| 1089 | Client Transaction ID is missing |
| 1094 | Max withdrawal limit has been reached for today |
| 1095 | Provider ID is missing |
| 1106 | Beneficiary name is missing |
| 1107 | Bank name is missing |
| 1116 | You have reached your daily deposit limit |
| 1117 | You have reached your weekly deposit limit |
| 1118 | You have reached your monthly deposit limit |
| 1121 | DOB is missing |
| 1122 | Address is missing |
| 1123 | City is missing |
| 1124 | Zip Code is missing |
| 1129 | You can't cancel this transaction |
| 1130 | Min. withdrawal limit is {{amount}} |
| 1142 | Transaction is already processed |
| 1153 | Invalid Date |
| 1174 | Max. deposit limit for this provider is {{amount}} {{currency}} |
| 1175 | Min. deposit limit for this provider is {{amount}} {{currency}} |
| 1177 | Max. user deposit for today is {{amount}} {{currency}} |
| 1178 | Min. user deposit is {{amount}} {{currency}} |
| 1179 | Max. user deposit is {{amount}} {{currency}} |
| 1187 | Provider Id is required |
| 1200 | Domain is not allowed |
| 1208 | The provided email has invalid format |
| 1215 | Invalid Exp. date |
| 1216 | Your KYC needs to be approved |
| 1228 | DOB format is wrong |
| 1229 | Your Webhook URL is not available at this time |
| 1230 | Card Number is required |
| 1231 | CVC is required |
| 1232 | Exp. month is required |
| 1233 | Exp. year is required |
| 1234 | Invalid Card Number |
| 1235 | Invalid CVC |
| 1236 | Routing Id is required |
| 1237 | Holder Name is required |
| 1276 | This user is restriced to access this provider |
| 1282 | Maximum difference between from and to dates must be 7 days |
| 1295 | Your IP is blocked |
| 1305 | You can't use these credentials because your account has been deleted |
| 1306 | S2S is not activated on this account |
| 1329 | Provider has been disabled |
| 1384 | You're using production credentials but the mode is test |
| 1385 | You're using sandbox credentials but the mode is prod |
| 1387 | This provider isn't configured to support payouts |
| 1388 | This provider isn't supported for S2S payouts |
| 1389 | Cardholder name format is invalid |
| 1411 | Multiple transactions match this id. Send the transaction_id instead |
| 1412 | {{field}} must be a text value |
| 1413 | {{field}} is too long. Maximum {{max}} characters |
| 1414 | Country code is invalid. Use ISO 3166-1 alpha-2 codes |
Error response format
Validation errors are nested under error:
{
"error": {
"code": 1178,
"message": "Min. user deposit is 10.00 EUR",
"data": "Min. user deposit is 10.00 EUR",
"params": { "amount": "10.00", "currency": "EUR" }
}
}
Messages that quote a limit are built from a template, so match on code and read the values
from params rather than parsing the message text.
API key failures are answered by the authentication layer in a different shape, without a code:
{ "status": false, "error": { "message": "API Key is missing" } }
All failures use HTTP 400, authentication failures included.
Text fields are checked for shape as well as presence. A field you leave out stays optional - these rules apply to what you do send.
Type. A value must be text. A number is accepted and read as text, so a numeric zip code or
phone number is fine. An object, an array, a boolean or a non-finite number is rejected with
1412, naming the field in error.params.field.
Length. Values are trimmed, then measured. Over the limit is rejected with 1413, which
reports the field and its maximum in error.params.
| Field | Maximum |
|---|---|
| user_id, tracking_id | 100 |
| first_name, last_name | 100 |
| 100 | |
| address, city | 100 |
| zip_code | 20 |
| phone.number | 20 |
| phone.prefix | 5 |
Email. customer.email must be a valid address; a malformed one is rejected with 1208.
Country. customer.country_code must be a two-letter ISO 3166-1 alpha-2 code and must be a
real country - a well-formed code that does not exist, such as FF, is rejected with 1414.
Send XX when the country is genuinely unknown; it is accepted and resolved later.
customer.phone.country follows the same rules but reports 1065.
Normalisation. Values are stored trimmed, with country codes upper-cased. The cleaned values are what appear on the hosted page, on webhooks and on the transaction endpoints, so a name sent with stray spaces comes back without them.
Every hosted page can be shown in en, de, fr, es, tr or ru. Set
request.language when you create the checkout. A regional form is reduced to its base
language, so fr-CA and fr_CA both give French, and an unsupported value falls back to
English rather than failing the request.
Send language: "auto" to use the language the player's browser asks for, read from its
Accept-Language header. The header is never read unless you ask for it this way, so a partner
that sends no language keeps English for every player.
Test accounts allow you to test and process API transactions that mirror the production environment.
Payment transactions processed in the Test environment are executed on a simulator. To create a test payments call the URL does not change. You will just need to ensure you use a DEV API key which can be created under Settings – Credentials
When integrating with our system, you will receive webhooks every time the status of a transaction changes. These webhooks are a convenient way to stay up to date with the latest information about your transactions in real-time. If your webhook URL is temporarily inaccessible when we send notifications, our system will automatically retry every five minutes, up to a maximum of 15 attempts.
Below is an example of the payload you will receive in these webhooks:
{
"transaction_id": "bbds7128hdha",
"user_id": "123",
"tracking_id": "kshdhay6381623",
"status": "successful",
"currency": "EUR",
"amount": "200.00",
"transaction_type": "withdrawal",
"provider": "simulator",
"rejected_reason": "Insufficient funds"
}
A card deposit carries the card it was paid with:
{
"transaction_id": "i2izognxw9jtoai",
"user_id": "123",
"tracking_id": "6062e803-a99e-4263-9a17-5c4ef9fc809d",
"status": "successful",
"currency": "GBP",
"amount": "20.00",
"transaction_type": "deposit",
"provider": "paysafe",
"card_details": {
"masked_number": "51676797****3951",
"expiry": "02/2029",
"holder_name": "Samantha Mary Paul",
"type": "Mastercard",
"fingerprint": "95f3f7589d68c380061ce6d295038cc92df9bf3b683bc27cc9a26a07da725775"
}
}
Webhook Payload Explanation
Webhook Signature
New fields are only ever appended to the payload; existing fields never change or move. The signature covers the whole body, so verify it over the raw request string rather than over re-serialised JSON.
To ensure the integrity and authenticity of the data in these webhooks, it's crucial to verify the included signature. This guide explains how to verify the webhook signature generated by our system. When you receive a webhook, it will include an "x-signature" header in the HTTP request. To generate signature you must use the SHA-1 hashing algorithm. Update the hash with the payload, and then convert it to a hexadecimal representation in uppercase.
Signature sample (NodeJs):
const crypto = require("crypto");
const data = /* Data object from the webhook payload */;
const signaturePassword = /* Your secret signature password that can be find in BACK OFFICE under Credentials page */;
const payloadForHash = JSON.stringify(data) + signaturePassword;
const localSignature = crypto
.createHash("sha1")
.update(payloadForHash)
.digest("hex")
.toUpperCase();
Example:
payload =
{
"transaction_id":"r21nmrtpcmrcava",
"user_id":"1111222",
"tracking_id":"b8f04416-116a-11ed-861d-0242ac120002",
"status":"rejected",
"currency":"GBP",
"amount":"200.00",
"transaction_type":"withdrawal"
}
signature_password = spg_test_companyxxxxQyGAheyMqcHVmp8ZMQtkYcev27sCu7RF
Calculated Hash: "5FDDA8F46411C132DCFBEE53C39BA06298CB48BC"
This endpoint facilitates an all in one cashier, this will provide a one time integration solution that will show all the available providers.
The Origin of the call must be registered against your account under Settings - Domains.
An unregistered origin is rejected with 1200 (Domain is not allowed).
Validation errors are returned as:
{
"error": {
"code": 1070,
"message": "This currency is not supported...",
"data": "This currency is not supported..."
}
}
Messages that quote a limit also carry the substituted values under error.params.
API key failures are answered by the authentication layer in a different shape, with no code:
{ "status": false, "error": { "message": "API Key is missing" } }
All failures use HTTP 400, including authentication ones.
A test (sandbox) API key may only create test transactions and a production key only prod
transactions. A mismatch is rejected with 1384 or 1385 before anything else is validated.
amount is only validated when amount_restricted is true. With the flag absent or false
the player chooses the amount on the hosted page, and none of the amount checks below run -
they are applied on the page instead.
When amount_restricted is true the amount must be greater than 0 (1075) and is checked
against your account minimum and maximum (1178 / 1179) and the player's daily, weekly and
monthly deposit limits (1116 / 1117 / 1118).
| x-api-key required | string Example: api_key |
object |
{- "request": {
- "mode": "test",
- "theme": "dark",
- "language": "de",
- "settings": {
}, - "user_id": "128",
- "tracking_id": "fb832194-34e1-4e6c-8494-d88034cf3e47",
- "ip": "127.34.125.54",
- "amount": 10.05,
- "currency": "EUR",
- "amount_restricted": true,
- "customer": {
- "max_deposit_limit": 1000,
- "first_name": "John",
- "last_name": "Doe",
- "kyc_status": "passed",
- "email": "user@example.com",
- "zip_code": "12345",
- "address": "123 Main Street",
- "city": "New York",
- "dob": "05/03/2000",
- "country_code": "GB",
- "phone": {
- "country": "GB",
- "number": 783433252,
- "prefix": 44
}
}
}
}{- "token": "Mtg4OakI0YSGdHPY1y4vUnGLOaMxnJJZ9BX09LQ1u3yft0OY81"
}This endpoint facilitates Direct Integration payments, This hosted checkout allows users to be redirected directly to the payment provider for processing. You will need to specify the provider ID which you can find under settings - providers.
The Origin of the call must be registered against your account under Settings - Domains.
An unregistered origin is rejected with 1200 (Domain is not allowed).
Validation errors are returned as:
{
"error": {
"code": 1070,
"message": "This currency is not supported...",
"data": "This currency is not supported..."
}
}
Messages that quote a limit also carry the substituted values under error.params.
API key failures are answered by the authentication layer in a different shape, with no code:
{ "status": false, "error": { "message": "API Key is missing" } }
All failures use HTTP 400, including authentication ones.
provider_id is required (1187). The provider must be active on your account: a disabled or
deleted credential is rejected with 1329, and a player excluded from that provider with 1276.
Providers can also carry their own deposit limits, checked after your account limits:
1174 (above the provider maximum) and 1175 (below the provider minimum).
Unlike the hosted checkout, first_name, last_name and email are always required here, even when
the customer details step is enabled on your account.
| x-api-key required | string Example: api_key |
object |
{- "request": {
- "mode": "test",
- "language": "de",
- "provider_id": 210,
- "settings": {
}, - "user_id": "128",
- "tracking_id": "fb832194-34e1-4e6c-8494-d88034cf3e47",
- "ip": "127.34.125.54",
- "amount": 10.05,
- "currency": "EUR",
- "customer": {
- "max_deposit_limit": 1000,
- "first_name": "John",
- "last_name": "Doe",
- "kyc_status": "passed",
- "email": "user@example.com",
- "zip_code": "12345",
- "address": "123 Main Street",
- "city": "New York",
- "dob": "05/03/2000",
- "country_code": "GB",
- "phone": {
- "country": "GB",
- "number": 783433252,
- "prefix": 44
}
}
}
}This endpoint facilitates Server-to-Server (S2S) payments, providing a straightforward integration process. Below, you will find details on its implementation. Upon successful invocation, the response will include two key attributes: url and transaction_status. Check the url on the response; if it is not empty, redirect the user to complete the 3DS process. Additionally, if the transaction_status is rejected, an error attribute will accompany the response.
The Origin of the call must be registered against your account under Settings - Domains.
An unregistered origin is rejected with 1200 (Domain is not allowed).
Validation errors are returned as:
{
"error": {
"code": 1070,
"message": "This currency is not supported...",
"data": "This currency is not supported..."
}
}
Messages that quote a limit also carry the substituted values under error.params.
API key failures are answered by the authentication layer in a different shape, with no code:
{ "status": false, "error": { "message": "API Key is missing" } }
All failures use HTTP 400, including authentication ones.
S2S is off by default. If it has not been switched on for your account the call is rejected with
1306 before anything else is checked - contact your account manager to have it enabled.
The card is validated before the payment is attempted: holder_name (1237) must contain no
digits (1389) and is trimmed of repeated whitespace, card_number (1230) must pass the card
number check (1234), cvc (1231 / 1235), and exp_month / exp_year (1232 / 1233) must form a
valid expiry no more than 10 years in the future (1215).
first_name, last_name and email are always required here, even when the customer details step
is enabled on your account.
| x-api-key required | string Example: api_key |
object |
{- "request": {
- "mode": "test",
- "language": "de",
- "routing_id": 210,
- "settings": {
}, - "user_id": "U123",
- "tracking_id": "fb832194-34e1-4e6c-8494-d88034cf3e47",
- "ip": "127.34.125.54",
- "amount": 10.05,
- "currency": "EUR",
- "customer": {
- "max_deposit_limit": 1000,
- "first_name": "John",
- "last_name": "Doe",
- "kyc_status": "passed",
- "email": "user@example.com",
- "zip_code": "12345",
- "address": "123 Main Street",
- "city": "New York",
- "dob": "05/03/2000",
- "country_code": "GB",
- "phone": {
- "country": "GB",
- "number": 783433252,
- "prefix": 44
}
}, - "card_details": {
- "holder_name": "John Doe",
- "card_number": "4111111111111111",
- "cvc": "444",
- "exp_month": "05",
- "exp_year": "2025"
}
}
}{- "url": "{{url}}",
- "transaction_status": "pending"
}This endpoint facilitates an all in one cashier for withdrawals. This will provide a one time integration solution that will show all the available payout providers. You can configure the payout providers in Settings - Provider Rules
The Origin of the call must be registered against your account under Settings - Domains.
An unregistered origin is rejected with 1200 (Domain is not allowed).
Validation errors are returned as:
{
"error": {
"code": 1070,
"message": "This currency is not supported...",
"data": "This currency is not supported..."
}
}
Messages that quote a limit also carry the substituted values under error.params.
API key failures are answered by the authentication layer in a different shape, with no code:
{ "status": false, "error": { "message": "API Key is missing" } }
All failures use HTTP 400, including authentication ones.
amount is always required and must be greater than 0 (1075). It is checked against the minimum
withdrawal configured on your API key (1130, which quotes the limit) and the player's daily
withdrawal total (1094).
The bank_details block is only used when beneficiary_name is present; without that field the
whole block is ignored and the player is asked for their details on the hosted page as usual.
When this endpoint returns an error it also posts a rejected webhook to your status_url, with
an empty transaction_id, so a failed call is reported twice: once in the HTTP response and once
on the webhook.
| x-api-key required | string Example: xxxx |
object |
{- "request": {
- "mode": "test",
- "theme": "dark",
- "language": "de",
- "settings": {
}, - "user_id": "128",
- "tracking_id": "fb832194-34e1-4e6c-8494-d88034cf3e47",
- "ip": "127.34.125.54",
- "amount": 10.05,
- "currency": "EUR",
- "customer": {
- "first_name": "John",
- "last_name": "Doe",
- "kyc_status": "passed",
- "email": "user@example.com",
- "zip_code": "12345",
- "address": "123 Main Street",
- "city": "New York",
- "dob": "05/03/2000",
- "country_code": "GB",
- "phone": {
- "country": "GB",
- "number": 783433252,
- "prefix": 44
}
}, - "bank_details": {
- "beneficiary_name": "John Doe",
- "bank_name": "Bank of Example",
- "account_type": "savings",
- "account_number": "1234567890",
- "iban": "ME25505000012345678951",
- "swift": "EXAMPLEXXX",
- "sort_code": "12-34-56",
- "bank_branch_code": "001",
- "ifsc": "SBIN0001234",
- "bank_code": "1234",
- "bank_city": "London",
- "bank_province": "Greater London",
- "pix_account": "email@example.com",
- "cpf_number": "123.456.789-00"
}
}
}{- "token": "Mtg4OakI0YSGdHPY1y4vUnGLOaMxnJJZ9BX09LQ1u3yft0OY81",
- "tracking_id": "fb832194-34e1-4e6c-8494-d88034cf3e47"
}Processes a payout server-to-server using bank details and an explicit provider_id, without showing the hosted cashier. .
The S2S payout supports 3 different approval modes. You have to contact your account manager so it can be configured for you:
default — Uses our built-in approval logic.automatic — Always dispatched to the provider immediately. All approval checks are skipped.manual — Always queued with status pending. Must be approved via the back office or /v1/withdrawal/approve.A pending transaction_status in the response means the payout has been queued; any other value reflects the immediate provider result.
The Origin of the call must be registered against your account under Settings - Domains.
An unregistered origin is rejected with 1200 (Domain is not allowed).
Validation errors are returned as:
{
"error": {
"code": 1070,
"message": "This currency is not supported...",
"data": "This currency is not supported..."
}
}
Messages that quote a limit also carry the substituted values under error.params.
API key failures are answered by the authentication layer in a different shape, with no code:
{ "status": false, "error": { "message": "API Key is missing" } }
All failures use HTTP 400, including authentication ones.
Only Turbo Havale, LuqaPay Havale and Nixxe Simulator can be used. A provider that is
not one of those is rejected with 1388, and a provider that is not configured for payouts at
all with 1387.
beneficiary_name (1106) and bank_name (1107) are always required. Which of the remaining
fields are needed depends on the provider and the destination country.
amount must be greater than 0 (1075) and is checked against the minimum withdrawal on your API
key (1130) and the player's daily withdrawal total (1094). kyc_status is required when your account is
configured to check KYC (1086).
| x-api-key required | string Example: xxxx API key for authentication |
object |
{- "request": {
- "mode": "prod",
- "user_id": "128",
- "tracking_id": "fb832194-34e1-4e6c-8494-d88034cf3e47",
- "ip": "127.34.125.54",
- "currency": "EUR",
- "amount": 100,
- "provider_id": "330",
- "customer": {
- "first_name": "John",
- "last_name": "Doe",
- "kyc_status": "passed",
- "email": "user@example.com",
- "zip_code": "12345",
- "address": "123 Main Street",
- "city": "New York",
- "dob": "05/03/2000",
- "country_code": "GB",
- "phone": {
- "country": "GB",
- "number": 783433252,
- "prefix": 44
}
}, - "bank_details": {
- "beneficiary_name": "John Doe",
- "bank_name": "Bank of Example",
- "account_type": "savings",
- "account_number": "12345678",
- "iban": "GB33BUKB20201555555555",
- "swift": "BUKBGB22",
- "sort_code": "12-34-56",
- "bank_branch_code": "001234",
- "ifsc": "SBIN0001234",
- "bank_code": "1234",
- "bank_city": "London",
- "bank_province": "Greater London",
- "pix_account": "email@example.com",
- "cpf_number": "123.456.789-00"
}
}
}{- "transaction_id": "abc123xyz456789",
- "transaction_status": "successful"
}If there are any pending payouts, this endpoint can be used to reject them from the client side.
transaction_id accepts either your own tracking_id or the gateway transaction_id. Your
tracking id is matched first. Because a tracking id is not guaranteed to be unique, a value that
matches more than one transaction is refused with 1411 rather than acting on an arbitrary one -
resend the request using the gateway transaction_id, which is always unique.
A payout can only be rejected while the gateway still holds it. The request is refused with 1129
once the payout has been sent to the provider - that is, once it has been processed or has a
provider transaction id - or once it has reached a final status.
1142 is different from 1129: it means a back-office operator is working on the payout right
now (approving it, or changing its payment method). Nothing was changed, and the request can be
retried shortly.
| x-api-key required | string Example: xxxx API key for authentication |
| transaction_id required | string Either your own |
{- "transaction_id": "fb832194-34e1-4e6c-8494-d88034cf3e47"
}{- "message": "Withdrawal has been rejected successfully"
}If there are any pending payouts, this endpoint can be used to approve them from the client side.
transaction_id accepts either your own tracking_id or the gateway transaction_id. Your
tracking id is matched first. Because a tracking id is not guaranteed to be unique, a value that
matches more than one transaction is refused with 1411 rather than acting on an arbitrary one -
resend the request using the gateway transaction_id, which is always unique.
The payout must still be waiting for approval; one that is not is refused with 1076. A payout
that has already been sent to the provider, or that a back-office operator is working on at that
moment, is refused with 1142.
For providers that require the player to confirm their bank details, a payout whose details are
still unconfirmed is refused with 1009.
| x-api-key required | string Example: xxxx API key for authentication |
| transaction_id required | string Either your own |
{- "transaction_id": "fb832194-34e1-4e6c-8494-d88034cf3e47"
}{- "message": "Transaction Withdrawal has been approved successfully",
- "transaction_status": "pending"
}This endpoint can be used to get the latest infromation regarding a specific transaction.
A transaction that failed on the provider side may be reported as failed. A transaction that
is still on its way may report a value other than the ones listed, so treat any status you do
not recognise as still in progress rather than final.
| id required | string Unique transaction id in your system |
| x-api-key required | string Example: xxxx API key for authentication |
{- "transaction_status": "rejected",
- "rejected_reason": "Insufficient funds"
}This endpoint retrieves transactions. You can specify a date range using from and to query parameters. If no date range is specified, it will return transactions for the current date. Maximum range between dates it’s 7 days
Both from and to must be supplied together; if either is missing the current day is returned.
Dates use DD-MM-YYYY; an unparseable value is rejected with 1153 and a range wider than seven
days with 1282.
Every transaction that is still in progress is reported as pending on this endpoint.
| from | string Example: from=01-08-2024 (optional) The start date for the date range in DD-MM-YYYY format. |
| to | string Example: to=01-08-2024 (optional) The end date for the date range in DD-MM-YYYY format. |
| x-api-key required | string Example: xxxx API key for authentication |
[- {
- "transaction": {
- "date": "2024-07-05 11:53:25",
- "type": "deposit",
- "status": "pending",
- "transaction_id": "g7xp8kudinz3tyi",
- "tracking_id": "sh7gv8knfxpktgh"
}, - "provider": {
- "provider": "nixxe_simulator",
- "provider_name": "Nixxe Systems",
- "provider_id": "sh7gv8knfxpktgh",
- "amount": {
- "value": 8.56,
- "currency": "GBP"
}, - "credited_amount": {
- "value": 10,
- "currency": "EUR"
}, - "fx": {
- "value": 10,
- "currency": "EUR"
}
}, - "customer": {
- "customer_id": 123,
- "first_name": "John",
- "last_name": "Doe",
- "dob": "1985-05-20",
- "country": "US",
- "tags": [
- "Premium",
- "Trusted"
], - "IP": "192.168.0.1"
}
}
]