NAV Navbar

Overview

This is a developer zone. Ladies and gentlemen kindly fasten your seat belts and note that this is a non-smoking flight. Sit-back and enjoy your flight. Thank you for choosing Postpay!

Authentication

Create credentials

echo -n '{merchant_id}:{sk_live}' | base64

Request

GET / HTTP/1.1
Host: api.postpay.io
Authorization: Basic {credentials}

HTTP Basic authentication is the simplest way of interacting with the Postpay API.

The credentials is the base64 encoding of your merchant id and your live secret key joined by a single colon {merchant_id}:{sk_live}.

Data types

Media types

Request

GET /orders HTTP/1.1
Accept: application/vnd.postpay+json; version=v1

Custom media types are used in the API to choose the format of the data you wish to receive. This is done by customizing the Accept header when you make a request.

Accept: application/vnd.postpay+{format}; version={version}

Pagination

Request

GET /orders?page={page}&page_size={page_size} HTTP/1.1

Response

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
    "count": 1000,
    "next": "https://api.postpay.io/orders?page=6",
    "previous": "https://api.postpay.io/orders?page=4",
    "results": [
    ]
}

Requests that return multiple items will be paginated to 20 items by default. You can specify further pages with the {page} parameter and you can also set a custom page size up to 50 with the {page_size} parameter.

GET
/orders?page={page}&page_size={page_size}
Field Description
next Link for the immediate next page.
previous Link for the immediate previous page.
count Total number of items matching the request.

Testing

Learn about the different methods to test your integration before going live.

Endpoints

Authentication

The credentials is the base64 encoding of your merchant id and your test secret key joined by a single colon {merchant_id}:{sk_test}.

SMS code

On Sandbox environment Postpay does not send any SMS, use the last 4 digits of the phone number to verify it.

Test cards

You can use any of the following test cards to simulate a successful payment:

Brand Number CVC Date
VISA 4111 1111 1111 1111 Any 3 digits Any future date
MasterCard 5555 5555 5555 4444 Any 3 digits Any future date
American Express 3782 8224 6310 005 Any 3 digits Any future date
Discover 6011 1111 1111 1117 Any 3 digits Any future date

SDKs

Postpay has official libraries for different programming languages:

Checkout

Workflow

Checkout Workflow

  1. The user selects Postpay as payment method.
  2. The server creates a new checkout to obtain the redirect_url to redirect the user.
  3. User is redirected to Postpay checkout.
  4. Once the checkout is pre-approved, the user is redirected back to the provided confirmation_url appending the order_id and the order status (options areAPPROVED, DENIED or CANCELLED).
  5. If the order is APPROVED, the server will perform a request to capture the prepayment.
  6. The user is redirected to a success/failure page.

Create a checkout

Request

POST /checkouts HTTP/1.1
Content-Type: application/json

{
  "order_id": "order-01",
  "total_amount": 81480,
  "tax_amount": 3880,
  "currency": "AED",
  "shipping": {
    "id": "shipping-01",
    "name": "Express Delivery",
    "amount": 2000,
    "address": {
      "first_name": "John",
      "last_name": "Doe",
      "phone": "+971 50 000 0000",
      "alt_phone": "800 239",
      "line1": "The Gate District, DIFC",
      "line2": "Level 4, Precinct Building 5",
      "city": "Dubai",
      "state": "Dubai",
      "country": "AE",
      "postal_code": "00000"
    }
  },
  "billing_address": {
    "first_name": "John",
    "last_name": "Doe",
    "phone": "+971 50 000 0000",
    "alt_phone": "800 239",
    "line1": "The Gate District, DIFC",
    "line2": "Level 4, Precinct Building 5",
    "city": "Dubai",
    "state": "Dubai",
    "country": "AE",
    "postal_code": "00000"
  },
  "customer": {
    "id": "customer-01",
    "email": "john@postpay.io",
    "first_name": "John",
    "last_name": "Doe",
    "gender": "male",
    "account": "guest",
    "date_of_birth": "1990-01-20",
    "date_joined": "2019-08-26T09:28:14.790Z"
  },
  "items": [
    {
      "reference": "sku-01",
      "name": "Wild Flower Eau de Parfum (50ml)",
      "description": "It’s a windswept bouquet with a spring awakening.",
      "url": "https://www.example.ae/wild-flower.html",
      "image_url": "https://www.example.ae/wild-flower.jpg",
      "unit_price": 84000,
      "qty": 1
    }
  ],
  "discounts": [
    {
      "code": "return-10",
      "name": "Returning customer 10% discount",
      "amount": 8400
    }
  ],
  "merchant": {
    "confirmation_url": "https://www.example.ae/success",
    "cancel_url": "https://www.example.ae/cancel"
  }
}

Response

HTTP/1.1 201 CREATED
Content-Type: application/vnd.api+json

{
    "token": "83eee160fb08471fa46de1b1121fb27e",
    "expires": "2023-05-05T06:59:28.924329Z",
    "redirect_url": "https://checkout.postpay.io/83eee160fb08471fa46de1b1121fb27e?needs_email=False",
    "reference": "c10a871cba414fcda0f29aeac8d0c543"
}
POST
/checkouts
Parameter Type Description
order_id String❗️ Unique order ID.
total_amount Decimal❗️ Total total amount of the order, including tax and any discounts.
tax_amount Decimal❗️ Total tax amount after all discounts have been applied.
currency Currency❗️ ISO 4217 order currency.
num_instalments Integer Optionally, you can set a number of instalments within your payment options. If this value is set, the customer will not be able to edit it during the checkout process.
shipping Shipping❗️ Shipping information.
billing_address Address Billing address.
customer Customer❗️ Information about the liable customer of the order.
items Item[]❗️ A list of item objects.
discounts Discount[] A list of discount objects.
merchant Merchant The merchant configuration.
metadata Key/Value Pairs Any metadata to be passed into checkout.

⚬ Address

{
    "first_name": "John",
    "last_name": "Doe",
    "phone": "+971 50 000 0000",
    "alt_phone": "800 239",
    "line1": "The Gate District, DIFC",
    "line2": "Level 4, Precinct Building 5",
    "city": "Dubai",
    "state": "Dubai",
    "country": "AE",
    "postal_code": "00000"
}
Parameter Type Description
first_name String❗️ First name.
last_name String❗️ Last name.
phone String Phone number.
alt_phone String Alternative phone number.
line1 String❗️ Street address.
line2 String Apartment, suite, floor, etc.
city String❗️ City name.
state String State or Region.
country Country❗️ ISO 3166 alpha-2 country code.
postal_code String ️ Postal code.

⚬ Shipping

{
    "id": "shipping-01",
    "name": "Express Delivery",
    "amount": 2000,
    "address": {},
}
Parameter Type Description
id String Shipping option ID.
name String❗️ Shipping name.
amount Decimal❗️ Total shipping amount, excluding tax.
address Address❗️ Shipping address.

⚬ Customer

{
    "id": "customer-01",
    "email": "john@postpay.io",
    "first_name": "John",
    "last_name": "Doe",
    "gender": "male",
    "account": "guest",
    "date_of_birth": "1990-01-20",
    "date_joined": "2019-08-26T09:28:14.790Z",
    "default_address": {}
}
Parameter Type Description
id String Customer ID.
email String❗️ A valid email address.
first_name String First name.
last_name String Last name.
gender String Gender, options are male, female, other.
account String Account type, options are new, existing, guest.
date_of_birth String The customer date of birth ISO 8601.
date_joined String A datetime designating when the account was created ISO 8601.
default_address Address Customer default address.

⚬ Item

{
    "reference": "sku-01",
    "name": "Wild Flower Eau de Parfum (50ml)",
    "description": "It’s a windswept bouquet with a spring awakening.",
    "url": "https://www.example.ae/wild-flower.html",
    "image_url": "https://www.example.ae/wild-flower.jpg",
    "unit_price": 84000,
    "qty": 1
}
Parameter Type Description
reference String❗️ Item number, SKU or similar.
name String❗️ Name of the product.
description String Description of the product.
url URL Item's description page URL.
image_url URL Item's image URL.
unit_price Decimal❗️ Item price, excluding tax and discounts.
qty Integer❗ Item quantity.

⚬ Discount

{
    "code": "return-10",
    "name": "Returning customer 10% discount",
    "amount": 8400
}
Parameter Type Description
code String❗️ Discount code.
name String Name of the discount.
amount Decimal❗️ Discount amount, excluding tax.

⚬ Merchant

{
    "confirmation_url": "https://www.example.ae/success",
    "cancel_url": "https://www.example.ae/cancel"
}
Parameter Type Description
confirmation_url URL❗️ URL that the customer is sent to if they successfully complete the checkout process. The order_id and status=APPROVED will be sent to this URL as a HTTP query parameter in order to capture the order.
cancel_url URL❗️ URL that the customer is sent to if the payment process is cancelled. A status will be sent to this URL as a HTTP query parameter, options are CANCELLED, DENIED.

Capture

Request

POST /orders/{order_id}/capture HTTP/1.1

Response

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "order_id": "order-01",
  "status": "captured",
  "status_changed": "2020-05-08T10:58:04.095618Z",
  "total_amount": 81480,
  "tax_amount": 3880,
  "currency": "AED",
  "created": "2020-05-08T10:53:57.095579Z",
  "shipping": {
    "id": "shipping-01",
    "name": "Express Delivery",
    "amount": 2000,
    "address": {
      "first_name": "John",
      "last_name": "Doe",
      "phone": "+971 50 199 8853",
      "alt_phone": "800 239",
      "line1": "The Gate District, DIFC",
      "line2": "Level 4, Precinct Building 5",
      "city": "Dubai",
      "state": "Dubai",
      "country": "AE",
      "postal_code": "00000"
    }
  },
  "billing_address": {
    "first_name": "John",
    "last_name": "Doe",
    "phone": "+971 50 199 8853",
    "alt_phone": "800 239",
    "line1": "The Gate District, DIFC",
    "line2": "Level 4, Precinct Building 5",
    "city": "Dubai",
    "state": "Dubai",
    "country": "AE",
    "postal_code": "00000"
  },
  "customer": {
    "id": "customer-01",
    "email": "john@postpay.io",
    "first_name": "John",
    "last_name": "Doe",
    "gender": "male",
    "account": "guest",
    "date_of_birth": "1990-01-20",
    "date_joined": "2019-08-26T09:28:14.790Z"
  },
  "items": [
    {
      "reference": "sku-01",
      "name": "Wild Flower Eau de Parfum (50ml)",
      "description": "It’s a windswept bouquet with a spring awakening.",
      "url": "https://www.example.ae/wild-flower.html",
      "image_url": "https://www.example.ae/wild-flower.jpg",
      "unit_price": 84000,
      "qty": 1
    }
  ],
  "discounts": [
    {
      "code": "return-10",
      "name": "Returning customer 10% discount",
      "amount": 8400,
    }
  ]
}

Once the checkout is approved, the user is redirected back to the provided confirmation_url appending the order_idto capture the order with Postpay's API.

POST
/orders/{order_id}/capture
Parameter Type Description
order_id String❗️ Unique order ID.

Capture errors

HTTP Status Code Error Code Description
409 invalid_status Order status must be approved.
402 capture_error Payment transaction declined.
410 expired The capture has expired.

Orders

This API is used to query all previously created orders and check the status: pending, approved, captured or denied.

List orders

Request

GET /orders HTTP/1.1

Response

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "order_id": "order-01",
      "status": "captured",
      "status_changed": "2020-05-08T10:58:04.095618Z",
      "total_amount": 81480,
      "tax_amount": 3880,
      "currency": "AED",
      "created": "2020-05-08T10:53:57.095579Z"
    }
  ]
}
GET
/orders
Filter Type Lookups Example
order_id String exact, in /orders?order_id=order-01
status String exact, in /orders?status__in=captured,denied
total_amount Decimal exact, gt, lt, gte, lte /orders?total_amount__gte=10050
currency Currency exact, in /orders?currency=AED
created Datetime exact, gt, lt, gte, lte, date, year, month, week_day, day, hour /orders?created__date__gt=2020-05-20
Order by Type Example
total_amount Decimal /orders?ordering=total_amount
created Datetime /orders?ordering=-created

Get single order

Request

GET /orders/{order_id} HTTP/1.1

Response

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "order_id": "order-01",
  "status": "captured",
  "status_changed": "2020-05-08T10:58:04.095618Z",
  "total_amount": 81480,
  "tax_amount": 3880,
  "currency": "AED",
  "created": "2020-05-08T10:53:57.095579Z",
  "shipping": {
    "id": "shipping-01",
    "name": "Express Delivery",
    "amount": 2000,
    "address": {
      "first_name": "John",
      "last_name": "Doe",
      "phone": "+971 50 199 8853",
      "alt_phone": "800 239",
      "line1": "The Gate District, DIFC",
      "line2": "Level 4, Precinct Building 5",
      "city": "Dubai",
      "state": "Dubai",
      "country": "AE",
      "postal_code": "00000"
    }
  },
  "billing_address": {
    "first_name": "John",
    "last_name": "Doe",
    "phone": "+971 50 199 8853",
    "alt_phone": "800 239",
    "line1": "The Gate District, DIFC",
    "line2": "Level 4, Precinct Building 5",
    "city": "Dubai",
    "state": "Dubai",
    "country": "AE",
    "postal_code": "00000"
  },
  "customer": {
    "id": "customer-01",
    "email": "john@postpay.io",
    "first_name": "John",
    "last_name": "Doe",
    "gender": "male",
    "account": "guest",
    "date_of_birth": "1990-01-20",
    "date_joined": "2019-08-26T09:28:14.790Z"
  },
  "items": [
    {
      "reference": "sku-01",
      "name": "Wild Flower Eau de Parfum (50ml)",
      "description": "It’s a windswept bouquet with a spring awakening.",
      "url": "https://www.example.ae/wild-flower.html",
      "image_url": "https://www.example.ae/wild-flower.jpg",
      "unit_price": 84000,
      "qty": 1
    }
  ],
  "discounts": [
    {
      "code": "return-10",
      "name": "Returning customer 10% discount",
      "amount": 8400,
    }
  ]
}
GET
/orders/{order_id}
Parameter Type Description
order_id String❗️ Unique order ID.

Refunds

Refunds API allows you to refund the entire captured amount or part of the captured amount. Partial and multiple refunds are supported when the sum of all refunds is less than or equal to the total captured amount.

List refunds

Request

GET /orders/{order_id}/refunds HTTP/1.1

Response

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "refund_id": "refund-01",
      "amount": 12050,
      "full": false,
      "description": "Item returned by user",
      "created": "2020-05-09T11:20:04.311723Z"
    }
  ]
}
GET
/orders/{order_id}/refunds
Filter Type Lookups Example
refund_id String exact, in /refunds?refund_id=refund-01
description String contains, icontains, startswith, istartswith, endswith, iendswith, regex, iregex /refunds?description__contains=@
amount Decimal exact, gt, lt, gte, lte /refunds?amount__gte=10050
created Datetime exact, gt, lt, gte, lte, date, year, month, week_day, day, hour /refunds?created__year=2020
Order by Type Example
amount Decimal /refunds?ordering=amount
created Datetime /refunds?ordering=-created

Get single refund

Request

GET /orders/{order_id}/refunds/{refund_id} HTTP/1.1

Response

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "refund_id": "refund-01",
  "amount": 12050,
  "full": false,
  "description": "Item returned by user",
  "created": "2020-05-09T11:20:04.311723Z"
}
GET
/orders/{order_id}/refunds/{refund_id}
Parameter Type Description
order_id String❗️ Unique order ID.
refund_id String❗️ Unique refund ID.

Create a refund

Request

POST /orders/{order_id}/refunds HTTP/1.1
Content-Type: application/json

{
  "refund_id": "refund-01",
  "amount": 12050,
  "description": "Item returned by user"
}

Response

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "refund_id": "refund-01",
  "amount": 12050,
  "full": false,
  "description": "Item returned by user",
  "created": "2020-05-09T11:20:04.311723Z"
}
POST
/orders/{order_id}/refunds
Parameter Type Description
order_id String❗️ Unique order ID.
refund_id String❗️ Unique refund ID.
amount Decimal Amount to be refunded. If the field is absent, a full refund will be applied.
description String Description of the refund.

Refund errors

HTTP Status Code Error Code Description
400 invalid Invalid input.
409 invalid_status Order status must be captured.
409 conflict There is already a refund with this ID.
409 limit_exceeded The amount exceeds the limit.

Settlements

Settlements API allows for managing and gathering all transactions that will be paid to your bank account in our next available payment cycle. There are 4 types of transactions: order, refund, instalment and regularization.

List transactions

Request

GET /transactions HTTP/1.1

Response

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "09737e0fa4ef47ba855bdd59f172318b",
      "type": "order",
      "currency": "AED",
      "amount": 81480,
      "fee_amount": 100,
      "fee_rate": 450,
      "fee_tax_rate": 500,
      "total_amount": 77525,
      "description": "",
      "created": "2020-05-08T10:53:57.118777Z",
      "paid": "2020-05-09T00:00:00.214566Z",
      "order": {
        "order_id": "order-01",
        "status": "captured",
        "status_changed": "2020-05-08T10:58:04.095618Z",
        "total_amount": 81480,
        "tax_amount": 3880,
        "currency": "AED",
        "created":"2020-05-08T10:53:57.095579Z"
      }
    }
  ]
}
GET
/transactions
Filter Type Lookups Example
id String exact, in /transactions?id={transaction_id}
type String exact, in /transactions?type__in=order,refund
amount Decimal exact, gt, lt, gte, lte /transactions?amount__gte=10050
currency Currency exact, in /transactions?currency=AED
created Datetime exact, gt, lt, gte, lte, date, year, month, week_day, day, hour /transactions?created__hour=10
payment Datetime exact, isnull, gt, lt, gte, lte, date, year, month, week_day, day, hour /transactions?payment__isnull=true
Order by Type Example
amount Decimal /transactions?ordering=amount
created Datetime /transactions?ordering=-created

Get single transaction

Request

GET /transactions/{transaction_id} HTTP/1.1

Response

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "id": "09737e0fa4ef47ba855bdd59f172318b",
  "type": "order",
  "currency": "AED",
  "amount": 81480,
  "fee_amount": 100,
  "fee_rate": 450,
  "fee_tax_rate": 500,
  "total_amount": 77525,
  "description": "",
  "created": "2020-05-08T10:53:57.118777Z",
  "paid": "2020-05-09T00:00:00.214566Z",
  "order": {
    "order_id": "order-01",
    "status": "captured",
    "status_changed": "2020-05-08T10:58:04.095618Z",
    "total_amount": 81480,
    "tax_amount": 3880,
    "currency": "AED",
    "created":"2020-05-08T10:53:57.095579Z"
  }
}
GET
/transactions/{transaction_id}
Parameter Type Description
id String❗️ Unique transaction ID.

Webhooks

Webhooks API allows you to set up integrations which subscribe to certain events on postpay.io. When one of those events is triggered, we'll send a HTTP POST payload to the webhook's configured URL.

List hooks

Request

GET /hooks HTTP/1.1

Response

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "e4dc7f6537364b629b37367a5cad43bd",
      "active": true,
      "events": [
        "order"
      ],
      "url": "https://www.example.ae/hooks",
      "last_response": {
        "code": 200,
        "status": "success"
      },
      "created": "2020-05-06T02:14:16Z",
      "modified": "2020-05-06T02:14:16Z"
    }
  ]
}
GET
/hooks
Filter Type Lookups Example
id String exact, in /hooks?id={hook_id}
events String exact, contains /hooks?events__contains=order
url String exact, in, contains, icontains, startswith, istartswith, endswith, iendswith, regex, iregex /hooks?url__startswith=https
active Boolean exact /hooks?active=true
last_response_code Integer exact, in, gt, lt, gte, lte /hooks?last_response_code=500
created Datetime exact, gt, lt, gte, lte, date, year, month, week_day, day, hour /hooks?created__year=2020
Order by Type Example
created Datetime /hooks?ordering=-created

Get single hook

Request

GET /hooks/{hook_id} HTTP/1.1

Response

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "id": "e4dc7f6537364b629b37367a5cad43bd",
  "active": true,
  "events": [
    "order"
  ],
  "url": "https://www.example.ae/hooks",
  "last_response": {
    "code": 200,
    "status": "success"
  },
  "created": "2020-05-06T02:14:16Z",
  "modified": "2020-05-06T02:14:16Z"
}
GET
/hooks/{hook_id}
Parameter Type Description
id String❗️ Unique hook ID.

Create a hook

Request

POST /hooks HTTP/1.1
Content-Type: application/json

{
  "active": true,
  "events": [
    "order"
  ],
  "url": "https://www.example.ae/hooks",
  "secret": "dolphins"
}

Response

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "id": "e4dc7f6537364b629b37367a5cad43bd",
  "active": true,
  "events": [
    "order"
  ],
  "url": "https://www.example.ae/hooks",
  "last_response": {
    "code": null,
    "status": "unused"
  },
  "created": "2020-05-06T02:14:16Z",
  "modified": "2020-05-06T02:14:16Z"
}
POST
/hooks
Parameter Type Description
events String[]❗️ Events the hook is triggered for. Options are order, transaction.
url URL❗️ The URL to which the payloads will be delivered.
secret String❗️ The secret will be used as the key to generate the HMAC hex digest value in the X-Postpay-Signature header.
active Boolean Determines if notifications are sent when the webhook is triggered. Default true.

Edit a hook

Request

PATCH /hooks/{hook_id} HTTP/1.1
Content-Type: application/json

{
  "active": false,
  "events": [
    "transaction"
  ]
}

Response

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "id": "e4dc7f6537364b629b37367a5cad43bd",
  "active": false,
  "events": [
    "transaction"
  ],
  "url": "https://www.example.ae/hooks",
  "last_response": {
    "code": 200,
    "status": "success"
  },
  "created": "2020-05-06T02:14:16Z",
  "modified": "2020-05-06T02:14:16Z"
}
PATCH
/hooks/{hook_id}
Parameter Type Description
id String❗️ Unique hook ID.
events String[] Events the hook is triggered for. Options are order, transaction.
url URL The URL to which the payloads will be delivered.
secret String The secret will be used as the key to generate the HMAC hex digest value in the X-Postpay-Signature header.
active Boolean Determines if notifications are sent when the webhook is triggered. Default true.

Delete a hook

Request

DELETE /hooks/{hook_id} HTTP/1.1

Response

HTTP/1.1 204 No Content
DELETE
/hooks/{hook_id}
Parameter Type Description
id String❗️ Unique hook ID.

Errors

Forbidden error

HTTP/1.1 403 Forbidden
Content-Type: application/vnd.api+json

{ 
  "error": { 
    "code": "permission_denied",
    "message": "You do not have permission to perform this action."
  }
}

Validation error

HTTP/1.1 400 Invalid
Content-Type: application/vnd.api+json

{
  "error": {
    "code": "invalid",
    "message": "Invalid input.",
    "fields": {
      "refund_id": [
        "This field is required."
      ]
    }
  }
}
HTTP Status Code Error Code Description
400 invalid Invalid input.
400 parse_error Malformed request.
401 authentication_failed Invalid authentication credentials.
402 payment_required Payment required.
403 permission_denied You do not have permission to perform this action.
404 not_found Not found.
405 method_not_allowed HTTP method not allowed.
406 not_acceptable Could not satisfy the request Accept header.
409 conflict A conflict of data exists, even with valid information.
410 gone The target resource is no longer available.
415 unsupported_media_type Unsupported media type in request.
422 unprocessable The requested information is okay, but invalid.
429 throttled Request was throttled.
50x error Oops!!