In many cases, using one of the plugins provided by your payment service provider is the fastest way to integrate. This page contains the information to integrate with our APIs directly.
The API is only accessible using HTTPS and is secured using TLS (SSL). We support TLS 1.2 and newer. Older versions of SSL and TLS are vulnerable and not supported.
API clients must authenticate themselves for each request to the API. We have implemented this using HTTP Basic Authentication. The username is the supplied system-to-system API key; the password remains empty. Basic Authentication is implemented using the “Authorization” header:
Authorization: Basic aHVudGVyMjo=
Most HTTP clients support Basic Authentication out of the box and do not require manual construction of the Authorization header.
However, if your HTTP client does not support basic authentication, you can obtain the value after "Basic" by encoding the API key, followed by a colon, using the Base64 algorithm.
For example, the API key hunter2
followed by :
will result in the string aHVudGVyMjo=
.
Example requests using curl to perform Basic Authentication
</> Out-of-the-box
curl -X GET \
--user 'hunter2:' \
https://api.example.com/v1/merchants/self/projects/self/
</> Manual
curl -X GET \
--header 'Authorization: Basic aHVudGVyMjo=' \
https://api.example.com/v1/merchants/self/projects/self/
The API can respond with the following HTTP status codes:
CODE | DEFINITION | EXAMPLE |
---|---|---|
200 | Ok | |
201 | Created | |
400 | Bad request | Used when the request is invalid |
401 | Unauthorized | |
403 | Forbidden | Used when the request is not allowed |
404 | Not found | Used when the resource could not be found |
500 | Internal server error | Indicates that there is a problem why we could not serve the request |
502 | Bad gateway | Can be triggered when the unreachable |
503 | Service Unavailable | Can be triggered when the system is down |
504 | Gateway Timeout | Can be triggered when the system does not respond in time |
The hosted payment page (HPP) solution manages the customer redirections that are required in the checkout process and gives the option to use secure hosted payment pages. This significantly reduces the burden of compliance with PCI DSS for the merchant as they don't need to store sensitive cardholder information. The following is a basic transaction where the cardholder will select a payment method on the HPP:
POST /v1/orders/ HTTP/1.1
Authorization: Basic aHVudGVyMjo=
Content-Type: application/json
{
"currency": "EUR",
"amount": 995,
"description": "Example description",
"merchant_order_id": "TEST001",
"return_url": "https://www.example.com/",
"failure_url": "https://www.example.com/failure/",
"customer": {
"locale": "nl"
}
}
Please refer to the Mandatory Fields and Optional Fields below for what each one means and allowed values.
A response will be send by the server, which includes a URL (order_url
) where the cardholder will need to be redirected to by the webshop.
{
"currency": "EUR",
"amount": 995,
"description": "Example description",
"merchant_order_id": "TEST001",
"return_url": "https://www.example.com/",
"failure_url": "https://www.example.com/failure/",
"customer": {
"locale": "nl"
},
"id": "1c969951-f5f1-4290-ae41-6177961fb3cb",
"created": "2016-07-04T11:41:57.121017+00:00",
"modified": "2016-07-04T11:41:57.183822+00:00",
"order_url": "https://api.example.com/pay/1c969951-f5f1-4290-ae41-6177961fb3cb/",
"status": "new"
}
All payment methods that have been approved and enabled for the webshop will be shown to the cardholder. Once the customer has completed the transaction, they will be redirected to the submitted return_url
(or the failure_url
if provided and if order status is cancelled
, expired
or error
).
In case you only want to offer the shopper a subset of available payment methods, you can limit the payment methods by specifying an allow list: payment_methods
.
Example order request that is limited to (credit) card and Vipps Mobilepay:
POST /v1/orders/ HTTP/1.1
Authorization: Basic aHVudGVyMjo=
Content-Type: application/json
{
"currency": "EUR",
"amount": 995,
"description": "Example description",
"merchant_order_id": "TEST001",
"payment_methods": ["credit-card", "vipps-mobilepay"],
"customer": {
"locale": "nl"
}
}
To change the order in which the payment methods are displayed on the hosted payment page, you can use the payment_methods
field. Please note that Apple Pay and Google Pay are always displayed on top of the list.
Example order request that places Vipps Mobilepay before the (credit) card option:
POST /v1/orders/ HTTP/1.1
Authorization: Basic aHVudGVyMjo=
Content-Type: application/json
{
"currency": "EUR",
"amount": 995,
"description": "Example description",
"payment_methods": ["apple-pay", "vipps-mobilepay", "credit-card"]
}
Please contact your PSP to activate this feature.
You can cancel an order and transactions at different stages of the payment process.
FIELD NAME | DESCRIPTION, POSSIBLE VALUES AND FORMAT |
---|---|
currency |
Currency in ISO 4217 alphabetic code format, e.g. EUR, GBP, USD, NOK, SEK. |
amount |
All amounts are in cents. For example the amount of 12.95 needs to be sent as 1295. |
FIELD NAME | DESCRIPTION, POSSIBLE VALUES AND FORMAT |
---|---|
merchant_order_id |
The order ID that will be stored. |
return_url |
URL where cardholder will be redirected to once the transaction has been completed. If not provided, the customer will be redirected to page at eCommerce Payment Gateway and unless you make use of the webhook, your webshop won't be able to know if there are any updates on the transaction status. |
failure_url |
URL where cardholder will be redirected to once the transaction has been completed and the status is cancelled, expired or error. If not provided, the customer will be redirected to page at eCommerce Payment Gateway and unless you make use of the webhook, your webshop won't be able to know if there are any updates on the transaction status. |
locale |
This locale will be used to determine the language of the hosted payment page. Possible values are: • en-GB • de-DE • nl-NL • nl-BE • fr-BE • sv-SE • no-NO • da-DK |
description |
A description of the order that will be stored. |
payment_methods |
If you let the customer select the payment method (e.g. credit card or Vipps Mobilepay) in your shop environment or want to define the payment type yourself, transmit the parameter payment_methods. If you do not submit this parameter, the payment gateway will display a drop-down menu to the customer to choose from the payment methods available for your shop. |
webhook_url |
The URL that will be used for the webhook. |
expiration_period |
It is optional to set an expiration_period , which will expire the payment page after a fixed duration. |
The API has the concept of orders and transactions. An order represents the shopper's order or shopping basket, while the transaction represents the financial consequences of this order. The merchants should only refer to the order status and ignore the transaction status.
Via the GET /v1/orders/order-id/
endpoint you can always get the latest order status. To ensure you do not miss a status update we advise to use the following mechanisms.
new
, processing
). The frequence of checking should be determined by your business. If for example you reserve tickets for a concert for 15 minutes, then the status check should be completed within this time frame.The status of an order can be determined by sending an HTTP GET request to /orders/<order_id>/
. The API will respond with an overview of the order and its transactions.
STATUS | DESCRIPTION | FINAL |
---|---|---|
new | Order has been created in the database. | no |
processing | All transactions in the order are either pending or processing. | no |
error | Order processing failed due to technical reasons or due to transaction processing failure. | yes |
completed | All transactions in the order are either accepted or completed; merchant can deliver the goods. | yes |
cancelled | All transactions in the order are cancelled. | yes |
expired | Order has expired (e.g. payment link where customer fails to follow the link within a certain period). | yes |
Example of a (credit) card order that is still being processed:
GET /v1/orders/4c6afd74-a840-4aab-b411-1e6e0636d341/ HTTP/1.1
Authorization: Basic aHVudGVyMjo=
Response:
{
"amount": 100,
"client": {
"user_agent": "Testing API"
},
"created": "2020-10-14T13:15:12.613044+00:00",
"currency": "EUR",
"description": "Example order #1",
"id": "4c6afd74-a840-4aab-b411-1e6e0636d341",
"last_transaction_added": "2020-10-14T13:15:12.650161+00:00",
"modified": "2020-10-14T13:15:13.815621+00:00",
"return_url": "http://www.example.com",
"status": "new",
"transactions": [
{
"amount": 100,
"balance": "internal",
"created": "2020-10-14T13:15:12.650161+00:00",
"credit_debit": "credit",
"currency": "EUR",
"description": "Example order #1",
"events": [
{
"event": "new",
"id": "3cb2259b-a3f9-4908-bb98-eb51c773fc70",
"noticed": "2020-10-14T13:15:12.812215+00:00",
"occurred": "2020-10-14T13:15:12.650161+00:00",
"source": "set_status"
}
],
"expiration_period": "PT30M",
"id": "e3ed069e-c931-40ae-8035-e022e8a4e5e7",
"modified": "2020-10-14T13:15:13.913284+00:00",
"payment_method": "credit-card",
"payment_url": "https://api.example.com/redirect/e3ed069e-c931-40ae-8035-e022e8a4e5e7/to/payment/",
"status": "new"
//...
}
]
}
Example of a successful (credit) card order:
GET /v1/orders/4c6afd74-a840-4aab-b411-1e6e0636d341/ HTTP/1.1
Authorization: Basic aHVudGVyMjo=
Response:
{
"amount": 100,
"client": {
"user_agent": "Testing API"
},
"completed": "2020-10-13T07:16:44.959162+00:00",
"created": "2020-10-13T07:16:35.402150+00:00",
"currency": "EUR",
"description": "Example order #1",
"id": "4c6afd74-a840-4aab-b411-1e6e0636d341",
"last_transaction_added": "2020-10-13T07:16:39.757385+00:00",
"modified": "2020-10-14T01:03:17.811770+00:00",
"order_url": "https://api.example.com/pay/e19b9594-85ce-4177-a002-36d30a47d948/",
"status": "completed",
"transactions": [
{
"amount": 100,
"balance": "internal",
"completed": "2020-10-13T07:33:07.154914+00:00",
"created": "2020-10-13T07:16:39.757385+00:00",
"credit_debit": "credit",
"currency": "EUR",
"description": "Example order #1",
"events": [
//...
],
"expiration_period": "PT30M",
"id": "058cf70d-7a84-4957-941c-532c065cef72",
"modified": "2020-10-14T01:03:17.761187+00:00",
"payment_method": "credit-card",
"status": "completed"
//...
}
]
}
In some cases, the consumer does not return to the webshop (in the case of bank transfer, the payment will always be decoupled), and another way of checking the current status of the order needs to be used. It is possible to periodically retrieve the order and check whether the status was changed, but this is inefficient and an unnecessary stress on resources when real-time feedback is required.
To solve this, webhooks can be used. A webhook is a callback (HTTP POST) to a merchant-supplied URL (the "webhook handler"). The URL is configurable per project in the webhook_url
field. The order ID and project ID are available in the body of the request. Our platform makes the request whenever the status of an order changes.
We recommend you have a backup process in place to retrieve the status of open orders.
In certain cases, a webhook call might get delayed or not arrive at all. We recommend implementing a background process that updates all orders, older than 10 minutes (or any other period that suits your business), that haven't transitioned to a final status yet.
Example webhook from eCommerce Payment Gateway to http://www.example.com/webhook
:
POST /webhook HTTP/1.1
Host: www.example.com
Content-Type: application/json
{
"event": "status_changed",
"order_id": "4c6afd74-a840-4aab-b411-1e6e0636d341",
"project_id": "b5f39273-44e7-4385-8e08-44612ef3e117"
}
Webhooks can be configured on project level, but can be overwritten for a specific order by supplying a webhook URL when creating the order. For this specific order the specific webhook URL will be used. This is part of the order schema:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Order",
"type": "object",
"properties": {
"id": {
"description": "Order identifier",
"type": "string",
"readOnly": true
},
"webhook_url": {
"description": "Used for transaction updates",
"type": "string",
"format": "uri"
}
}
}
When a call to the webhook handler results in a failure, delivery will be retried. Examples of failures:
If our platform is unable to deliver the message for the 10th time, delivery is stopped. The retries are two minutes apart. The connect and read timeout for the first attempt is 4 seconds, and for the subsequent attempts the timouet is 10 seconds.
Test credentials can be easily obtained by creating an account. After creation you can login to our admin portal and view your API key under Settings > API Key.
A project can be set to test mode by setting its status to active-testing
. In test mode, all payments are made against a sandbox environment and do not incur any charges. You can have projects that are permanently in test mode; useful for test and acceptance environments, for example.
POST /v1/merchants/self/projects/ HTTP/1.1
Authorization: Basic MWZiYWZjNzViMjEwNGRmYjk4MmVlNTRjOWZlNDNlOGU=
Content-Type: application/json
{
"trade_name": "Trade Name",
"description": "Project Description",
"status": "active-testing",
"website_url": "https://www.example.com/",
"webhook_url": "https://www.example.com/webhook/"
}