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

Pagination

Request

POST /graphql HTTP/1.1
Content-Type: application/vnd.api+json

{
  "query": "
  {
    orders(first: 2, after: \"{cursor}\") {
      edges {
        node {
          orderId
        }
        cursor
      }
      totalCount
      pageInfo {
        startCursor
        endCursor
        hasPreviousPage
        hasNextPage
      }
    }
  }"
}

Response

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

{
  "data": {
    "orders": {
      "edges": [
        {
          "node": {
            "orderId": "order-01"
          },
          "cursor": "YXJyYXljb25uZWN0aW9uOjA="
        }
      ],
      "totalCount": 100,
      "pageInfo": {
        "startCursor": "YXJyYXljb25uZWN0aW9uOjA=",
        "endCursor": "YXJyYXljb25uZWN0aW9uOjE=",
        "hasPreviousPage": false,
        "hasNextPage": true
      }
    }
  }
}
Parameter Type Description
first Int Slice the results first elements.
last Int Slice the results last elements.
before String Slice the results before the cursor.
after String Slice the results after the cursor.
cursor String A cursor for use in pagination.
pageInfo Object The Relay compliant PageInfo type, containing data necessary to paginate this connection.
PageInfo field Type Description
startCursor String When paginating backwards, the cursor to continue.
endCursor String When paginating forwards, the cursor to continue.
hasPreviousPage String Indicates whether the beginning of the list was reached (only relevant when paginating backwards through a list).
hasNextPage Boolean Indicates whether the end of the list was reached (only relevant when paginating forward through a list).

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 redirectUrl 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 confirmationUrl appending the orderId 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 /graphql HTTP/1.1
Content-Type: application/json

{
  "operationName": "CreateCheckout",
  "variables": {
    "input": {
      "orderId": "order-01",
      "totalAmount": 81480,
      "taxAmount": 3880,
      "currency": "AED",
      "shipping": {
        "id": "shipping-01",
        "name": "Express Delivery",
        "amount": 2000,
        "address": {
          "firstName": "John",
          "lastName": "Doe",
          "phone": "+971 50 000 0000",
          "altPhone": "800 239",
          "line1": "The Gate District, DIFC",
          "line2": "Level 4, Precinct Building 5",
          "city": "Dubai",
          "state": "Dubai",
          "country": "AE",
          "postalCode": "00000"
        }
      },
      "billingAddress": {
        "firstName": "John",
        "lastName": "Doe",
        "phone": "+971 50 000 0000",
        "altPhone": "800 239",
        "line1": "The Gate District, DIFC",
        "line2": "Level 4, Precinct Building 5",
        "city": "Dubai",
        "state": "Dubai",
        "country": "AE",
        "postalCode": "00000"
      },
      "customer": {
        "id": "customer-01",
        "email": "john@postpay.io",
        "firstName": "John",
        "lastName": "Doe",
        "gender": "male",
        "account": "guest",
        "dateOfBirth": "1990-01-20",
        "dateJoined": "2019-08-26T09:28:14.790Z",
        "defaultAddress": {}
      },
      "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",
          "imageUrl": "https://www.example.ae/wild-flower.jpg",
          "unitPrice": 84000,
          "qty": 1
        }
      ],
      "discounts": [
        {
          "code": "return-10",
          "name": "Returning customer 10% discount",
          "amount": 8400
        }
      ],
      "merchant": {
        "confirmationUrl": "https://www.example.ae/success",
        "cancelUrl": "https://www.example.ae/cancel"
      }
    }
  },
  "query": "
  mutation CreateCheckout($input: CreateCheckoutInput!) {
    createCheckout(input: $input) {
      token
      expires
      redirectUrl
    }
  }"
}

Response

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

{
  "data": {
    "createCheckout": {
      "token": "e35f6487d0044ef4b52f6a399427b962",
      "expires": "2020-05-08T11:53:57.095579Z",
      "redirectUrl": "https://checkout.postpay.io/e35f6487d0044ef4b52f6a399427b962"
    }
  }
}
Parameter Type Description
orderId String❗️ Unique order ID.
totalAmount Decimal❗️ Total total amount of the order, including tax and any discounts.
taxAmount Decimal❗️ Total tax amount after all discounts have been applied.
currency Currency❗️ ISO 4217 order currency.
numInstalments 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.
billingAddress 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

{
    "firstName": "John",
    "lastName": "Doe",
    "phone": "+971 50 000 0000",
    "altPhone": "800 239",
    "line1": "The Gate District, DIFC",
    "line2": "Level 4, Precinct Building 5",
    "city": "Dubai",
    "state": "Dubai",
    "country": "AE",
    "postalCode": "00000"
}
Parameter Type Description
firstName String❗️ First name.
lastName String❗️ Last name.
phone String Phone number.
altPhone 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.
postalCode 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",
    "firstName": "John",
    "lastName": "Doe",
    "gender": "male",
    "account": "guest",
    "dateOfBirth": "1990-01-20",
    "dateJoined": "2019-08-26T09:28:14.790Z",
    "defaultAddress": {}
}
Parameter Type Description
id String Customer ID.
email String❗️ A valid email address.
firstName String First name.
lastName String Last name.
gender String Gender, options are male, female, other.
account String Account type, options are new, existing, guest.
dateOfBirth String The customer date of birth ISO 8601.
dateJoined String A datetime designating when the account was created ISO 8601.
defaultAddress 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",
    "imageUrl": "https://www.example.ae/wild-flower.jpg",
    "unitPrice": 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.
imageUrl URL Item's image URL.
unitPrice 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

{
    "confirmationUrl": "https://www.example.ae/success",
    "cancelUrl": "https://www.example.ae/cancel"
}
Parameter Type Description
confirmationUrl URL❗️ URL that the customer is sent to if they successfully complete the checkout process. The orderId and status=APPROVED will be sent to this URL as a HTTP query parameter in order to capture the order.
cancelUrl 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 /graphql HTTP/1.1
Content-Type: application/json

{
  "query": "
  mutation {
    capture(input: {orderId: \"{orderId}\"}) {
      order {
        status
      }
    }
  }"
}

Response

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

{
  "data": {
    "capture": {
      "order": {
        "status": "captured"
      }
    }
  }
}

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

Parameter Type Description
orderId String❗️ Unique order ID.

Capture errors

Error Code Description
invalidStatus Order status must be approved.
captureError Payment transaction declined.
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

POST /graphql HTTP/1.1
Content-Type: application/vnd.api+json

{
  "query": "
  {
    orders {
      edges {
        node {
          orderId
          status
        }
      }
    }
  }"
}

Response

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

{
  "data": {
    "orders": {
      "edges": [
        {
          "node": {
            "orderId": "order-01",
            "status": "captured"
          }
        }
      ]
    }
  }
}
Filter Type Lookups Example
orderId String Exact, In orders(orderId: "order-01")
status String Exact, In orders(status_In: "captured,denied")
totalAmount Decimal Exact, Gt, Lt, Gte, Lte orders(totalAmount: 10050)
currency Currency Exact, In orders(currency: "AED")
created Datetime Exact, Gt, Lt, Gte, Lte, Date, Year, Month, WeekDay, Day, Hour orders(created_Date_Gt: "2020-05-20")
Order by Type Example
totalAmount Decimal orders(orderBy: "totalAmount")
created Datetime orders(orderBy: "-created")

Get single order

Request

POST /graphql HTTP/1.1
Content-Type: application/vnd.api+json

{
  "query": "
  {
    order(orderId: \"{orderId}\") {
      orderId
      status
      totalAmount
      currency
      created
      customer {
        email
        firstName
        lastName
      }
      items {
        edges {
          node {
            reference
            name
            unitPrice
            qty
          }
        }
      }
    }
  }"
}

Response

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

{
  "data": {
    "order": {
      "orderId": "order-01",
      "status": "captured"
      "totalAmount": 81480,
      "currency": "AED",
      "created": "2020-05-08T10:53:57.095579Z",
      "customer": {
        "email": "john@postpay.io",
        "firstName": "John",
        "lastName": "Doe"
      },
      "items": {
        "edges": [
          {
            "node": {
              "reference": "sku-01",
              "name": "Wild Flower Eau de Parfum (50ml)",
              "unitPrice": 84000,
              "qty": 1
            }
          }
        ]
      }
    }
  }
}
Parameter Type Description
orderId 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

POST /graphql HTTP/1.1
Content-Type: application/vnd.api+json


{
  "query": "
  {
    order(orderId: \"{orderId}\") {
      orderId
      refunds {
        edges {
          node {
            refundId
            amount
          }
        }
      }
    }
  }"
}

Response

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

{
  "data": {
    "order": {
      "orderId": "order-01",
      "refunds": {
        "edges": [
          {
            "node": {
              "refundId": "refund-01",
              "amount": 12050
            }
          }
        ]
      }
    }
  }
}
Filter Type Lookups Example
refundId String Exact, In refunds(refundId: "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, WeekDay, Day, Hour refunds(created_Year: 2020)
Order by Type Example
amount Decimal refunds(orderBy: "amount")
created Datetime refunds(orderBy: "-created")

Create a refund

Request

POST /graphql HTTP/1.1
Content-Type: application/vnd.api+json

{
  "operationName": "Refund",
  "variables": {
    "input": {
      "orderId": "{orderId}",
      "refundId": "{refundId}",
      "amount": 12050,
      "description": "Item returned by user"
    }
  },
  "query": "
  mutation Refund($input: RefundInput!) {
    refund(input: $input) {
      order {
        orderId
        refunds {
          edges {
            node {
              refundId
              amount
              full
              description
              created
            }
          }
        }
      }
    }
  }"
}

Response

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

{
  "data": {
    "order": {
      "orderId": "order-01",
      "refunds": {
        "edges": [
          {
            "node": {
              "refundId": "refund-01",
              "amount": 12050,
              "full": false,
              "description": "Item returned by user",
              "created": "2020-05-09T11:20:04.311723Z"
            }
          }
        ]
      }
    }
  }
}
RefundInput Type Description
orderId String❗️ Unique order ID.
refundId String❗️ Unique refund ID.
amount Decimal If the field is absent, a full refund will be applied.
description String Description of the refund.

Refund errors

Error Code Description
invalid Invalid input.
invalidStatus Order status must be captured.
conflict There is already a refund with this ID.
limitExceeded 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

POST /graphql HTTP/1.1
Content-Type: application/vnd.api+json

{
  "query": "
  {
    transactions {
      edges {
        node {
          id
          type
          currency
          totalAmount
          paid
        }
      }
    }
  }"
}

Response

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

{
  "data": {
    "transactions": {
      "edges": [
        {
          "node": {
            "id": "VHJhbnNhY3Rpb246ZmNlZWVhZTYwZTUzNDVmMjlhMTJhMGI1ODNmMzFkNGE=",
            "type": "order",
            "currency": "AED",
            "totalAmount": 77525,
            "paid": "2020-05-09T00:00:00.214566Z"
          }
        }
      ]
    }
  }
}
Filter Type Lookups Example
id String Exact, In transactions(id: "{transactionId}")
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, WeekDay, Say, Hour transactions(created_Hour: 10)
paid Datetime Exact, Isnull, Gt, Lt, Gte, Lte, Date, Year, Month, WeekDay, Say, Hour transactions(paid_Isnull: true)
Order by Type Example
amount Decimal transactions(orderBy: "amount")
created Datetime transactions(orderBy: "-created")
paid Datetime transactions(orderBy: "paid")

Get single transaction

Request

POST /graphql HTTP/1.1
Content-Type: application/vnd.api+json

{
  "query": "
  {
    transaction(id: \"{transactionId}\") {
      id
      type
      currency
      amount
      feeAmount
      feeRate
      feeTaxRate
      totalAmount
      description
      created
      paid
    }
  }"
}

Response

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

{
  "data": {
    "transaction": {
      "id": "VHJhbnNhY3Rpb246ZmNlZWVhZTYwZTUzNDVmMjlhMTJhMGI1ODNmMzFkNGE=",
      "type": "order",
      "currency": "AED",
      "amount": 81480,
      "feeAmount": 100,
      "feeRate": 450,
      "feeTaxRate": 500,
      "totalAmount": 77525,
      "description": "",
      "created": "2020-05-08T10:53:57.118777Z",
      "paid": "2020-05-09T00:00:00.214566Z"
    }
  }
}
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

POST /graphql HTTP/1.1
Content-Type: application/vnd.api+json

{
  "query": "
  {
    hooks {
      edges {
        node {
          id
          events
          url
        }
      }
    }
  }"
}

Response

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

{
  "data": {
    "hooks": {
      "edges": [
        {
          "node": {
            "id": "SG9vazpmYjM1NWI1NTMwMmU0YzExYmU4MjZiYjA1ZTJjMmM3OA==",
            "events": [
              "transaction"
            ],
            "url": "https://www.example.ae/hooks"
          }
        }
      ]
    }
  }
}
Filter Type Lookups Example
id String Exact, In hooks(id: "{hookId}")
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)
lastResponseCode Integer Exact, In, Gt, Lt, Gte, Lte hooks(lastResponseCode: 500)
created Datetime Exact, Gt, Lt, Gte, Lte, Date, Year, Month, WeekDay, Day, Hour hooks(created_Year: 2020)
Order by Type Example
created Datetime hooks(orderBy: "-created")

Get single hook

Request

POST /graphql HTTP/1.1
Content-Type: application/vnd.api+json

{
  "query": "
  {
    hook(id: \"{hookId}\") {
      id
      active
      events
      url
      lastResponse {
        code
        status
      }
      created
      modified
    }
  }"
}

Response

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

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

Create a hook

Request

POST /graphql HTTP/1.1
Content-Type: application/vnd.api+json

{
  "operationName": "CreateHook",
  "variables": {
    "input": {
      "active": true,
      "events": [
        "order"
      ],
      "url": "https://www.example.ae/hooks",
      "secret": "dolphins"
    }
  },
  "query": "
  mutation CreateHook($input: CreateHookInput!) {
    createHook(input: $input) {
      hook {
        id
        active
        events
        url
      }
    }
  }"
}

Response

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

{
  "data": {
    "createHook": {
      "hook": {
        "id": "SG9vazpmYjM1NWI1NTMwMmU0YzExYmU4MjZiYjA1ZTJjMmM3OA==",
        "active": true,
        "events": [
          "order"
        ],
        "url": "https://www.example.ae/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

POST /graphql HTTP/1.1
Content-Type: application/vnd.api+json

{
  "operationName": "EditHook",
  "variables": {
    "input": {
      "id": "{hookId}",
      "active": false,
      "events": [
        "transaction"
      ]
    }
  },
  "query": "
  mutation EditHook($input: CreateHookInput!) {
    editHook(input: $input) {
      hook {
        id
        active
        events
        url
      }
    }
  }"
}

Response

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

{
  "data": {
    "editHook": {
      "hook": {
        "id": "SG9vazpmYjM1NWI1NTMwMmU0YzExYmU4MjZiYjA1ZTJjMmM3OA==",
        "active": false,
        "events": [
          "transaction"
        ],
        "url": "https://www.example.ae/hooks"
      }
    }
  }
}
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

POST /graphql HTTP/1.1
Content-Type: application/vnd.api+json

{
  "query": "
  mutation {
    deleteHook(input: {id: \"{hookId}\"}) {
      success
    }
  }"
}

Response

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

{
  "data": {
    "deleteHook": {
      "success": true
    }
  }
}
Parameter Type Description
id String❗️ Unique hook ID.

Errors

Permission denied error

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

{
  "errors": [
    {
      "type": "PermissionDenied",
      "message": "You do not have permission to perform this action",
      "code": "permissionDenied",
      "path": ["orders"],
      "operation": "query"
    }
  ],
  "data": {
    "orders": null
  }
}

The GraphQL specification provides for a top-level errors key which may include information about errors during query execution.

Parameter Type Description
type String Error type.
message String Translated error message.
code String Error code.
path String[] Explains where in a response an error corresponds.
operation String Operation type, choices are query or mutation.

shell Error codes

Name Code Description
ValidationError invalid Data validation error.
PermissionDenied permissionDenied You do not have permission to perform this action.
NotFound notFound The server can not find what was requested.
GraphQLError error Query error.
GraphQLSyntaxError error Syntax error.