NAV
HTTP cURL

Introduction

Hokodo provides a set of API endpoints to facilitate Deferred Payments, also known as credit terms, or "Buy Now, Pay Later" (BNPL) for B2B platforms, such as marketplaces or e-commerce sites.

This reference documentation details how developers may use Hokodo to implement credit terms into their customer journey, from checking whether a customer can be eligible for credit terms, to submitting a customer's orders to Hokodo. Hokodo APIs are organized around REST, with predictable, resource-oriented URLs, and use HTTP response codes to indicate API errors.

Our API expects incoming data to be valid JSON objects with requests containing the header Content-Type: application/json, unless explicitly stated otherwise.

All responses of the API, including errors, are in JSON, except for some endpoints returning PDF documents, Excel files or CSV files, that will be clearly indicated as such.

You can view request/response examples in the dark area to the right, and you can switch between raw representation and curl command with tabs in the top right.

The base URL of the API in the sandbox (see environments) is https://api-sandbox.hokodo.co/

 API Guide

This API reference is a comprehensive description of the technical behaviour of Hokodo's BNPL API.

It is intended to be read alongside our API Guide, which should be your primary resource for integrating Hokodo's BNPL solution.

Glossary

In the document, we will use the following terms, with a specific meaning:

Organisations and Users

Because Hokodo focuses on B2B sales, the buyers on your platform will consist of Companies, who have employees, and those employees may be organised into teams or departments. Hokodo deals with this complexity through the concept of Organisations and Users.

A User is an individual employee at a company. An Organisation is a group of Users who are all able to see or take action on that company's orders on your platform. Each Organisation must be associated with a Company.

In many cases the company will just have a single Organisation, and any employees of the company (Users) will be members of that Organisation. In this case, any one of those Users will be able to see or take actions on any of the company's orders on your platform. For example, if a member of the Organisation has set up a direct debit mandate, then any other member of that Organisation can make purchases using the mandate.

In other cases (for larger companies), there may be several Organisations - perhaps one associated to each department in the company. In this case, Users can only see the orders associated with their Organisation.

Authorization

To authentify pass the correct header with each request:

GET /v1/me HTTP/1.1
Authorization: Token <your_api_key>
curl --request GET \
  --url https://api-sandbox.hokodo.co/v1/me/ \
  --header "Authorization: Token <your_api_key>"

Make sure to replace <your_api_key> with your API key from https://sandbox.hokodo.co.

Use your secret key in your API requests. You can manage your keys in your Developer dashboard. Be sure to keep your key secure and do not share it in publicly-accessible areas, such as GitHub, in your client-side Javascript code, etc.

Authorization to the API is done by providing the key in Authorization header preceded by Token keyword. The API key can also be provided as user with no password through HTTP Basic Auth.

All API requests must be made over HTTPS. Calls made over plain HTTP or without proper authentication will fail.

Testing the API

Please make sure to test your integration thoroughly in our sandbox before going live. After registering, you will be given your test API keys. Those are safe to use for development. When you are ready, make sure to replace those keys with live ones.

While testing, the API will not return real credit approvals and limits. If you want to simulate how well we can cover your clients, please do not hesitate to get in touch with our team at support@hokodo.co.

API versioning

The BNPL API is in version v1. Your feedback is most appreciated for any improvement.

Backwards compatible changes are made regularly to improve the API. You can find the changelog in the partner dashboard.

Pagination

For example to get 10 orders starting with the 51st order:

GET /v1/payment/orders/?limit=10&offset=50 HTTP/1.1
curl --request GET \
  --url https://api-sandbox.hokodo.co/v1/payment/orders/?limit=10&offset=50 \
  --header "Authorization: Token <your_api_key>"

The answer is a JSON looking like this:

{
    "count": 95,  # Total number of orders
    "next": "http://api-sandbox.hokodo.co/v1/payment/orders/?limit=10&offset=60",
    "previous": null,
    "results": [
        {
            ... # 51st order in the list
        },
        {
            ... # 52nd order in the list
        }
        ...
    ]
}

The API returns paginated results, for list endpoints where the response might contain many items in a large list. By default, the number of items returned is 25.

You can control the page size and position by using the query parameters limit and offset. limit controls the number of items displayed, offset the index of the first item of the list, starting from 0. The defaults if no value is passed are thus offset=0 and limit=25.

See examples on the right.

Expansion

For example let's consider the following request:

GET /v1/payment/offers/offer-kEFDnwu8cnkETeagWAcqF4 HTTP/1.1
curl --request GET \
  --url https://api-sandbox.hokodo.co/v1/payment/offers/offer-kEFDnwu8cnkETeagWAcqF4 \
  --header "Authorization: Token <your_api_key>"

It's returning the following JSON response (compacted for the example):

{
    "url": "http://api-sandbox.hokodo.co/v1/payment/offers/offer-kEFDnwu8cnkETeagWAcqF4",
    "id": "offer-kEFDnwu8cnkETeagWAcqF4",
    "order": "order-TiehJCGZmFRkKoL8NsM3d6",
    "status": "accepted"
    ...  # Other payment offer fields
}

We can use ?expand=order for example:

GET /v1/payment/offers/offer-kEFDnwu8cnkETeagWAcqF4?expand=order HTTP/1.1
curl --request GET \
  --url https://api-sandbox.hokodo.co/v1/payment/offers/offer-kEFDnwu8cnkETeagWAcqF4?expand=order \
  --header "Authorization: Token <your_api_key>"

As a response we get:

{
    "url": "http://api-sandbox.hokodo.co/v1/payment/offers/offer-kEFDnwu8cnkETeagWAcqF4",
    "id": "quo-kEFDnwu8cnkETeagWAcqF4",
    "order": {
        "id": "order-TiehJCGZmFRkKoL8NsM3d6"
        ...  # Other order fields
    },
    "status": "accepted"
    ...  # Other payment offer fields
}

The API returns some items as API identifiers. The designated resource can be expanded, meaning that the identifier is replaced in the response with a dictionary representing the resource itself. You can control which field is expanded using the query parameter expand. Expected value is a comma separated list of field names, for example ?expand=order,payment.

Note: At the moment, only read requests can use expansion. You can't use resource expansion for requests where you create and modify resources.

See examples on the right.

Environments

Test environment (aka Sandbox)

Register at: https://sandbox.hokodo.co API base URL: https://api-sandbox.hokodo.co/

This is the test environment for our API clients, where you can integrate your own software with our API without consequences. It will always run the same version(s), expect the same request format and return the same response format as the production environment.

Data such as credit scores or payment offers will not be real however, and no payment is provided. Non-sensitive data, such as companies search, will be as close as possible to the production data.

Production

Apply at: https://www.hokodo.co/contact API base URL: https://api.hokodo.co/

This is the live, production environment, where:

Data formats

Countries

Requests

  • buyer countries
GET /v1/countries/debtor HTTP/1.1
curl --request GET \
    --url https://api-sandbox.hokodo.co/v1/countries/debtor

Response

200 Ok
Content-Type: application/json
[
  {
    "code": "GB",
    "name": "United Kingdom"
  },
  {
    "code": "FR",
    "name": "France"
  }
]

Where a country input field is required by the API, you can use either the ISO 3166-1 alpha-2 code or the country's name. See below on how to obtain a full list of accepted countries.

Obtain a list of valid countries for a buyer/customer.

Dates and times

When a date, or date and time field is required by the API, it is expected in ISO 8601 notation, for example:

Type Format Example
Date yyyy-mm-dd 2018-10-31
Datetime yyyy-mm-ddThh:mm:ss.ffffff 2018-10-31T16:53:00.12345
Datetime UTC yyyy-mm-ddThh:mm:ss.ffffffZ 2018-10-31T16:53:00.12345Z

For order issue and due dates for example, there is no time associated and the API expects only a date, no time nor timezone. Be careful if you are internally converting a datetime with timezone to a date, e.g. 2018-10-31T00:00:00+02:00 could become 2018-10-30T22:00:00Z when converted to UTC and then 2018-10-30 in the request to the API, which wouldn't fit the user input.

Currencies

When a currency field is used by the API, it is an ISO 4217 code, such as GBP, EUR or USD.

Amounts

When a money amount is expected or returned by the API, it is always in minor units, ie cents. For example:

Idempotent Requests

The API supports idempotent requests on a selection of endpoints for safely retrying requests without performing the operation twice.

To perform an idempotent request provide the optional Idempotency-Key: <key> header with a value that must be unique per request. If a request is repeated with the same key, it will return the same data and status code.

We recommend choosing a randomly generated string with high entropy, such as a UUID v4. This will avoid accidentally re-using the same key for different requests, resulting in an HTTP 400 error.

Example: repeating a request

Request 1

GET /v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/capture HTTP/1.1
Authorization: Token <your_api_key>
Itempotency-Key: 33871f6b-ff2f-4de3-9e10-ff42ef7af553

{
    "amount": 100000
}
curl --request POST \
     --url https://api-sandbox.hokodo.co/v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/capture \
     --header "Itempotency-Key: 33871f6b-ff2f-4de3-9e10-ff42ef7af553" \
     --header "Authorization: Token <your_api_key>" \
     --data-binary '{"amount": 100000}'

Response 1

201 CREATED
Content-Type: application/json
{
  "created": "2023-05-30T15:22:44.788858Z",
  "type": "capture",
  "amount": 100000,
  "currency": "GBP",
  "metadata": {},
  "changes": {
    "authorisation": -10000,
    "protected_captures": 10000,
    "unprotected_captures": 0,
    "refunds": 0,
    "voided_authorisation": 0,
    "expired_authorisation": 0
  }
}

Request 2

GET /v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/capture HTTP/1.1
Authorization: Token <your_api_key>
Itempotency-Key: 33871f6b-ff2f-4de3-9e10-ff42ef7af553

{
    "amount": 100000
}
 curl --request POST \
     --url https://api-sandbox.hokodo.co/v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/capture \
     --header "Itempotency-Key: 33871f6b-ff2f-4de3-9e10-ff42ef7af553" \
     --header "Authorization: Token <your_api_key>" \
     --data-binary '{"amount": 100000}'

Response 2

201 CREATED
Content-Type: application/json
{
  "created": "2023-05-30T15:22:44.788858Z",
  "type": "capture",
  "amount": 100000,
  "currency": "GBP",
  "metadata": {},
  "changes": {
    "authorisation": -10000,
    "protected_captures": 10000,
    "unprotected_captures": 0,
    "refunds": 0,
    "voided_authorisation": 0,
    "expired_authorisation": 0
  }
}

In the example on the right, the same request is made twice. Each time, the same Idempotency-Key and request body is used.

The first request will create a new capture deferred payment event for deferred payment defpay-bqRyGIGaORKiK8bhMVPirp and return a 201 CREATED.

Making a second request with the same idempotency key will not create a new event. It will return the event created in the original request, with the original HTTP status code.

Example: accidental key re-use

Request 1: Different event type

GET /v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/void HTTP/1.1
Authorization: Token <your_api_key>
Itempotency-Key: 33871f6b-ff2f-4de3-9e10-ff42ef7af553

{
    "amount": 100000
}
 curl --request POST \
     --url https://api-sandbox.hokodo.co/v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/void \
     --header "Authorization: Token <your_api_key>" \
     --header "Itempotency-Key: 33871f6b-ff2f-4de3-9e10-ff42ef7af553" \
     --data-binary '{"amount": 100000}'

Response 1

400 BAD REQUEST
Content-Type: application/json
     {
       "error": "Duplicate `Idempotency-Key` [33871f6b-ff2f-4de3-9e10-ff42ef7af553] has been used to create a `capture` event, the key cannot be used to create a `void` event."
     }

Request 2: Different amount

GET /v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/capture HTTP/1.1
Authorization: Token <your_api_key>
Itempotency-Key: 33871f6b-ff2f-4de3-9e10-ff42ef7af553

{
    "amount": 50
}
 curl --request POST \
     --url https://api-sandbox.hokodo.co/v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/capture \
     --header "Authorization: Token <your_api_key>" \
     --header "Itempotency-Key: 33871f6b-ff2f-4de3-9e10-ff42ef7af553" \
     --data-binary '{"amount": 50}'

Response 2

400 BAD REQUEST
Content-Type: application/json
     {
       "error": "Duplicate `Idempotency-Key` [33871f6b-ff2f-4de3-9e10-ff42ef7af553] cannot be used to create an event with a different `amount`."
     }

Any other use of the same key, for instance on a different endpoint with a slightly different request, will result in a 400.

In the first example on the right, we are using the same Idempotency-Key as before, but we are using it to create a void instead of a capture. The result is an HTTP 400 because this is not the same request as before.

In the second example on the right, we are using the same Idempotency-Key as before, but capturing a different amount. The result is an HTTP 400 because this is not the same request as before.

Companies

Companies represent the legal entities associated with your customers. To be able to provide accurate credit approval and limits, and payment plans, we need to properly identify the companies.

If you already store a unique company identifier such as a Companies House number (UK) or SIREN (France) then you can use our Companies endpoint to obtain the Hokodo ID for the company.

More commonly, however, merchants simply store a free text name for their customers' companies. Because there can often be many companies with similar sounding names (including different subsidiaries of the same parent), we typically recommend adopting the following process to make sure you are supplying the correct company identifiers:

  1. presenting your user with text box(es), where they can enter their company's name, and/or address, and/or registration number,
  2. using that information in our company search API, to obtain a list of companies which are potential matches to the text you supplied.
  3. asking the user to pick among the choices our company search API has returned.

Companies endpoints

Company object

{
  "url": "https://api-sandbox.hokodo.co/v1/companies/co-bqRyKAGaFrEEN8JMjWJiqk",
  "id": "co-bqRyKAGaFrEEN8JMjWJiqk",
  "name": "Hokodo Ltd",
  "creation_date": "2018-02-20",
  "status": "Active",
  "legal_form": "Private limited with share capital",
  "country": "GB",
  "address": "35 Kingsland Road, London, E2 8AA",
  "city": "London",
  "postcode": "E2 8AA",
  "email": "",
  "phone": "",
  "sectors": [
    {
      "system": "SIC2007",
      "code": "64999"
    },
    {
      "system": "SIC2007",
      "code": "62012"
    },
    {
      "system": "SIC2007",
      "code": "66220"
    }
  ],
  "identifiers": [
    {
      "idtype": "reg_number",
      "country": "GB",
      "value": "11215527"
    }
  ]
}
field type description
url string API endpoint to access the company
id string(uuid) API unique identifier for the company
name string Company name
creation_date date Date of inception of the company
status string Current status of the company. You are generally interested about Active or ACT companies
legal_form string Legal form of the company. The list of possible legal forms varies from country to country.
country country Registered address: country code
address string Registered address: full postal address
city string Registered address: city name
postcode string Registered address: postcode
email string Contact email address for the company
phone string Contact phone number for the company
sectors list The list of sectors the company operate in.
sectors[*][system] string The system of reference to interpret the code (SIC2007 in UK, NAF_2008 in FR)
sectors[*][code] string Sector code in the given system
identifiers list The list of official identifiers know for this company, e.g. Companies House registration number, VAT number, etc.
identifiers[*][id_type] string The type of identifier (reg_number for a registration number, lei for an identifier of the Global LEI System, vat_number for a tax identifier)
identifiers[*][country] country Country in which the identifier is relevant when it applies. Can be blank.
identifiers[*][value] string Identifier

Request

POST /v1/companies/search HTTP/1.1
Content-Type: application/json

{
  "name": "Hokodo Ltd",
  "country": "GB"
}
curl --request POST \
  --url https://api-sandbox.hokodo.co/v1/companies/search \
  --header "Content-Type: application/json" \
  --data-binary '{
    "name": "Hokodo Ltd",
    "country": "GB"
}'

Responses

  • regular response
200 OK
Content-Type: application/json
{
  "matches": [
    {
      "url": "https://api-sandbox.hokodo.co/v1/companies/co-EWzoaRqbvsdq8FW7dB6evL",
      "id": "co-EWzoaRqbvsdq8FW7dB6evL",
      "country": "GB",
      "name": "HOKODO LTD",
      "address": "35 Kingsland Road, London, United Kingdom, E2 8AA",
      "city": "London",
      "postcode": "E2 8AA",
      "legal_form": "",
      "sectors": [],
      "creation_date": "2018-02-20",
      "identifiers": [
        {
          "idtype": "reg_number",
          "country": "GB",
          "value": "11215527"
        }
      ],
      "email": "",
      "phone": "",
      "status": "Undefined",
      "confidence": null
    },
    {
      "url": "https://api-sandbox.hokodo.co/v1/companies/co-JbTDrzejAhRafYrKSFEGi4",
      "id": "co-JbTDrzejAhRafYrKSFEGi4",
      "country": "GB",
      "name": "Hokodo Services Ltd",
      "address": "35 Kingsland Road, London, E2 8AA",
      "city": "London",
      "postcode": "E2 8AA",
      "legal_form": "Private limited with share capital",
      "sectors": [],
      "creation_date": "2018-05-09",
      "identifiers": [
        {
          "idtype": "reg_number",
          "country": "GB",
          "value": "11351988"
        }
      ],
      "email": "",
      "phone": "",
      "status": "Active",
      "confidence": null
    }
  ]
}
  • no results
200 OK
Content-Type: application/json
{
  "matches": []
}
  • error response (country field missing)
{
  "country": [
    "This field is required."
  ]
}
  • error response (name and reg_number fields missing)
400 Bad Request
Content-Type: application/json
{
  "non_field_errors": [
    "Not enough information to identify company. Provide at least country and either name or registration number."
  ]
}

Search for a company by country, name, registration number if available. Country is mandatory, and one of name or registration number must be provided. The API will try to find the best match and return a list of potential matches.

field description requirement
country Country the company is registered in required
name Name of the company required *
reg_number Registration number in country required *
address Address of the company optional

(at least one of fields, marked with * is required)

Errors:

code description
400 a required field is missing

View Company

Request

GET /v1/companies/{company_id} HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>
curl --request GET \
  --url https://api-sandbox.hokodo.co/v1/companies/{company_id} \
  --header "Authorization: Token <your_api_key>" \
  --header "Content-Type: application/json"

Responses

  • regular response
200 OK
Content-Type: application/json
{
  "url": "https://api-sandbox.hokodo.co/v1/companies/co-EWzoaRqbvsdq8FW7dB6evL",
  "id": "co-EWzoaRqbvsdq8FW7dB6evL",
  "country": "GB",
  "name": "HOKODO LTD",
  "address": "35 Kingsland Road, London, United Kingdom, E2 8AA",
  "city": "London",
  "postcode": "E2 8AA",
  "legal_form": "",
  "sectors": [],
  "creation_date": "2018-02-20",
  "identifiers": [
    {
      "idtype": "reg_number",
      "country": "GB",
      "value": "11215527"
    }
  ],
  "email": "",
  "phone": "",
  "status": "Undefined"
}
  • not found
404 Not Found
Content-Type: application/json
{
  "detail": "Not found."
}

Look up a previously found company.

Errors:

code description
404 the company_id is probably invalid, and the company has not been found

Sole traders

Sole Traders represent unregistered entities associated with your customers. To be able to provide accurate credit approval, limits, and payment plans, we need to properly identify the company and the sole trader (proprietor).

Commonly, merchants store a free text name for their customers' sole trading businesses. Because there can often be many sole traders with similar sounding names, and, as unregistered businesses sole traders will generally not have a government issued unique identifier (registered companies will have a registration number for instance) we typically recommend adopting the following process to make sure you are supplying the correct information for sole traders:

  1. presenting your user with text box(es), where they can enter their owner / proprietor's name and address
  2. presenting your user with text boxes where they can enter their company's name and address
  3. using that information to create a SoleTrader on the Hokodo platform

Hokodo require both company and proprietor data to provide servers for the sole trader, without complete data Hokodo will not be able to accurately credit score the company.

By default, only certain types of companies can be offered Buy Now Pay Later by Hokodo. If a significant portion of your users are sole traders, get in touch with us to enable that function for you.

You will be able to create SoleTrader objects, which are an extension of the Company objects.

Sole trader endpoints

SoleTrader object

{
    "id": "co-YuNEQ4nqA6Yto9QQUBnopW",
    "soletrader_id": "st-eE4un8TnDNjx9Uac2DVa6N",
    "owner": "user-sVr7a58Smbfqbo8cVpjEV6",
    "unique_id": "0d201ab1-46df-4274-8c90-256eaa66c135",
    "vat_number": "15141312",
    "trading_name": "The Dogfather 21",
    "trading_address": "123 Commercial St, Shoreditch",
    "trading_address_city": "London",
    "trading_address_postcode": "EC2A 8AB",
    "trading_address_country": "GB",
    "proprietor_name": "John John",
    "proprietor_address_line1": "Flat 5",
    "proprietor_address_line2": "10 Residential Street",
    "proprietor_address_line3": "Hackney",
    "proprietor_address_city": "London",
    "proprietor_address_postcode": "EC2 8AA",
    "proprietor_address_country": "GB",
    "date_of_birth": "1969-12-31"
}
field type flags description
id string(uuid) read-only Unique company identifier for the object. To be used where a Company identifier is required, such as creditor in a transaction.
soletrader_id string(uuid) read-only Unique identifier for the object. To be used where a SoleTrader identifier is required.
owner string(uuid) required Unique identifier of the user associated to the sole trader.
unique_id string required Unique identifier of the sole trader at your platform
vat_number string optional VAT number of the sole trader if available.
trading_name string required Company's name
trading_address string required Company's full address
trading_address_city string required Company's city
trading_address_postcode string required Company's postcode
trading_address_country country required Company's country
proprietor_name string required Proprietor's name
proprietor_address_line1 string required Proprietor's address including house number
proprietor_address_line2 string required Proprietor's address
proprietor_address_line3 string optional Proprietor's address
proprietor_address_city string required Proprietor's city
proprietor_address_postcode string required Proprietor's postcode
proprietor_address_country country required Proprietor's country
date_of_birth date required Proprietor's date of birth (e.g. 1969-12-31). Accepted format: YYYY-MM-DD.

Create a sole trader

Request

POST /v1/soletraders HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "owner": "user-KZcuB2oT6BPTjmQJiHm7ha",
  "trading_name": "The Dogfather",
  "trading_address": "123 Commercial St, Shoreditch",
  "trading_address_city": "London",
  "trading_address_postcode": "EC2A 8AB",
  "trading_address_country": "GB",
  "proprietor_name": "John John",
  "proprietor_address_line1": "Flat 5",
  "proprietor_address_line2": "10 Residential Street",
  "proprietor_address_line3": "Hackney",
  "proprietor_address_city": "London",
  "proprietor_address_postcode": "EC2 8AA",
  "proprietor_address_country": "GB",
  "vat_number": "15141312",
  "unique_id": "0d201ab1-46df-4274-8c90-256eaa66c136",
  "date_of_birth": "1969-12-31"
}
curl --request POST
  --url https://api-sandbox.hokodo.co/v1/soletraders \
  --header "Authorization: Token <your_api_key>" \
  --header 'Content-Type: application/json' \
  --data-binary "{
    \"owner\": \"user-KZcuB2oT6BPTjmQJiHm7ha\",
    \"trading_name\": \"The Dogfather\",
    \"trading_address\": \"123 Commercial St, Shoreditch\",
    \"trading_address_city\": \"London\",
    \"trading_address_postcode\": \"EC2A 8AB\",
    \"trading_address_country\": \"GB\",
    \"proprietor_name\": \"John John\",
    \"proprietor_address_line1\": \"Flat 5\",
    \"proprietor_address_line2\": \"10 Residential Street\",
    \"proprietor_address_line3\": \"Hackney\",
    \"proprietor_address_city\": \"London\",
    \"proprietor_address_postcode\": \"EC2 8AA\",
    \"proprietor_address_country\": \"GB\",
    \"vat_number\": \"15141312\",
    \"unique_id\": \"0d201ab1-46df-4274-8c90-256eaa66c136\",
    \"date_of_birth\": \"1969-12-31\"
}"

Responses

  • regular response
201 Created
Content-Type: application/json
{
  "id": "co-5oh3SJKQBaKMov9PYR7BkA",
  "owner": "user-mECT3e5n9i7gVGrbn2Pd38",
  "soletrader_id": "st-Vdrisa6GZnSp49ZaqMDssR",
  "trading_name": "The Dogfather",
  "trading_address": "123 Commercial St, Shoreditch",
  "trading_address_city": "London",
  "trading_address_postcode": "EC2A 8AB",
  "trading_address_country": "GB",
  "proprietor_name": "John John",
  "proprietor_address_line1": "Flat 5",
  "proprietor_address_line2": "10 Residential Street",
  "proprietor_address_line3": "Hackney",
  "proprietor_address_city": "London",
  "proprietor_address_postcode": "EC2 8AA",
  "proprietor_address_country": "GB",
  "vat_number": "15141312",
  "unique_id": "0d201ab1-46df-4274-8c90-256eaa66c136",
  "date_of_birth": "1969-12-31"
}
  • error response (example)
400 Bad Request
Content-Type: application/json
{
  "owner": [
    "Invalid pk \"user-KZcuB2oT6BPTjmQJiHm7hb\" - object does not exist."
  ],
  "unique_id": [
    "sole trader with this Unique identifier on platform already exists."
  ]
}

To create a sole trader, you create a SoleTrader object.

Errors

errors description
400 a required field is missing or some fields have incorrect values

List sole traders

Request

POST /v1/soletraders HTTP/1.1
Authorization: Token <your_api_key>
curl --request POST
  --url https://api-sandbox.hokodo.co/v1/soletraders \
  --header "Authorization: Token <your_api_key>"

Response

200 Ok
Content-Type: application/json
{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "co-5oh3SJKQBaKMov9PYR7BkA",
      "owner": "user-mECT3e5n9i7gVGrbn2Pd38",
      "soletrader_id": "st-Vdrisa6GZnSp49ZaqMDssR",
      "trading_name": "The Dogfather",
      "trading_address": "123 Commercial St, Shoreditch",
      "trading_address_city": "London",
      "trading_address_postcode": "EC2A 8AB",
      "trading_address_country": "GB",
      "proprietor_name": "John John",
      "proprietor_address_line1": "Flat 5",
      "proprietor_address_line2": "10 Residential Street",
      "proprietor_address_line3": "Hackney",
      "proprietor_address_city": "London",
      "proprietor_address_postcode": "EC2 8AA",
      "proprietor_address_country": "GB",
      "vat_number": "15141312",
      "unique_id": "0d201ab1-46df-4274-8c90-256eaa66c136",
      "date_of_birth": "1969-12-31"
    }
  ]
}

List all sole traders, created by your platform

View sole trader

Request

GET /v1/soletraders/<soletrader_id> HTTP/1.1
Authorization: Token <your_api_key>
curl --request GET
  --url https://api-sandbox.hokodo.co/v1/soletraders/co-5oh3SJKQBaKMov9PYR7BkA \
  --header "Authorization: Token <your_api_key>"

Response

200 Ok
Content-Type: application/json
{
  "id": "co-5oh3SJKQBaKMov9PYR7BkA",
  "owner": "user-mECT3e5n9i7gVGrbn2Pd38",
  "soletrader_id": "st-Vdrisa6GZnSp49ZaqMDssR",
  "trading_name": "The Dogfather",
  "trading_address": "123 Commercial St, Shoreditch",
  "trading_address_city": "London",
  "trading_address_postcode": "EC2A 8AB",
  "trading_address_country": "GB",
  "proprietor_name": "John John",
  "proprietor_address_line1": "Flat 5",
  "proprietor_address_line2": "10 Residential Street",
  "proprietor_address_line3": "Hackney",
  "proprietor_address_city": "London",
  "proprietor_address_postcode": "EC2 8AA",
  "proprietor_address_country": "GB",
  "vat_number": "15141312",
  "unique_id": "0d201ab1-46df-4274-8c90-256eaa66c136",
  "date_of_birth": "1969-12-31"
}

Retrieve a single sole trader, created by your platform

Errors

errors description
404 the soletrader_id is probably invalid, the sole trader has not been found

Modify sole trader

Request

PATCH /v1/soletraders/<soletrader_id> HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "trading_name": "The Catfather",
  "proprietor_name": "Johnny John"
}
curl --request PATCH
  --url https://api-sandbox.hokodo.co/v1/soletraders/co-5oh3SJKQBaKMov9PYR7BkA \
  --header "Authorization: Token <your_api_key>" \
  --header 'Content-Type: application/json' \
  --data-binary "{
    \"trading_name\": \"The Catfather\",
    \"proprietor_name\": \"Johnny John\"
}"

Response

200 Ok
Content-Type: application/json
{
  "id": "co-5oh3SJKQBaKMov9PYR7BkA",
  "owner": "user-mECT3e5n9i7gVGrbn2Pd38",
  "soletrader_id": "st-Vdrisa6GZnSp49ZaqMDssR",
  "trading_name": "The Catfather",
  "trading_address": "123 Commercial St, Shoreditch",
  "trading_address_city": "London",
  "trading_address_postcode": "EC2A 8AB",
  "trading_address_country": "GB",
  "proprietor_name": "Johnny John",
  "proprietor_address_line1": "Flat 5",
  "proprietor_address_line2": "10 Residential Street",
  "proprietor_address_line3": "Hackney",
  "proprietor_address_city": "London",
  "proprietor_address_postcode": "EC2 8AA",
  "proprietor_address_country": "GB",
  "vat_number": "15141312",
  "unique_id": "0d201ab1-46df-4274-8c90-256eaa66c136",
  "date_of_birth": "1969-12-31"
}

Modify previously created sole trader

Errors

errors description
404 the soletrader_id is probably invalid, the sole trader has not been found
400 a required field is missing or some fields have incorrect values

Organisations

Because Hokodo focuses on B2B sales, the buyers on your platform will consist of Companies, who have employees, and those employees may be organised into teams or departments. Hokodo deals with this complexity through the concept of Organisations and Users. A User is an individual employee at a company. An Organisation is a group of Users who are all able to see or take action on that company's orders on your platform. Each Organisation must be associated with a Company.

User roles within organisations

Users can have one of the following roles in an organisation:

Organisation endpoints

Organisation object

{
    "id": "org-9RxFsXTgnWqwjK4apxBAn8",
    "unique_id": "c105b862-f1ba-4197-9d97-57db63196b00",
    "registered": "2017-06-01T14:37:12Z",
    "name": "",
    "company": null,
    "users": []
}
field type flags description
id string(uuid) read-only API unique identifier for the organisation
unique_id string required Unique identifier of the organisation on your platform
registered datetime required When the organisation registered on your platform
name string optional Organisation name
company string optional Hokodo unique identifier of the company
users list read-only List of users attached to the organisation

Note that registered is the organisation's registration date on your platform, not with Hokodo.

Create an organisation

Request

POST /v1/organisations HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "unique_id": "c105b862-f1ba-4197-9d97-57db63196b00",
  "registered": "2017-06-01T14:37:12Z",
  "name": "My organisation",
  "company": "co-bqRyKAGaFrEEN8JMjWJiqk"
}
curl --request POST
  --url https://api-sandbox.hokodo.co/v1/organisations \
  --header "Authorization: Token <your_api_key>" \
  --header "Content-Type: application/json" \
  --data-binary "{
    \"unique_id\": \"c105b862-f1ba-4197-9d97-57db63196b00\",
    \"registered\": \"2017-06-01T14:37:12Z\",
    \"name\": \"My organisation\",
    \"company\": \"co-bqRyKAGaFrEEN8JMjWJiqk\"
}"

Responses

  • organisation created successfully
201 Created
Content-Type: application/json
{
    "id": "org-pHr6VCyzQJALUsePkatPBo",
    "unique_id": "c105b862-f1ba-4197-9d97-57db63196b00",
    "registered": "2017-06-01T14:37:12Z",
    "name": "My organisation",
    "company": "co-bqRyKAGaFrEEN8JMjWJiqk",
    "users": []
}
  • organisation already exists (identified by unique_id), it is updated
200 Ok
Content-Type: application/json
{
    "id": "org-pHr6VCyzQJALUsePkatPBo",
    "unique_id": "c105b862-f1ba-4197-9d97-57db63196b00",
    "registered": "2017-06-01T14:37:12Z",
    "name": "My organisation",
    "company": "co-bqRyKAGaFrEEN8JMjWJiqk",
    "users": []
}

To create an organisation, you create an Organisation object.

Errors

errors description
400 a required field is missing or a field has incorrect format

List organisations

Request

GET /v1/organisations HTTP/1.1
Authorization: Token <your_api_key>
curl --request GET
  --url https://api-sandbox.hokodo.co/v1/organisations \
  --header "Authorization: Token <your_api_key>"

Response

200 Ok
Content-Type: application/json
{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
        "id": "org-pHr6VCyzQJALUsePkatPBo",
        "unique_id": "c105b862-f1ba-4197-9d97-57db63196b00",
        "registered": "2017-06-01T14:37:12Z",
        "name": "My organisation",
        "company": "co-bqRyKAGaFrEEN8JMjWJiqk",
        "users": []
    }
  ]
}

List organisations created by your platform

View organisation

Request

GET /v1/organisations/<organisation_id> HTTP/1.1
Authorization: Token <your_api_key>
curl --request GET
  --url https://api-sandbox.hokodo.co/v1/organisations/org-pHr6VCyzQJALUsePkatPBo \
  --header "Authorization: Token <your_api_key>"

Response

200 Ok
Content-Type: application/json
{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": "org-pHr6VCyzQJALUsePkatPBo",
            "unique_id": "c105b862-f1ba-4197-9d97-57db63196b00",
            "registered": "2017-06-01T14:37:12Z",
            "name": "My organisation",
            "company": "co-bqRyKAGaFrEEN8JMjWJiqk",
            "users": []
        }
    ]
}

Retrieve an organisation created by your platform

Errors

errors description
404 the organisation_id is probably invalid, the organisation has not been found

Modify organisation

Request

PATCH /v1/organisations/<organisation_id> HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "unique_id": "c105b862-f1ba-4197-9d97-57db63196b01",
  "registered": "2018-06-01T14:37:12Z",
  "company": "co-bqRyKAGaFrEEN8JMjWJiqk"
}
curl --request PATCH
  --url https://api-sandbox.hokodo.co/v1/organisations/org-pHr6VCyzQJALUsePkatPBo \
  --header "Authorization: Token <your_api_key>" \
  --header "Content-Type: application/json" \
  --data-binary "{
    \"unique_id\": \"c105b862-f1ba-4197-9d97-57db63196b01\",
    \"registered\": \"2018-06-01T14:37:12Z"\,
    \"company\": \"co-bqRyKAGaFrEEN8JMjWJiqk\"
}"

Response

200 Ok
Content-Type: application/json
{
    "id": "org-pHr6VCyzQJALUsePkatPBo",
    "unique_id": "c105b862-f1ba-4197-9d97-57db63196b01",
    "registered": "2018-06-01T14:37:12Z",
    "name": "My organisation",
    "company": "co-bqRyKAGaFrEEN8JMjWJiqk",
    "users": []
}

Modify an organisation created by your platform

Errors

errors description
404 the organisation_id is probably invalid, the organisation has not been found
400 a required field is missing or a field has incorrect format

Delete an organisation

Request

DELETE /v1/organisations/<organisation_id> HTTP/1.1
Authorization: Token <your_api_key>
curl --request DELETE
  --url https://api-sandbox.hokodo.co/v1/organisations/org-pHr6VCyzQJALUsePkatPBo \
  --header "Authorization: Token <your_api_key>"

Responses

  • regular response
204 No Content
  • can not delete organisation, it has objects attached
409 Conflict
Content-Type: application/json
{
  "detail": "Organisation has undeletable objects attached, it cannot be deleted."
}

Delete an organisation created by your platform. Please note, that you can not delete an organisation that has payment-related objects attached to it (such as deferred payments or offers, etc.)

Errors

errors description
404 the organisation_id is probably invalid, the organisation has not been found
409 an organisation can not be deleted because it has objects attached to it

Manage users in organisation

Our API provides two alternative endpoint collections to manage relation between users and organisations. Below is the list of methods from the perspective of an organisation. For the list of methods from the perspective of a user, please refer to section Manage organisations of user

Organisation users endpoints

Organisation user object

{
  "id": "user-mECT3e5n9i7gVGrbn2Pd38",
  "email": "johnny@hokodo.co",
  "role": "admin"
}
field type flags description
id string(uuid) required API unique identifier for the user
email string read-only Email of the user
role role required Role of the user in the organisation

Add user to organisation

Request

POST /v1/organisations/<organisation_id>/users HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "id": "user-mECT3e5n9i7gVGrbn2Pd38",
  "role": "admin"
}
curl --request POST
  --url https://api-sandbox.hokodo.co/v1/organisations/org-pHr6VCyzQJALUsePkatPBo/users \
  --header "Authorization: Token <your_api_key>" \
  --header "Content-Type: application/json" \
  --data-binary "{
    \"id\": \"user-mECT3e5n9i7gVGrbn2Pd38\",
    \"role\": \"admin"\
}"

Responses

  • regular response
201 Created
Content-Type: application/json
{
  "id": "user-mECT3e5n9i7gVGrbn2Pd38",
  "email": "johnny@hokodo.co",
  "role": "admin"
}
  • user already added to the organisation
200 Ok
Content-Type: application/json
{
  "id": "user-mECT3e5n9i7gVGrbn2Pd38",
  "email": "johnny@hokodo.co",
  "role": "admin"
}
  • error (user not found and/or incorrect user role)
400 Bad Request
Content-Type: application/json
{
  "id": [
    "Invalid pk \"user-mECT3e5n9i7gVGrbn2Pd39\" - object does not exist."
  ],
  "role": [
    "\"reader\" is not a valid choice."
  ]
}

Attach previously created user to the organisation. When a user is already added to the organisation, but a different role is provided in the request, his existing role will be updated.

Users can have one of the following roles in an organisation:

To create a user, see the relevant section.

Errors

errors description
400 a required field is missing or a field has incorrect format

View users of organisation

Request

GET /v1/organisations/<organisation_id>/users HTTP/1.1
Authorization: Token <your_api_key>
curl --request GET
  --url https://api-sandbox.hokodo.co/v1/organisations/org-pHr6VCyzQJALUsePkatPBo/users \
  --header "Authorization: Token <your_api_key>"

Response

200 Ok
Content-Type: application/json
{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "user-mECT3e5n9i7gVGrbn2Pd38",
      "email": "johnny@hokodo.co",
      "role": "admin"
    }
  ]
}

List all current users of an organisation

View individual user of organisation

Request

GET /v1/organisations/<organisation_id>/users/<user_id> HTTP/1.1
Authorization: Token <your_api_key>
curl --request GET
  --url https://api-sandbox.hokodo.co/v1/organisations/org-pHr6VCyzQJALUsePkatPBo/users/user-mECT3e5n9i7gVGrbn2Pd38 \
  --header "Authorization: Token <your_api_key>"

Response

200 Ok
Content-Type: application/json
{
  "id": "user-mECT3e5n9i7gVGrbn2Pd38",
  "email": "johnny@hokodo.co",
  "role": "admin"
}

Retrieve one specific user of an organisation

Errors

errors description
404 the user_id is probably invalid, the user has not been found

Modify user role in organisation

Request

PATCH /v1/organisations/<organisation_id>/users/<user_id> HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "role": "member"
}
curl --request POST
  --url https://api-sandbox.hokodo.co/v1/organisations/org-pHr6VCyzQJALUsePkatPBo/users/user-mECT3e5n9i7gVGrbn2Pd38 \
  --header "Authorization: Token <your_api_key>" \
  --header "Content-Type: application/json" \
  --data-binary "{
    \"role\": \"member"\
}"

Responses

  • regular response
200 Ok
Content-Type: application/json
{
  "id": "user-mECT3e5n9i7gVGrbn2Pd38",
  "email": "johnny@hokodo.co",
  "role": "member"
}
  • error (incorrect user role)
400 Bad Request
Content-Type: application/json
{
  "role": [
    "\"reader\" is not a valid choice."
  ]
}

Modify the role of a specific user in an organisation

Errors

errors description
400 the role field is missing or has incorrect value

Remove user from organisation

Request

DELETE /v1/organisations/<organisation_id>/users/<user_id> HTTP/1.1
Authorization: Token <your_api_key>
curl --request DELETE
  --url https://api-sandbox.hokodo.co/v1/organisations/org-pHr6VCyzQJALUsePkatPBo/users/user-mECT3e5n9i7gVGrbn2Pd38 \
  --header "Authorization: Token <your_api_key>"

Response

204 No Content

Remove one specific user from the organisation

Errors

errors description
404 the user_id is probably invalid, the user has not been found

Users

Users represent the individual customers on your platform. They are associated to one or multiple organisations, which themselves represent the company of these customers. A user can have different roles and permissions in each organisation.

Users not linked to an organisation cannot access orders, payment offers or deferred payments. Therefore, we suggest creating the organisation first, then create users linked to the organisation with the proper role.

User endpoints

User object

{
  "id": "user-VG4i93EPLRamVFK6oXpvt9",
  "email": "johnny@hokodo.co",
  "unique_id": "",
  "name": "John",
  "phone": "",
  "registered": "2017-06-01T14:37:12Z",
  "organisations": [
    {
      "id": "org-FEjrdMsmhdNp34HxaZ6n63",
      "role": "member"
    }
  ]
}
field type flags description
id string(uuid) read-only API unique identifier for the user
email string required Email of the user
unique_id string optional Unique identifier of the user on your platform (currently we don't validate its uniqueness and store it for your reference only)
name string required Full name of the user
phone string optional Phone number of the user
registered datetime required Date of user registration on your platform
organisations list optional List of organisations to which the user is linked (can be empty)
organisations[*][id] string(uuid) required API identifier of the organisation
organisations[*][role] role required Role of the user in the organisation

Note that registered is the user's registration date on your platform, not with Hokodo.

Create a user

Request

POST /v1/users HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "name": "John",
  "email": "johnny@hokodo.co",
  "registered": "2017-06-01T14:37:12Z",
  "organisations": [
    {
      "id": "org-FEjrdMsmhdNp34HxaZ6n63",
      "role": "member"
    }
  ]
}
curl --request POST \
  --url https://api-sandbox.hokodo.co/v1/users \
  --header "Authorization: Token <your_api_key>"
  --header "Content-Type: application/json"
  --data-binary="{
    \"name\": \"John\",
    \"email\": \"johnny@hokodo.co\",
    \"registered\": \"2017-06-01T14:37:12Z\",
    \"organisations\": [
      {
        \"id\": \"org-FEjrdMsmhdNp34HxaZ6n63\",
        \"role\": \"member\"
      }
    ]
}"

Response

  • regular response
201 Created
Content-Type: application/json
{
  "id": "user-VG4i93EPLRamVFK6oXpvt9",
  "email": "johnny@hokodo.co",
  "unique_id": "",
  "name": "John",
  "phone": "",
  "registered": "2017-06-01T14:37:12Z",
  "organisations": [
    {
      "id": "org-FEjrdMsmhdNp34HxaZ6n63",
      "role": "member"
    }
  ]
}
  • error response
400 Bad Request
Content-Type: application/json
{
  "email": [
    "This field is required."
  ],
  "name": [
    "This field is required."
  ],
  "registered": [
    "This field is required."
  ]
}

To create a user, you create a User object.

Note: Repeated POST requests with user information that contains the same email address will trigger partial updates on the existing user. Any organisations in this list will be appended to the list of organisations the user is already a member of. If the list includes an organisation the user is currently a member of, but with a different role, the user's role will be updated to the latest received.

errors description
400 a required field is missing

List users

Request

GET /v1/users HTTP/1.1
Authorization: Token <your_api_key>
curl --request GET \
  --url https://api-sandbox.hokodo.co/v1/users \
  --header "Authorization: Token <your_api_key>"

Response

200 OK
Content-Type: application/json
{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "user-mECT3e5n9i7gVGrbn2Pd38",
      "email": "johnny@hokodo.co",
      "unique_id": "",
      "name": "John",
      "phone": "",
      "registered": "2017-06-01T14:37:12Z",
      "organisations": [
        {
          "id": "org-FEjrdMsmhdNp34HxaZ6n63",
          "role": "member"
        }
      ]
    }
  ]
}

List all users associated with your platform.

Get user

Request

GET /v1/users/<user_id> HTTP/1.1
Authorization: Token <your_api_key>
curl --request GET \
  --url https://api-sandbox.hokodo.co/v1/users/user-mECT3e5n9i7gVGrbn2Pd38 \
  --header "Authorization: Token <your_api_key>"

Response

  • regular response
200 OK
Content-Type: application/json
{
  "id": "user-mECT3e5n9i7gVGrbn2Pd38",
  "email": "johnny@hokodo.co",
  "unique_id": "",
  "name": "John",
  "phone": "",
  "registered": "2017-06-01T14:37:12Z",
  "organisations": [
    {
      "id": "org-FEjrdMsmhdNp34HxaZ6n63",
      "role": "member"
    }
  ]
}
  • user not found
404 Not Found
Content-Type: application/json
{
  "detail": "Not found."
}

Look up a previously created user.

errors description
404 the user_id is probably invalid, the user has not been found

Modify user

Request

PATCH /v1/users/<user_id> HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "id": "user-mECT3e5n9i7gVGrbn2Pd38",
  "unique_id": "some-unique-id",
  "name": "Johnny",
  "phone": "+1234567890",
  "registered": "2018-06-01T14:37:10Z"
}

Response

200 OK
Content-Type: application/json
{
  "id": "user-mECT3e5n9i7gVGrbn2Pd38",
  "email": "johnny@hokodo.co",
  "unique_id": "some-unique-id",
  "name": "Johnny",
  "phone": "+1234567890",
  "registered": "2018-06-01T14:37:10Z",
  "organisations": [
    {
      "id": "org-FEjrdMsmhdNp34HxaZ6n63",
      "role": "member"
    }
  ]
}

Update a previously created user.

User emails are read-only and cannot be modified through the API. To update a buyer email, please contact support@hokodo.co.

Please note that the organisations list appends to the user's existing organisations list. Supplying an existing organisation in the list will update the user's role on that organisation.

errors description
404 the user_id is probably invalid, the user has not been found
400 updating a user failed or some of the fields have incorrect format

Delete user

Request

DELETE /v1/users/<user_id> HTTP/1.1
Authorization: Token <your_api_key>
curl --request DELETE \
  --url https://api-sandbox.hokodo.co/v1/users/user-mECT3e5n9i7gVGrbn2Pd38 \
  --header "Authorization: Token <your_api_key>"

Response

  • regular response
204 No Content
  • user not found
404 Not Found
Content-Type: application/json
{
  "detail": "Not found."
}

Delete a previously created user.

Errors

errors description
404 the user_id is probably invalid, the user has not been found

Manage organisations of user

You can manage users' memberships and roles in various organisations. Please refer to section Organisations regarding creating and managing organisations.

Our API provides two alternative endpoint collections to manage relations between users and organisations. Below is the list of methods from the perspective of a user. For the list of methods from the perspective of an organisation, please refer to section Manage users in organisation

User organisations endpoints

User organisation object

{
  "id": "org-pHr6VCyzQJALUsePkatPBo",
  "role": "admin"
}
field type flags description
id string(uuid) required API unique identifier for the organisation
role role required Role of the user in the organisation

Add user to organisation

Request

POST /v1/users/<user_id>/organisations HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "id": "org-pHr6VCyzQJALUsePkatPBo",
  "role": "admin"
}
curl --request POST
  --url https://api-sandbox.hokodo.co/v1/users/user-mECT3e5n9i7gVGrbn2Pd38/organisations \
  --header "Authorization: Token <your_api_key>" \
  --header "Content-Type: application/json" \
  --data-binary "{
    \"id\": \"org-pHr6VCyzQJALUsePkatPBo\",
    \"role\": \"admin"\
}"

Responses

  • regular response
201 Created
Content-Type: application/json
{
  "id": "org-pHr6VCyzQJALUsePkatPBo",
  "role": "admin"
}
  • user already added to the organisation
200 Ok
Content-Type: application/json
{
  "id": "org-pHr6VCyzQJALUsePkatPBo",
  "role": "admin"
}
  • error (organisation not found and/or incorrect user role)
400 Bad Request
Content-Type: application/json
{
  "id": [
    "Invalid pk \"org-mECT3e5n9i7gVGrbn2Pd39\" - object does not exist."
  ],
  "role": [
    "\"reader\" is not a valid choice."
  ]
}

Attach existing user to a previously created organisation. When a user is already added to the organisation, but a different role is provided in the request, his existing role will be updated.

To create a user, see the relevant section.

Errors

errors description
400 a required field is missing or a field has incorrect format

View organisations of a user

Request

GET /v1/users/<user_id>/organisations HTTP/1.1
Authorization: Token <your_api_key>
curl --request GET
  --url https://api-sandbox.hokodo.co/v1/users/user-mECT3e5n9i7gVGrbn2Pd38/organisations \
  --header "Authorization: Token <your_api_key>"

Response

200 Ok
Content-Type: application/json
{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "org-pHr6VCyzQJALUsePkatPBo",
      "role": "admin"
    }
  ]
}

List all organisations of a user

View individual organisation of user

Request

GET /v1/users/<user_id>/organisations/<organisation_id> HTTP/1.1
Authorization: Token <your_api_key>
curl --request GET
  --url https://api-sandbox.hokodo.co/v1/users/user-mECT3e5n9i7gVGrbn2Pd38/organisations/org-pHr6VCyzQJALUsePkatPBo \
  --header "Authorization: Token <your_api_key>"

Response

200 Ok
Content-Type: application/json
{
  "id": "org-pHr6VCyzQJALUsePkatPBo",
  "role": "admin"
}

Retrieve one specific organisation of a user

Errors

errors description
404 the organisation_id is probably invalid, the organisation has not been found

Modify user role in organisation

Request

PATCH /v1/users/<user_id>/organisations/<organisation_id> HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "role": "member"
}
curl --request POST
  --url https://api-sandbox.hokodo.co/v1/users/user-mECT3e5n9i7gVGrbn2Pd38/organisations/org-pHr6VCyzQJALUsePkatPBo \
  --header "Authorization: Token <your_api_key>" \
  --header "Content-Type: application/json" \
  --data-binary "{
    \"role\": \"member"\
}"

Responses

  • regular response
200 Ok
Content-Type: application/json
{
  "id": "org-pHr6VCyzQJALUsePkatPBo",
  "role": "member"
}
  • error (incorrect user role)
400 Bad Request
Content-Type: application/json
{
  "role": [
    "\"reader\" is not a valid choice."
  ]
}

Modify the role of the user in a specific organisation

Errors

errors description
400 the role field is missing or has incorrect value

Remove user from organisation

Request

DELETE /v1/users/<user_id>/organisations/<organisation_id> HTTP/1.1
Authorization: Token <your_api_key>
curl --request DELETE
  --url https://api-sandbox.hokodo.co/v1/users/user-mECT3e5n9i7gVGrbn2Pd38/organisations/org-pHr6VCyzQJALUsePkatPBo \
  --header "Authorization: Token <your_api_key>"

Response

204 No Content

Remove the user from a specific organisation

Errors

errors description
404 the organisation_id is probably invalid, the organisation has not been found

Credit Limits

Depending on the customer's company, the history of their orders and repayments, Hokodo can offer them deferred payments.

There are two situations where you might want to check whether one of your customers can obtain credit.

  1. Your customer is at the checkout, and you want to check if that particular purchase is eligible for deferred payment. To do that, you use the Orders endpoint to inform Hokodo about the purchase, and the Payment Offers endpoint to check eligibility of the Order.

  2. Your customer has not decided what they want to purchase, but you may wish to proactively inform them that they will be eligible for Deferred Payment. For example, you could display a banner at the top of the page with their credit limit or perhaps add a credit limit section to their "My Account" page. The CreditLimit endpoint is designed for this second situation.

To find out your customer's credit limit, please use the following endpoint, with the associated customer Company in the URL.

POST /v1/payment/credit_limits/company/<company_id>

You will get one of the two possible responses:

Credit limits endpoint

Credit limit object

{
    "company": "co-74cgmhG9U79oTWGEW4jeDW",
    "status": "eligible",
    "rejection_reason": null,
    "credit_limit": {
        "currency": "GBP",
        "amount_available": "987654",
        "amount_in_use": "123456",
        "amount": "1111110"
    }
}
field type description
company string(uuid) API unique identifier for the company
status string Current credit approval status (eligible or declined)
rejection_reason dictionary If status is declined, details about why, otherwise null
credit_limit dictionary Current credit limit if approved
credit_limit[currency] currency ISO 4217 currency code (e.g. GBP, EUR)
credit_limit[amount_available] int Credit limit currently available, in minor units (cents/pence)
credit_limit[amount_in_use] int Credit limit currently in use, in minor units (cents/pence)
credit_limit[amount] int Total credit limit, in minor units (cents/pence)

Please note that in general the amount will equal amount_available plus amount_in_use.

Therefore, it’s better to only share amount_available and amount_in_use with the customer.

Request company credit limit

Requests

POST /v1/payment/credit_limits/company/co-74cgmhG9U79oTWGEW4jeDW/ HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "currency": "GBP"
}
curl --request POST \
  --url https://api-sandbox.hokodo.co/v1/payment/credit_limits/company/co-74cgmhG9U79oTWGEW4jeDW/ \
  --header "Authorization: Token <your_api_key>" \
  --header "Content-Type: application/json" \
  --data-binary '{
  "currency": "GBP"
}'

Responses

  • eligible
200 OK
Content-Type: application/json
{
    "company": "co-74cgmhG9U79oTWGEW4jeDW",
    "status": "eligible",
    "rejection_reason": null,
    "credit_limit": {
        "currency": "GBP",
        "amount_available": "987654",
        "amount_in_use": "123456",
        "amount": "1111110"
    }
}
  • declined
200 OK
Content-Type: application/json
{
    "company": "co-74cgmhG9U79oTWGEW4jeDW",
    "status": "declined",
    "rejection_reason": {
      "code": "buyer-country",
      "detail": "We're currently unable to provide payment plans to Buyers domiciled in {debtor_country}.",
      "params": {
        "debtor_country": "Ireland"
      }
    },
    "credit_limit": {
        "currency": "GBP",
        "amount_available": null,
        "amount_in_use": "123456",
        "amount": null
    }
}

The currency is optional in the request, and defaults to EUR if not provided.

It is advisable to request the credit limit in the currency used by the company in question. For example, use "currency": "GBP" when requesting the credit limit of a UK company.

field type description
currency currency Desired currency for the credit limit, as a ISO 4217 currency code (e.g. GBP, EUR)

Errors

errors description
400 A field is not in the expected format

Credit Limits (Legacy)

Depending on the customer's company, the history of their orders and repayments, Hokodo can offer them deferred payments.

There are two situations where you might want to check whether one of your customers can obtain credit.

  1. Your customer is at the checkout, and you want to check if that particular purchase is eligible for deferred payment. To do that, you use the Orders endpoint to inform Hokodo about the purchase, and the Payment Offers endpoint to check eligibility of the Order.

  2. Your customer has not decided what they want to purchase, but you may wish to proactively inform them that they will be eligible for Deferred Payment. For example, you could display a banner at the top of the page with their credit limit or perhaps add a credit limit section to their "My Account" page. The CreditLimit endpoint is designed for this second situation.

To find out your customer's credit limit, please use the following endpoint, with the associated customer Company in the URL.

GET /v1/payment/credit_limits/company/<company_id>

You will get one of the two possible responses:

CreditLimit endpoints

CreditLimit object

{
    "company": "co-74cgmhG9U79oTWGEW4jeDW",
    "status": "eligible",
    "current_credit_limit": {
        "currency": "GBP",
        "amount": 200000,
        "amount_in_use": 99700,
        "amount_available": 100300
    },
    "credit_limit_history": [
        {
            "valid_from": "2020-07-16T08:44:49.059Z",
            "valid_to": null,
            "currency": "GBP",
            "amount": 200000
        },
        {
            "valid_from": "2020-06-02T09:12:34.059Z",
            "valid_to": "2020-07-16T08:44:49.059Z",
            "currency": "GBP",
            "amount": 150000
        },
        {
            "valid_from": "2020-05-18T18:18:18.059Z",
            "valid_to": "2020-06-02T09:12:34.059Z",
            "currency": "GBP",
            "amount": 100000
        }
    ]
}
field type flags description
company string(uuid) required API unique identifier of the associated company
status string read-only Current credit approval status (eligible or declined)
current_credit_limit dictionary read-only Current credit limit if approved
current_credit_limit[currency] string read-only ISO 4217 currency code (e.g. GBP, EUR)
current_credit_limit[amount] int read-only Total credit limit available, in cents
current_credit_limit[amount_in_use] int read-only Credit limit currently in use by deferred payments, in cents
current_credit_limit[amount_available] int read-only Credit limit currently available, in cents
credit_limit_history list read-only Current credit limit if approved
credit_limit_history[*][currency] string read-only ISO 4217 currency code (e.g. GBP, EUR)
credit_limit_history[*][amount] int read-only Total credit limit available, in cents
credit_limit_history[*][valid_from] datetime read-only From when the historical credit limit was valid
credit_limit_history[*][valid_to] datetime read-only Until when the historical credit limit was valid

Request a new Credit approval and limit

Request

GET /v1/payment/credit_limits/company/{company_id} HTTP/1.1
Content-Type: application/json
curl --request GET \
  --url https://api-sandbox.hokodo.co/v1/payment/credit_limits/company/{company_id} \
  --header "Content-Type: application/json"

Responses

  • Customer rejected
200 OK
Content-Type: application/json
{
    "company": "co-74cgmhG9U79oTWGEW4jeDW",
    "status": "declined",
    "current_credit_limit": null,
    "credit_limit_history": []
}
  • Customer accepted
200 OK
Content-Type: application/json
{
    "company": "co-74cgmhG9U79oTWGEW4jeDW",
    "status": "eligible",
    "current_credit_limit": {
        "currency": "GBP",
        "amount": 200000,
        "amount_in_use": 99700,
        "amount_available": 100300
    },
    "credit_limit_history": [
        {
            "valid_from": "2020-07-16T08:44:49.059Z",
            "valid_to": null,
            "currency": "GBP",
            "amount": 200000
        },
        {
            "valid_from": "2020-06-02T09:12:34.059Z",
            "valid_to": "2020-07-16T08:44:49.059Z",
            "currency": "GBP",
            "amount": 150000
        },
        {
            "valid_from": "2020-05-18T18:18:18.059Z",
            "valid_to": "2020-06-02T09:12:34.059Z",
            "currency": "GBP",
            "amount": 100000
        }
    ]
}

This endpoint is used to query credit approval and credit limits for your customer. The only required field is company, in the URL.

It returns:

field type flags description
company string(uuid) required API unique identifier of the customer company queried

Merchant Limits

Hokodo allows you to top-up your buyer's credit limit at your own risk. You do this by setting limits for specific buyers, called Merchant Limits. These are your limits for the buyers.

Merchant Limits apply on top of the Hokodo credit limit. A buyer with a Hokodo credit limit of €400 and a Merchant Limit of €200 can borrow €600 in total.

Funds lent using Merchant Limits are still financed by Hokodo, and we still attempt to recover non-payment from the buyer using our collections process. Any non-payment that cannot be recovered is subtracted from your Payouts.

There are two kinds of Merchant Limits:

The limit applied to a particular buyer is determined in the following order of precedence:

  1. The per-buyer limit for this buyer, if one exists.
  2. The default limit, if one exists.
  3. If neither is set, the limit is 0.

Merchant Limit object

{
  "currency": "GBP",
  "limits": {
    "GBP": 200000,
    "EUR": 227946,
    "USD": 263710
  },
  "is_active": true
}
field type description
currency string Currency the limit was set in (ISO 4217 code)
limits dictionary Total limits, provided in various currencies
limits["GBP"] int Total limit expressed in GBP, in minor units (pence)
limits["EUR"] int Total limit expressed in EUR, in minor units (cents)
limits["USD"] int Total limit expressed in USD, in minor units (cents)
is_active boolean If false, this limit does not apply

Limits are set in one particular currency, determined by the currency field. The entries in limits are converted from that currency using Hokodo's exchange rates, to allow you to know the exact limit applied in each currency.

Per-buyer endpoints

Default limits endpoints

Default Merchant Limits are set and retrieved separately from the per-buyer limits.

Get merchant limit

If no Merchant Limit has been set, this endpoint returns an HTTP 404 status code.

Errors

errors description
404 No per-buyer limit exists for this company_id

Requests

GET /v1/payment/merchant_limits/company/<company_id>/ HTTP/1.1
Authorization: Token <your_api_key>
curl --request GET \
  --url https://api-sandbox.hokodo.co/v1/payment/merchant_limits/company/co-74cpmhG9U79aTWGEW4je2W/ \
  --header "Authorization: Token <your_api_key>"

Responses

200 OK
Content-Type: application/json
{
  "currency": "GBP",
  "limits": {
    "GBP": 200000,
    "EUR": 227946,
    "USD": 263710
  },
  "is_active": true
}

Create or Update a merchant limit

In order to set a Merchant Limit, make a PUT request containing the currency, limit and is_active.

field type description
currency string Currency the limit applies to (ISO 4217 code)
limit dictionary Total limits, provided in various currencies
is_active boolean If false, this limit does not apply

Errors

errors description
400 A field is not in the expected format

Requests

PUT /v1/payment/merchant_limits/company/<company_id>/ HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "currency": "EUR",
  "is_active": true,
  "limit": 1000
}
curl --request PUT \
  --url https://api-sandbox.hokodo.co/v1/payment/merchant_limits/company/co-74cpmhG9U79aTWGEW4je2W/ \
  --header "Authorization: Token <your_api_key>" \
  --header "Content-Type: application/json" \
  --data-binary '{
    "currency": "EUR",
    "is_active": true,
    "limit": 1000
}'

Responses

200 OK
Content-Type: application/json
{
  "currency": "EUR",
  "limits": {
    "GBP": 877,
    "EUR": 1000,
    "USD": 1156
  },
  "is_active": true
}

Delete a merchant limit

In order to delete a merchant limit, make a DELETE request to the per-buyer or default limit endpoint.

Deleting a limit has the same effect as setting "is_active": false, but the record of the limit will also be removed. Subsequent GET requests to this endpoint will return an HTTP 404 status code.

DELETE /v1/payment/merchant_limits/company/<company_id>/ HTTP/1.1
Authorization: Token <your_api_key>
curl --request DELETE \
  --url https://api-sandbox.hokodo.co/v1/payment/merchant_limits/company/co-74cpmhG9U79aTWGEW4je2W/ \
  --header "Authorization: Token <your_api_key>"

Responses

200 OK
Content-Type: application/json
{
  "currency": "EUR",
  "limits": {
    "GBP": 877,
    "EUR": 1000,
    "USD": 1156
  },
  "is_active": true
}

Billing Accounts

If the order frequency is above 5 or 10 transactions per buyer per month, we would recommend Billing Accounts for your Buyers. Billing Accounts govern the generation of Statements of Account. Statements of account list all the Captures and Refunds from a given period.

This encourages buyers to pay Statements rather than the individual invoices. That way, buyers only need to reconcile one bank statement line item with the Hokodo Statement for the month’s business, rather than reconcile many bank line items with many invoices. We also provide a .csv file along with the statement files so that buyers can reconcile the Statement contents with their own systems.

Billing account endpoints

There are also endpoints to get the Billing Accounts for a particular Company or Organisation:

Billing Account object

{
    "id": "ba-5SvfKbhh8WsFdCp8p54eie",
    "active": true,
    "created": "2023-08-30T16:29:06.852559Z",
    "modified": "2023-08-30T16:29:06.852619Z",
    "deactivated": null,
    "organisations": [
        "org-cPJRZJJiQ7prk4yHYQY6TK"
    ],
    "emails": {
        "to": [
            "invoices@restaurant.com"
        ],
        "cc": [
            "secondary@restaurant.com"
        ]
    },
    "payment_terms": "1m"
}
field type flags description
id string(uuid) read-only API unique identifier for the billing account
active boolean If the billing account is active
created datetime read-only Creation date
modified datetime read-only Modification date
deactivated datetime read-only Deactivation date
organisations list[organisation] required The list of the organisations link to that billing account
organisation string(uuid) required Organisation id
emails dictionary required Email addresses that will be sent the statements
emails[to] list[string] required but can be empty Emails "to"
emails[cc] list[string] required but can be empty Emails "cc"
payment_terms string required Payment Terms

Payment terms

There are three possible values of payment_terms:

This refers to the billing period. The exact details of the payment terms are specific to each merchant and configured by your Solutions Engineer during onboarding. These details include:

Create a billing account

Request

POST /v1/payment/billing_accounts HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>
{
  "organisations": ["org-idcPJRZJJiQ7prk4yHYQY6TK"],
    "emails": {
        "to": ["invoices@restaurant.com"],
        "cc": ["secondary@restaurant.com"]
    },
    "payment_terms": "1m"
}
curl --request POST \
     --url https://api-sandbox.hokodo.co/v1/payment/billing_accounts \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>" \
     --data-binary '{
  "organisations": ["org-idcPJRZJJiQ7prk4yHYQY6TK"],
    "emails": {
        "to": ["invoices@restaurant.com"],
        "cc": ["secondary@restaurant.com"]
    },
    "payment_terms": "1m"
}'

Responses

  • success response
201 Created
Content-Type: application/json
{
    "id": "ba-5SvfKbhh8WsFdCp8p54eie",
    "active": true,
    "created": "2023-08-30T16:29:06.852559Z",
    "modified": "2023-08-30T16:29:06.852619Z",
    "deactivated": null,
    "organisations": [
        "org-idcPJRZJJiQ7prk4yHYQY6TK"
    ],
    "emails": {
        "to": [
            "invoices@restaurant.com"
        ],
        "cc": [
            "secondary@restaurant.com"
        ]
    },
    "payment_terms": "1m"
}
  • error response (example)
400 Bad Request
Content-Type: application/json
{
    "organisations": [
        "Invalid pk \"org-Gy4sQUpNddgyLAma3h8WQ3\" - object does not exist."
    ],
    "to": {
        "0": [
            "Enter a valid email address."
        ]
    },
    "payment_terms": [
        "You don't have billing account terms set up for period '7d'"
    ]
}

Errors

errors description
400 A required field is missing or some of the fields have incorrect values

List billing accounts

Request

GET /v1/payment/billing_accounts HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>
curl --request GET \
     --url https://api-sandbox.hokodo.co/v1/payment/billing_accounts \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>"

Response

200 Ok
Content-Type: application/json
{
    "count": 3,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": "ba-5SvfKbhh8WsFdCp8p54eie",
            "active": true,
            "created": "2023-08-30T16:29:06.852559Z",
            "modified": "2023-08-30T16:29:06.852619Z",
            "deactivated": null,
            "organisations": [
                "org-idcPJRZJJiQ7prk4yHYQY6TK", "org-Gy4sQUpNddgyLAma3h8WQ3"
            ],
            "emails": {
                "to": [
                    "Happy@southrestaurant.com"
                ],
                "cc": []
            },
            "payment_terms": "7d"
        },
        {
            "id": "ba-hofiCfoZN64KJQoq8kDfRf",
            "active": false,
            "created": "2023-06-30T16:29:06.852559Z",
            "modified": "2023-06-30T16:29:06.852619Z",
            "deactivated": null,
            "organisations": [
                "org-idcPJRZJJiQ7prk4yHYQY6TK", "org-Gy4sQUpNddgyLAma3h8WQ3"
            ],
            "emails": {
                "to": [
                    "Happy@southrestaurant.com"
                ],
                "cc": []
            },
            "payment_terms": "1m"
        },
        {
            "id": "ba-qeDkPMCYufuXpH6qA2qvqh",
            "active": true,
            "created": "2023-05-30T16:25:43.335278Z",
            "modified": "2023-05-30T16:25:43.335340Z",
            "deactivated": null,
            "organisations": [
                "org-idcPJRZJJiQ7prk4yHYQY6TK"
            ],
            "emails": {
                "to": [
                    "giselle@westrestaurant.com"
                ],
                "cc": [
                    "denis@westrestaurant.com"
                ]
            },
            "payment_terms": "1m"
        }
    ]
}

List billing accounts created by your platform

List for a particular company or organisation

These endpoints will list only the billing accounts for the given company or organisation:

Filters and ordering

You can order by:

You can filter on:

And combine both:

GET /v1/payment/billing_accounts?ordering=deactivated&active=false

View billing account

Requests

  • request one billing account
GET /v1/payment/billing_accounts/<billing_account_id> HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>
curl --request GET \
     --url https://api-sandbox.hokodo.co/v1/payment/billing_accounts/<billing_account_id> \
     --header "Authorization: <your_api_key>"

Responses

  • Success response with optional expansion
200 Ok
Content-Type: application/json
{
    "id": "ba-G4Xm4PHferPqdQhi8AQgW5",
    "active": false,
    "created": "2023-08-25T13:18:50.268382Z",
    "modified": "2023-08-30T09:32:34.380213Z",
    "deactivated": "2023-08-30T09:32:34.380090Z",
    "organisations": [
        "org-EzhfgufFRozsLMBMKqkcaQ"
    ],
    "emails": {
        "to": [
            "a_mail@restaurant.com",
            "another_mail@restaurant.com"
        ],
        "cc": []
    },
    "payment_terms": "1m"
}
  • billing account not found
404 Not Found
Content-Type: application/json
{
  "detail": "Not found."
}

Errors

errors description
404 The billing_account_id is probably invalid, the billing account has not been found

Modify billing account

Change emails

If you change the emails, the whole dictionary of emails will be replaced with the dictionary you provide (to and cc)

Request Example: Update emails

PATCH /v1/payment/billing_accounts/<billing_account_id> HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>
{
    "emails": {
        "to": ["a_mail@restaurant.com", "another_mail@restaurant.com"],
        "cc": []
    }
}
curl --request PATCH \
     --url https://api-sandbox.hokodo.co/v1/payment/billing_accounts/<billing_account_id> \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>" \
     --data-binary '{
    "emails": {
        "to": ["a_mail@restaurant.com", "another_mail@restaurant.com"],
        "cc": []
    }
}'

Response

200 Ok
Content-Type: application/json
{
    "id": "ba-G4Xm4PHferPqdQhi8AQgW5",
    "created": "2023-08-25T13:18:50.268382Z",
    "modified": "2023-08-25T13:20:20.465257Z",
    "deactivated": null,
    "organisations": [
        "org-EzhfgufFRozsLMBMKqkcaQ"
    ],
    "emails": {
        "to": [
            "a_mail@restaurant.com",
            "another_mail@restaurant.com"
        ],
        "cc": []
    },
    "payment_terms": "1m"
}

Errors

errors description
400 A required field is missing or some of the fields have incorrect values
409 The billing account has been deactivated and cannot be updated

Deactivate a billing account

You can deactivate a billing account.

Deactivated billing accounts do not generate new Statements. The existing open statement will be closed on its close_date as usual, and its statement emails will be sent out.

Deactivated billing accounts cannot be re-activated.

Request deactivate billing account

PATCH /v1/payment/billing_accounts/<billing_account_id> HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>
{
    "active": false
}
curl --request PATCH \
     --url https://api-sandbox.hokodo.co/v1/payment/billing_accounts/<billing_account_id> \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>" \
     --data-binary '{
    "active": false
}'

Response

200 Ok
Content-Type: application/json
{
    "id": "ba-XepNnfJe3QQ4wXCfYY4Uq3",
    "active": false,
    "created": "2023-09-01T14:00:25.744124Z",
    "modified": "2023-09-01T14:09:52.101054Z",
    "deactivated": "2023-09-01T14:09:52.100968Z",
    "organisations": [
        "org-jqCceJQ9QeiH8n3H4Fakk7"
    ],
    "emails": {
        "to": [
            "invoices@restaurant.com"
        ],
        "cc": [
            "secondary@restaurant.com"
        ]
    },
    "payment_terms": "1m"
}

Errors

errors description
400 A required field is missing or some of the fields have incorrect values
409 The billing account has already been deactivated

Modify a deactivated billing account

Once a billing account has been deactivated, it is read-only. It cannot re-activated nor modified.

409 Conflict
Content-Type: application/json
{
    "detail": "Billing account cannot be updated because it has been deactivated (2023-09-01 14:09:52.100968+00:00)"
}

Orders

An order describes an instance of buying or selling something on your platform. An order consists of a basket of order items, plus details about the company making the purchase. Orders can be paid for at the time of the order or benefit from credit terms.

Orders serve two purposes in an integration with Hokodo:

a) Orders can be used to inform Hokodo about purchases the customer has made on your platform which Hokodo was not involved in. For example, you may have given the customer trade credit in the past, which has been successfully settled. Or the customer may have made purchases which were settled upfront (e.g. paid by card). Both of these are indicators which enhance our confidence that this is a genuine client and are favourable risk indicators. So providing Hokodo with data on these orders helps us to assess the customer's creditworthiness and to set the right credit limits for them.

b) You will also create an order when a customer shops on your platform so that you can obtain Deferred Payment Offers from Hokodo.

As we explain below, there are some commonalities between use cases a) and b) – for example in both cases we need to know who the buyer was, the value of the order, the date of the order etc. But there are also some differences. For example when you inform us about historical orders, you would tell us what payment terms were involved, whereas when you create an order for the purposes of getting deferred payment offers, Hokodo will be determining the payment terms via the offers we return.

Having more of the orders of the customers allows us to provide finer and higher credit limits, as well as reduce fraud.

Order endpoints

Order Documents

There are also post-sale order endpoints described in a dedicated section:

Order object

{
  "url": "https://api-sandbox.hokodo.co/v1/payment/orders/order-yQKxbtCg9aTS5JYnsRVA9B",
  "id": "order-yQKxbtCg9aTS5JYnsRVA9B",
  "unique_id": "876987-987uinjojna-I8UH98Jnj",
  "customer": {
    "organisation": "org-...",
    "user": "user-...",
    "type": "registered", # or "guest"
    "delivery_address": {
      "name": "John Smith",
      "company_name": "",
      "address_line1": "1 Station Street",
      "address_line2": "Flat B",
      "address_line3": "",
      "city": "London",
      "region": "",
      "postcode": "SE11 6NQ",
      "country": "GB",
      "phone": "",
      "email": ""
    },
     "invoice_address": {
      "name": "John Smith",
      "address_line1": "1 Station Street",
      "address_line2": "Flat B",
      "city": "London",
      "postcode": "SE11 6NQ",
      "country": "GB"
    }
  },
  "status": "pending",
  "pay_method": "directdebit",
  "currency": "GBP",
  "total_amount": 12000,  # total amount including tax
  "tax_amount": 2000,  # tax amount
  "order_date": "2018-04-25",
  "invoice_date": "2018-04-25",
  "due_date": "2018-05-25",
  "paid_date": "2018-05-27",
  "items": [
    {
      "item_id": "1",
      "type": "product",  # or discount, shipping, etc.
      "description": "Super ergonomic chair",
      "metadata": {"color": "black", "name": "Karmus", "variant": "M"},
      "reference": "702.611.50",
      "category": "Furniture > Chairs",
      "supplier_id": "7363",
      "supplier_name": "Cool chair wholesaler",
      "quantity": "10.000",
      "unit_price": 1000,  # includes tax
      "tax_rate": "20.00",
      "total_amount": 10000,
      "tax_amount": 2000,
      "fulfilled_quantity": 0,
      "fulfillment_info": null,
      "cancelled_quantity": 0,
      "cancelled_info": null,
      "returned_quantity": 0,
      "returned_info": null
    },
    {
      "item_id": "2",
      "type": "shipping",
      "description": "Delivery fee",
      "quantity": "1.000",
      "unit_price": 2000,
      "tax_rate": "20.00",
      "total_amount": 2000,
      "tax_amount": 400,
      "fulfilled_quantity": 0,
      "fulfillment_info": null,
      "cancelled_quantity": 0,
      "cancelled_info": null,
      "returned_quantity": 0,
      "returned_info": null
    }
  ],
  "metadata": {},  # store key-values for your internal references
  "po_number": "P-45612",
  "payment_offer": null,
  "deferred_payment": null
}

The Order object contains many fields that are optional for historical orders. See below for an example of a minimal historical order.

field type flags description
url string read-only API endpoint to access the order
id string(uuid) read-only API unique identifier for the order
unique_id string required Unique identifier of the order in your platform
customer dictionary required Customer making the order (see guest/registered users)
customer[type] string required "registered" or "guest"
customer[organisation] string(uuid) required API unique identifier of the organisation of the customer (if registered) (can be expanded to a full Organisation object)
customer[user] string(uuid) required API unique identifier of the user of the customer (if registered) (can be expanded to a full User object)
customer[delivery_address] dictionary required Delivery/shipping address for this order. See Addresses for a description of the fields
customer[invoice_address] dictionary required Invoice (or Billing) address for this order. See Addresses for a description of the fields
status string required Order status
pay_method string optional Used to supply the Payment method, only if the order has already been paid without Hokodo
currency currency required Currency of order amounts
tax_amount int required Total amount of the taxes, in minor units (cents)
total_amount int required Total amount including tax, in minor units (cents)
order_date date required Date of the order
invoice_date date optional Date of issuance of the invoice, if different from order date
due_date date optional Date due of the order (assuming the customer was given credit terms – if no credit terms were offered, then this would simply be the order_date)
paid_date date optional Date when the order was paid in full (assuming credit terms were offered – otherwise this would simply be the order_date)
items list required The list of items that constitute the order
items[*][item_id] string required Your identifier for this line of the order, e.g. 1, 2, 3...
items[*][type] string required Type of the item. Can be one of the following: product, service, digital, shipping, fee, discount
items[*][description] string required Description of the item
items[*][metadata] dictionary optional Key-value pairs attached to the item, for example describing the color, variant, specific options, to help identify the item post-sale
items[*][reference] string optional Item reference number, SKU, etc.
items[*][category] string optional Category of the item, as per owner's internal classification
items[*][supplier_id] string optional An id of the supplier of the items (if applicable), can be your internal identifier of the supplier, for example "152"
items[*][supplier_name] string optional The name of the supplier of the items (if applicable)
items[*][quantity] decimal required Number of items in the order
items[*][unit_price] int required Price of a single unit, including tax, in minor units (cents)
items[*][tax_rate] decimal required Tax rate on this item, in percent (e.g. "19.50" for 19.5%)
items[*][tax_amount] int required Amount of the tax for this item, in minor units (cents)
items[*][total_amount] int required Total amount for this item, including tax, in minor units (cents)
items[*][fulfilled_quantity] decimal read-only Number of items fulfilled
items[*][fulfillment_info] list read-only Information about shipping of the items (see section Fulfillment)
items[*][fulfillment_info][*][quantity] decimal read-only Number of items in the shipment
items[*][fulfillment_info][*][shipping_id] string read-only Tracking id when the item has shipped (add when shipped)
items[*][fulfillment_info][*][shipping_provider] string read-only Name of the shipping provider (add when shipped)
items[*][cancelled_quantity] decimal read-only Number of items cancelled
items[*][cancelled_info] list read-only Information about cancellation of the items (see section Cancellation)
items[*][cancelled_info][*][quantity] decimal read-only Quantity of items cancelled
items[*][cancelled_info][*][total_amount] string read-only Total value of items cancelled
items[*][cancelled_info][*][tax_amount] string read-only Total tax amount of items cancelled
items[*][returned_quantity] decimal read-only Number of items returned
items[*][returned_info] list read-only Information about items returned (see section Returns)
items[*][returned_info][*][quantity] decimal read-only Number of items returned
items[*][returned_info][*][total_amount] string read-only Total value of items returned
items[*][returned_info][*][tax_amount] string read-only Total tax amount of items returned
metadata dictionary optional Set of key-value pairs you can attach to the object. You can use this to store your custom data in the object and read it back later.
po_number string optional Purchase order number from the customer (for their benefit, as reference)
payment_offer string(uuid) read-only API unique identifier for the deferred payment offer (if created, can be expanded to a full Payment Offer object)
deferred_payment string(uuid) read-only API unique identifier for the deferred payment in place (if created, can be expanded to a full Deferred payment object)

Order status

The order status must be one of:

On draft orders

Draft order status can be used for orders that the user has not yet committed to, e.g. they put something in their cart but did not yet complete the checkout. If the customer goes on to pay via a payment method other than Hokodo Deferred Payment (e.g. they pay by card) then you should amend the order status to paid. In this case the paid order becomes part of the payment history that Hokodo can take into account when assessing this customer for Deferred Payment in the future.

If the customer abandons the checkout and so never completes the purchase, then the order will remain in draft status, and so we will know not to include it in any analysis of the customer's historical payment behaviour.

If the customer ends up completing the purchase using a Hokodo Deferred Payment, then we will automatically move the status to unpaid, and ultimately to paid.

Payment method

The payment_method must be one of:

Please contact us to add more payment methods for purchases not made via Hokodo, to match closely your platform. This information helps us to provide finer and higher credit limits.

Guest users / registered users

Hokodo needs to identify the customer and their company to be able to provide deferred payments, whether they are a registered and logged-in user on your platform, or they are a guest user making a single purchase.

Both cases require a User and Organisation. For registered users, this will be a one-time creation. For guests users, you can re-use a User and Organisation you have already created, or create a fresh one each time.

This flow will work the same for both guest users and registered users:

  1. Create User with the email address of the user (which may be an unverified email address for guest customers)

  2. User uniqueness on Hokodo's side is based on email address. If we detect that they have already been registered as a User on your platform, Hokodo API will return the existing user and identifier, complete with links to Organisation and Company saved before.

  3. If no organisation was linked to the user, or they wish to link a different one, search and identify the company via company search.

  4. Create the Organisation linked to that Company.

  5. Attach the User to the Organisation.

Registered user

If the customer is a registered user on your platform, you should create or have created an Organisation (to represent their team / company), and a User (to represent the individuals within that team / company). Then, use that organisation and user in the customer field of the Order.

Registered user

{
  "customer": {
    "organisation": "...",
    "user": "...",
    "type": "registered",
    "delivery_address": {
      "...": "..."
    }
  }
}

Guest user

If the customer is a guest user, and has not registered on your platform, you should collect some information to help us identify the customer, and create a User and Organisation in the same way as for registered user. When you create the User object, Hokodo may return an existing User object, if you had previously created a User with the same email address. In that case, it may also have the correct Organisation filled in already.

Guest user

{
  "customer": {
    "organisation": "...",
    "user": "...",
    "type": "guest",
    "delivery_address": {
      "...": "..."
    }
  }
}

Addresses

{
  "name": "John Smith",
  "company_name": "",
  "address_line1": "1 Station Street",
  "address_line2": "Flat B",
  "address_line3": "",
  "city": "London",
  "region": "",
  "postcode": "SE11 6NQ",
  "country": "GB",
  "phone": "",
  "email": ""
}

The fields used in addresses are:

field type flags description
name string required Full name
company_name string optional (for delivery) Name of the company for delivery if it differs from the legal entity's name
address_line1 string required Line 1 of the address
address_line2 string optional Line 2 of the address
address_line3 string optional Line 3 of the address
city string required City
region string optional State or Region
postcode string required Postal/ZIP code
country country required Country code
phone string optional Phone number associated to the address (eg to handle delivery)
email string optional Email associated to the address (eg to handle delivery notifications)

Create order

Requests

  • minimal historical order of a registered user
POST /v1/payment/orders HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "unique_id": "876987-987uinjojna-I8UH98Jnj",
  "customer": {
    "type": "registered",
    "organisation": "org-ypTaHiLv5kgqSn4TzCr7xb",
    "user": "user-nNqgg5AFymQMumaU7EdrLa",
    "delivery_address": {
      "name": "John Smith",
      "address_line1": "1 Station Street",
      "address_line2": "Flat B",
      "city": "London",
      "postcode": "SE11 6NQ",
      "country": "GB"
    },
    "invoice_address": {
      "name": "John Smith",
      "address_line1": "1 Station Street",
      "address_line2": "Flat B",
      "city": "London",
      "postcode": "SE11 6NQ",
      "country": "GB"
    },
  },
  "status": "paid",
  "currency": "GBP",
  "total_amount": 12000,
  "tax_amount": 2000,
  "order_date": "2018-04-25",
  "invoice_date": "2018-04-25",
  "due_date": "2018-05-25",
  "paid_date": "2018-06-10",
  "pay_method": "directdebit"
}
curl --request POST \
     --url https://api-sandbox.hokodo.co/v1/payment/orders \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>" \
     --data-binary '{
  "unique_id": "876987-987uinjojna-I8UH98Jnj",
  "customer": {
    "type": "registered",
    "organisation": "org-ypTaHiLv5kgqSn4TzCr7xb",
    "user": "user-nNqgg5AFymQMumaU7EdrLa",
    "delivery_address": {
      "name": "John Smith",
      "address_line1": "1 Station Street",
      "address_line2": "Flat B",
      "city": "London",
      "postcode": "SE11 6NQ",
      "country": "GB"
    },
     "invoice_address": {
      "name": "John Smith",
      "address_line1": "1 Station Street",
      "address_line2": "Flat B",
      "city": "London",
      "postcode": "SE11 6NQ",
      "country": "GB"
    },
  },
  "status": "paid",
  "currency": "GBP",
  "total_amount": 12000,
  "tax_amount": 2000,
  "order_date": "2018-04-25",
  "invoice_date": "2018-04-25",
  "due_date": "2018-05-25",
  "paid_date": "2018-06-10",
  "pay_method": "directdebit"
}'
  • new order of a registered user
POST /v1/payment/orders HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "unique_id": "876987-987uinjojna-I8UH98Jnj",
  "customer": {
    "type": "registered",
    "organisation": "org-ypTaHiLv5kgqSn4TzCr7xb",
    "user": "user-nNqgg5AFymQMumaU7EdrLa",
    "delivery_address": {
      "name": "John Smith",
      "address_line1": "1 Station Street",
      "address_line2": "Flat B",
      "city": "London",
      "postcode": "SE11 6NQ",
      "country": "GB"
    },
  },
  "status": "draft",
  "currency": "GBP",
  "total_amount": 12000,
  "tax_amount": 2000,
  "order_date": "2018-04-25",
  "items": [
    {
      "item_id": "1",
      "type": "product",
      "description": "Super ergonomic chair",
      "metadata": {"color": "black", "name": "Karmus", "variant": "M"},
      "reference": "702.611.50",
      "category": "Furniture > Chairs",
      "supplier_id": "7363",
      "quantity": "10.000",
      "unit_price": 1000,
      "tax_rate": "20.00",
      "total_amount": 10000,
      "tax_amount": 2000,
      "fulfilled_quantity": 0,
      "fulfillment_info": null,
      "cancelled_quantity": 0,
      "cancelled_info": null,
      "returned_quantity": 0,
      "returned_info": null
    },
    {
      "item_id": "2",
      "type": "shipping",
      "description": "Delivery fee",
      "quantity": "1.000",
      "unit_price": 2000,
      "tax_rate": "20.00",
      "total_amount": 2000,
      "tax_amount": 400,
      "fulfilled_quantity": 0,
      "fulfillment_info": null,
      "cancelled_quantity": 0,
      "cancelled_info": null,
      "returned_quantity": 0,
      "returned_info": null
    }
  ],
  "metadata": {
    "customer_id": "2055b445-3d95-4d2f-bd80-3e336217905f",
    "checkout_id": "c0185e68-89aa-42d5-93e9-476d01d4c97f"
  }
}
curl --request POST \
     --url https://api-sandbox.hokodo.co/v1/payment/orders \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>" \
     --data-binary '{
  "unique_id": "876987-987uinjojna-I8UH98Jnj",
  "customer": {
    "type": "registered",
    "organisation": "org-ypTaHiLv5kgqSn4TzCr7xb",
    "user": "user-nNqgg5AFymQMumaU7EdrLa",
    "delivery_address": {
      "name": "John Smith",
      "address_line1": "1 Station Street",
      "address_line2": "Flat B",
      "city": "London",
      "postcode": "SE11 6NQ",
      "country": "GB"
    },
  },
  "status": "draft",
  "currency": "GBP",
  "total_amount": 12000,
  "tax_amount": 2000,
  "order_date": "2018-04-25",
  "items": [
    {
      "item_id": "1",
      "type": "product",
      "description": "Super ergonomic chair",
      "metadata": {"color": "black", "name": "Karmus", "variant": "M"},
      "reference": "702.611.50",
      "category": "Furniture > Chairs",
      "supplier_id": "7363",
      "quantity": "10.000",
      "unit_price": 1000,
      "tax_rate": "20.00",
      "total_amount": 10000,
      "tax_amount": 1667
    },
    {
      "item_id": "2",
      "type": "shipping",
      "description": "Delivery fee",
      "quantity": "1.000",
      "unit_price": 2000,
      "tax_rate": "20.00",
      "total_amount": 2000,
      "tax_amount": 333
    }
  ],
  "metadata": {
    "customer_id": "2055b445-3d95-4d2f-bd80-3e336217905f",
    "checkout_id": "c0185e68-89aa-42d5-93e9-476d01d4c97f"
  }
}'
  • new order of a guest user
POST /v1/payment/orders HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "unique_id": "876987-987uinjojna-I8UH98Jnj",
  "customer": {
    "type": "guest",
    "organisation": "org-ypTaHiLv5kgqSn4TzCr7xb",
    "user": "user-nNqgg5AFymQMumaU7EdrLa",
    "delivery_address": {
      "name": "John Smith",
      "address_line1": "1 Station Street",
      "address_line2": "Flat B",
      "city": "London",
      "postcode": "SE11 6NQ",
      "country": "GB"
    },
  },
  "status": "draft",
  "currency": "GBP",
  "total_amount": 12000,
  "tax_amount": 2000,
  "order_date": "2018-04-25",
  "items": [
    {
      "item_id": "1",
      "type": "product",
      "description": "Super ergonomic chair",
      "metadata": {"color": "black", "name": "Karmus", "variant": "M"},
      "reference": "702.611.50",
      "category": "Furniture > Chairs",
      "supplier_id": "7363",
      "quantity": "10.000",
      "unit_price": 1000,
      "tax_rate": "20.00",
      "total_amount": 10000,
      "tax_amount": 2000,
      "fulfilled_quantity": 0,
      "fulfillment_info": null,
      "cancelled_quantity": 0,
      "cancelled_info": null,
      "returned_quantity": 0,
      "returned_info": null
    },
    {
      "item_id": "2",
      "type": "shipping",
      "description": "Delivery fee",
      "quantity": "1.000",
      "unit_price": 2000,
      "tax_rate": "20.00",
      "total_amount": 2000,
      "tax_amount": 400,
      "fulfilled_quantity": 0,
      "fulfillment_info": null,
      "cancelled_quantity": 0,
      "cancelled_info": null,
      "returned_quantity": 0,
      "returned_info": null
    }
  ],
  "metadata": {
    "customer_id": "2055b445-3d95-4d2f-bd80-3e336217905f",
    "checkout_id": "c0185e68-89aa-42d5-93e9-476d01d4c97f"
  }
}
curl --request POST \
     --url https://api-sandbox.hokodo.co/v1/payment/orders \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>" \
     --data-binary '{
  "unique_id": "876987-987uinjojna-I8UH98Jnj",
  "customer": {
    "type": "registered",
    "company": "org-QdKZ5mdD8BrG5CKxGok2Q4",
    "email": "john@example.com",
    "name": "John Smith",
    "phone": "+44 123 456 7890",
    "delivery_address": {
      "name": "John Smith",
      "address_line1": "1 Station Street",
      "address_line2": "Flat B",
      "city": "London",
      "postcode": "SE11 6NQ",
      "country": "GB"
    },
  },
  "status": "draft",
  "currency": "GBP",
  "total_amount": 12000,
  "tax_amount": 2000,
  "order_date": "2018-04-25",
  "items": [
    {
      "item_id": "1",
      "type": "product",
      "description": "Super ergonomic chair",
      "metadata": {"color": "black", "name": "Karmus", "variant": "M"},
      "reference": "702.611.50",
      "category": "Furniture > Chairs",
      "supplier_id": "7363",
      "quantity": "10.000",
      "unit_price": 1000,
      "tax_rate": "20.00",
      "total_amount": 10000,
      "tax_amount": 1667
    },
    {
      "item_id": "2",
      "type": "shipping",
      "description": "Delivery fee",
      "quantity": "1.000",
      "unit_price": 2000,
      "tax_rate": "20.00",
      "total_amount": 2000,
      "tax_amount": 333
    }
  ],
  "metadata": {
    "customer_id": "2055b445-3d95-4d2f-bd80-3e336217905f",
    "checkout_id": "c0185e68-89aa-42d5-93e9-476d01d4c97f"
  }
}'

Responses

  • success response
201 Created
Content-Type: application/json
{
  "url": "https://api-sandbox.hokodo.co/v1/payment/orders/order-yQKxbtCg9aTS5JYnsRVA9B",
  "id": "order-yQKxbtCg9aTS5JYnsRVA9B",
  "unique_id": "48b0ce9a-f8a3-4dff-be56-26af747b3d98",
  "customer": {
    "type": "registered",
    "organisation": "org-ypTaHiLv5kgqSn4TzCr7xb",
    "user": "user-nNqgg5AFymQMumaU7EdrLa",
    "delivery_address": {
      "name": "John Smith",
      "address_line1": "1 Station Street",
      "address_line2": "Flat B",
      "address_line3": "",
      "city": "London",
      "region": "",
      "postcode": "SE11 6NQ",
      "country": "GB",
      "phone": "",
      "email": ""
    }
  },
  "status": "draft",
  "currency": "GBP",
  "pay_method": "",
  "total_amount": 12000,
  "tax_amount": 2000,
  "order_date": "2018-04-25",
  "invoice_date": null,
  "due_date": null,
  "paid_date": null,
  "items": [
    {
      "item_id": "1",
      "type": "product",
      "description": "Super ergonomic chair",
      "metadata": {"color": "black", "name": "Karmus", "variant": "M"},
      "reference": "702.611.50",
      "category": "Furniture > Chairs",
      "supplier_id": "7363",
      "supplier_name": "",
      "quantity": "10.000",
      "unit_price": 1000,
      "tax_rate": "20.00",
      "total_amount": 10000,
      "tax_amount": 2000,
      "fulfilled_quantity": 0,
      "fulfillment_info": null,
      "cancelled_quantity": 0,
      "cancelled_info": null,
      "returned_quantity": 0,
      "returned_info": null
    },
    {
      "item_id": "2",
      "type": "shipping",
      "description": "Delivery fee",
      "metadata": {},
      "reference": "",
      "category": "",
      "supplier_id": "",
      "supplier_name": "",
      "quantity": "1.000",
      "unit_price": 2000,
      "tax_rate": "20.00",
      "total_amount": 2000,
      "tax_amount": 400,
      "fulfilled_quantity": 0,
      "fulfillment_info": null,
      "cancelled_quantity": 0,
      "cancelled_info": null,
      "returned_quantity": 0,
      "returned_info": null
    }
  ],
  "metadata": {
    "customer_id": "2055b445-3d95-4d2f-bd80-3e336217905f",
    "checkout_id": "c0185e68-89aa-42d5-93e9-476d01d4c97f"
  },
  "payment_offer": null,
  "deferred_payment": null
}
  • error response (example)
400 Bad Request
Content-Type: application/json
{
  "organisation": [
    "Invalid pk \"org-AgBGknk7D8KixY2ntbJtmA\" - object does not exist."
  ],
  "user": [
    "Bad prefix. Expected a UUID prefixed by \"user\", but got xyz."
  ],
  "items": [
    {
      "total_amount": "Item 1 unit_price [1084] and quantity [10.000] does not match total_amount [13010]."
    }
  ]
}

To create an order, you create an Order object.

Many fields are optional. However, to obtain a Deferred Payment Offer later the system must be provided with the following information at least:

The more information is provided at order creation, the more accurate the Payment Offer Hokodo can provide, and the less friction there will be for your customer later on to complete the purchase.

Errors

errors description
400 a required field is missing or some of the fields have incorrect value

List orders

Request

GET /v1/payment/orders HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>
curl --request GET \
     --url https://api-sandbox.hokodo.co/v1/payment/orders \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>"

Response

200 Ok
Content-Type: application/json
{
  "count": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "url": "https://api-sandbox.hokodo.co/v1/payment/orders/order-yQKxbtCg9aTS5JYnsRVA9B",
      "id": "order-yQKxbtCg9aTS5JYnsRVA9B",
      "unique_id": "48b0ce9a-f8a3-4dff-be56-26af747b3d98",
      "customer": {
        "type": "registered",
        "organisation": "org-ypTaHiLv5kgqSn4TzCr7xb",
        "user": "user-nNqgg5AFymQMumaU7EdrLa",
        "delivery_address": {
          "name": "John Smith",
          "address_line1": "1 Station Street",
          "address_line2": "Flat B",
          "address_line3": "",
          "city": "London",
          "region": "",
          "postcode": "SE11 6NQ",
          "country": "GB",
          "phone": "",
          "email": ""
        }
      },
      "status": "draft",
      "currency": "GBP",
      "pay_method": "",
      "total_amount": 12000,
      "tax_amount": 2000,
      "order_date": "2018-04-25",
      "invoice_date": null,
      "due_date": null,
      "paid_date": null,
      "items": [
        {
          "item_id": "1",
          "type": "product",
          "description": "Super ergonomic chair",
          "metadata": {"color": "black", "name": "Karmus", "variant": "M"},
          "reference": "702.611.50",
          "category": "Furniture > Chairs",
          "supplier_id": "7363",
          "supplier_name": "",
          "quantity": "10.000",
          "unit_price": 1000,
          "tax_rate": "20.00",
          "total_amount": 10000,
          "tax_amount": 2000,
          "fulfilled_quantity": 0,
          "fulfillment_info": null,
          "cancelled_quantity": 0,
          "cancelled_info": null,
          "returned_quantity": 0,
          "returned_info": null
        },
        {
          "item_id": "2",
          "type": "shipping",
          "description": "Delivery fee",
          "metadata": {},
          "reference": "",
          "category": "",
          "supplier_id": "",
          "supplier_name": "",
          "quantity": "1.000",
          "unit_price": 2000,
          "tax_rate": "20.00",
          "total_amount": 2000,
          "tax_amount": 400,
          "fulfilled_quantity": 0,
          "fulfillment_info": null,
          "cancelled_quantity": 0,
          "cancelled_info": null,
          "returned_quantity": 0,
          "returned_info": null
        }
      ],
      "metadata": {
        "customer_id": "2055b445-3d95-4d2f-bd80-3e336217905f",
        "checkout_id": "c0185e68-89aa-42d5-93e9-476d01d4c97f"
      },
      "payment_offer": null,
      "deferred_payment": null
    },
    {
      "url": "https://api-sandbox.hokodo.co/v1/payment/orders/order-LitFGLodQh9qQHTFcjUvfm",
      "id": "order-LitFGLodQh9qQHTFcjUvfm",
      "unique_id": "8751729d-7e96-4d38-87bc-fe241ca1d4d7",
      "customer": {
        "type": "registered",
        "organisation": "org-dLWYumjHaqChNggScx5inV",
        "user": "user-czNtrBwLY63rJkqmgyQaEF",
        "delivery_address": {
          "name": "John Smith",
          "address_line1": "1 Station Street",
          "address_line2": "Flat B",
          "address_line3": "",
          "city": "London",
          "region": "",
          "postcode": "SE11 6NQ",
          "country": "GB",
          "phone": "",
          "email": ""
        }
      },
      "status": "draft",
      "currency": "GBP",
      "pay_method": "",
      "total_amount": 12000,
      "tax_amount": 2000,
      "order_date": "2018-04-25",
      "invoice_date": null,
      "due_date": null,
      "paid_date": null,
      "items": [
        {
          "item_id": "1",
          "type": "product",
          "description": "Super ergonomic chair",
          "metadata": {"color": "black", "name": "Karmus", "variant": "M"},
          "reference": "702.611.50",
          "category": "Furniture > Chairs",
          "supplier_id": "7363",
          "supplier_name": "",
          "quantity": "10.000",
          "unit_price": 1000,
          "tax_rate": "20.00",
          "total_amount": 10000,
          "tax_amount": 2000,
          "fulfilled_quantity": 0,
          "fulfillment_info": null,
          "cancelled_quantity": 0,
          "cancelled_info": null,
          "returned_quantity": 0,
          "returned_info": null
        },
        {
          "item_id": "2",
          "type": "shipping",
          "description": "Delivery fee",
          "metadata": {},
          "reference": "",
          "category": "",
          "supplier_id": "",
          "supplier_name": "",
          "quantity": "1.000",
          "unit_price": 2000,
          "tax_rate": "20.00",
          "total_amount": 2000,
          "tax_amount": 400,
          "fulfilled_quantity": 0,
          "fulfillment_info": null,
          "cancelled_quantity": 0,
          "cancelled_info": null,
          "returned_quantity": 0,
          "returned_info": null
        }
      ],
      "metadata": {
        "customer_id": "584eaf27-250c-4b83-826f-909cbaa1f54a",
        "checkout_id": "59e278cd-305a-4bbe-a275-f038f9319b1c"
      },
      "payment_offer": null,
      "deferred_payment": null
    }
  ]
}

List orders created by your platform

View order

Requests

  • without expanding referenced objects
GET /v1/payment/orders/<order_id> HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>
curl --request GET \
     --url https://api-sandbox.hokodo.co/v1/payment/orders/<order_id> \
     --header "Authorization: <your_api_key>"
  • with expanding referenced customer, payment_offer
GET /v1/payment/orders/<order_id>?expand=customer,payment_offer HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>
curl --request GET \
     --url https://api-sandbox.hokodo.co/v1/payment/orders/<order_id>?expand=customer,payment_offer \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>"

Responses

  • regular response (with optional expansion)
200 Ok
Content-Type: application/json
{
  "url": "https://api-sandbox.hokodo.co/v1/payment/orders/order-yQKxbtCg9aTS5JYnsRVA9B",
  "id": "order-yQKxbtCg9aTS5JYnsRVA9B",
  "unique_id": "48b0ce9a-f8a3-4dff-be56-26af747b3d98",
  "customer": {
    "type": "registered",
    "organisation": {
      "id": "org-ypTaHiLv5kgqSn4TzCr7xb",
      "unique_id": "c105b862-f1ba-4197-9d97-57db63196b00",
      "registered": "2022-06-01T14:37:12Z",
      "name": "Organisation name",
      "company": {
        "url": "https://api-sandbox.hokodo.co/v1/companies/co-Toq88Ko9RKoukP9AagxJoM",
        "id": "co-Toq88Ko9RKoukP9AagxJoM",
        "country": "GB",
        "name": "Hokodo Ltd",
        "address": "35 Kingsland Road, London, E2 8AA",
        "city": "London",
        "postcode": "E2 8AA",
        "legal_form": "Private limited with share capital",
        "sectors": [
          {
            "system": "SIC2007",
            "code": "64999"
          }
        ],
        "creation_date": "2018-02-20",
        "identifiers": [
          {
            "idtype": "reg_number",
            "country": "GB",
            "value": "11215527"
          }
        ],
        "email": "hokodo@hokodo.co",
        "phone": "",
        "status": "Active",
        "accounts_type": "Active"
      },
      "users": [
          "d1696bbe-e982-4065-ac84-3e6543f4da24",
          "3ae2713d-e79a-4837-8cef-06af956af3b9"
      ]
    },
    "user": {
      "id": "user-CXavtWTgLxU7rNuSzkyKDX",
      "email": "a_mail@example.com",
      "unique_id": "",
      "name": "A name",
      "phone": "+44123456789",
      "registered": "2018-07-01T12:12:12Z",
      "type": "registered"
    },
    "invoice_address": {
      "name": "Bob Accounting",
      "company_name": "",
      "address_line1": "1 Main Street",
      "address_line2": "65th floor",
      "address_line3": "",
      "city": "London",
      "region": "",
      "postcode": "SE11 6NQ",
      "country": "GB",
      "phone": "",
      "email": ""
    },
    "delivery_address": {
      "name": "John Smith",
      "address_line1": "1 Station Street",
      "address_line2": "Flat B",
      "address_line3": "",
      "city": "London",
      "region": "",
      "postcode": "SE11 6NQ",
      "country": "GB",
      "phone": "",
      "email": ""
    }
  },
  "status": "draft",
  "currency": "GBP",
  "pay_method": "",
  "total_amount": 12000,
  "tax_amount": 2000,
  "order_date": "2018-04-25",
  "invoice_date": null,
  "due_date": null,
  "paid_date": null,
  "items": [
    {
      "item_id": "1",
      "type": "product",
      "description": "Super ergonomic chair",
      "metadata": {"color": "black", "name": "Karmus", "variant": "M"},
      "reference": "702.611.50",
      "category": "Furniture > Chairs",
      "supplier_id": "7363",
      "supplier_name": "",
      "quantity": "10.000",
      "unit_price": 1000,
      "tax_rate": "20.00",
      "total_amount": 10000,
      "tax_amount": 2000,
      "fulfilled_quantity": 0,
      "fulfillment_info": null,
      "cancelled_quantity": 0,
      "cancelled_info": null,
      "returned_quantity": 0,
      "returned_info": null
    },
    {
      "item_id": "2",
      "type": "shipping",
      "description": "Delivery fee",
      "metadata": {},
      "reference": "",
      "category": "",
      "supplier_id": "",
      "supplier_name": "",
      "quantity": "1.000",
      "unit_price": 2000,
      "tax_rate": "20.00",
      "total_amount": 2000,
      "tax_amount": 400,
      "fulfilled_quantity": 0,
      "fulfillment_info": null,
      "cancelled_quantity": 0,
      "cancelled_info": null,
      "returned_quantity": 0,
      "returned_info": null
    }
  ],
  "metadata": {
    "customer_id": "2055b445-3d95-4d2f-bd80-3e336217905f",
    "checkout_id": "c0185e68-89aa-42d5-93e9-476d01d4c97f"
  },
  "payment_offer": {
    "url": "https://api-sandbox.hokodo.co/v1/payment/offers/offer-EzH6BixNSHvaByEpXcFW5h",
    "id": "offer-bqRyHAGaFrDEN8JNjXJirp",
    "order": "order-dTHo9Q2idffT7CMPCVjztA",
    "offered_payment_plans": [
      {
        "id": "ppln-bqRyHAGaFrDEN8JNjXJirp",
        "name": "net30",
        "template": "pptemp-RySHMoFqSxfmkcfrYC2VeF",
        "currency": "GBP",
        "protected_amount": 100000,
        "unprotected_amount": 0,
        "scheduled_payments": [
          {
            "date": "2020-10-16",
            "amount": 100000,
            "discounted_amount": 100000,
            "customer_fee": {
              "percentage": "0.00",
              "amount": 0
            },
            "allowed_payment_methods": [
              {"type": "card"},
              {"type": "direct_debit"},
              {"type": "invoice"}
            ],
            "payment_method": {"type": "card"},
            "due_date_config": {
              "due_after_nb_days": 30,
              "due_end_of_nb_months": null,
              "amount_percentage": "100.0",
              "is_upfront_payment": false
            }
          }
        ],
        "payment_terms_relative_to": "order_creation",
        "merchant_fee": {
          "currency": "GBP",
          "amount": 1000
        },
        "customer_fee": {
          "currency": "GBP",
          "percentage": "0.00",
          "amount": 0
        },
        "customer_percentage_discount": "0.00",
        "customer_discount": {
          "currency": "EUR",
          "amount": 0
        },
        "valid_until": "2020-09-16T12:44:49.059Z",
        "payment_url": "https://payment.app.hokodo.co/plans/ppln-bqRyHAGaFrDEN8JNjXJirp",
        "status": "active",
        "rejection_reason": null,
        "has_upfront_payment": false
      },
      {
        "id": "ppln-gJdDHAGaFrDLDvJNXJird",
        "name": "4xEOM",
        "template": "pptemp-RySHMoFqSxfmkcfrYC2VeF",
        "currency": "GBP",
        "protected_amount": 100400,
        "unprotected_amount": 0,
        "scheduled_payments": [
          {
            "date": "2020-09-30",
            "amount": 25100,
            "discounted_amount": 25100,
            "customer_fee": {
              "percentage": "0.40",
              "amount": 100
            },
            "allowed_payment_methods": [
              {"type": "card"}
            ],
            "payment_method": null,
            "due_date_config": {
              "due_after_nb_days": 30,
              "due_end_of_nb_months": null,
              "amount_percentage": "25.0",
              "is_upfront_payment": false
            }
          },
          {
            "date": "2020-10-31",
            "amount": 25100,
            "discounted_amount": 25100,
            "customer_fee": {
              "percentage": "0.40",
              "amount": 100
            },
            "allowed_payment_methods": [
              {"type": "card"}
            ],
            "payment_method": null,
            "due_date_config": {
              "due_after_nb_days": null,
              "due_end_of_nb_months": 1,
              "amount_percentage": "25.0",
              "is_upfront_payment": false
            }
          },
          {
            "date": "2020-11-30",
            "amount": 25100,
            "discounted_amount": 25100,
            "customer_fee": {
              "percentage": "0.40",
              "amount": 100
            },
            "allowed_payment_methods": [
              {"type": "card"}
            ],
            "payment_method": null,
            "due_date_config": {
              "due_after_nb_days": null,
              "due_end_of_nb_months": 2,
              "amount_percentage": "25.0",
              "is_upfront_payment": false
            }
          },
          {
            "date": "2020-12-31",
            "amount": 25100,
            "discounted_amount": 25100,
            "customer_fee": {
              "percentage": "0.40",
              "amount": 100
            },
            "allowed_payment_methods": [
              {"type": "card"}
            ],
            "payment_method": null,
            "due_date_config": {
              "due_after_nb_days": null,
              "due_end_of_nb_months": 3,
              "amount_percentage": "25.0",
              "is_upfront_payment": false
            }
          }
        ],
        "payment_terms_relative_to": "order_creation",
        "merchant_fee": {
          "currency": "GBP",
          "amount": 2000
        },
        "customer_fee": {
          "currency": "GBP",
          "percentage": "0.40",
          "amount": 400
        },
        "customer_percentage_discount": "0.00",
        "customer_discount": {
          "currency": "EUR",
          "amount": 0
        },
        "valid_until": "2020-09-16T12:44:49.059Z",
        "payment_url": "https://payment.app.hokodo.co/plans/ppln-gJdDHAGaFrDLDvJNXJird",
        "status": "active",
        "rejection_reason": null,
        "has_upfront_payment": false
      }
    ],
    "urls": {
      "success": "https://merchant.com/payment/ok",
      "failure": "https://merchant.com/checkout",
      "cancel": "https://merchant.com/checkout",
      "notification": "https://backend.merchant.com/payment/notifications",
      "merchant_terms": "https://merchant.com/terms"
    },
    "locale": "en-gb",
    "metadata": {}
  },
  "deferred_payment": null
}
  • order not found
404 Not Found
Content-Type: application/json
{
  "detail": "Not found."
}

Look up a previously created order.

Errors

errors description
404 the order_id is probably invalid, the order has not been found

Modify order

Modify a previously created order.

Historic Orders

When you supply information on Orders for the purposes of informing Hokodo about a customer's payment history, you are able to amend those orders freely, or even delete them using the Delete Order endpoint.

Orders with a PaymentOffer

Once you request a PaymentOffer for an Order, any subsequent changes made to the Order will automatically expire the PaymentOffer.

Note: You can still amend the following fields unique_id, metadata, po_number as they don't affect the terms of the PaymentOffer.

Orders with a DeferredPayment

Once the customer purchases a DeferredPayment, the underlying Order can no longer be amended using the Order's endpoint, with the following exception: unique_id. Instead, you must use the dedicated endpoints for dealing with Cancellations, Refunds/Discounts and Returns, which are described in the post-sale Order actions section.

Request (e.g. update when an invoice has been paid)

PATCH /v1/payment/orders/<order_id> HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "status": "paid",
  "paid_date": "2018-06-10",
  "pay_method": "bank"
}
curl --request PATCH \
     --url https://api-sandbox.hokodo.co/v1/payment/orders/<order_id> \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>" \
     --data-binary '{
  "status": "paid",
  "paid_date": "2018-06-10",
  "pay_method": "bank"
}'

Response

200 Ok
Content-Type: application/json
{
  "url": "https://api-sandbox.hokodo.co/v1/payment/orders/order-yQKxbtCg9aTS5JYnsRVA9B",
  "id": "order-yQKxbtCg9aTS5JYnsRVA9B",
  "unique_id": "876987-987uinjojna-I8UH98Jnj",
  "customer": {
    "type": "registered",
    "organisation": "org-ypTaHiLv5kgqSn4TzCr7xb",
    "user": "user-nNqgg5AFymQMumaU7EdrLa",
    "delivery_address": {
      "name": "John Smith",
      "address_line1": "1 Station Street",
      "address_line2": "Flat B",
      "address_line3": "",
      "city": "London",
      "region": "",
      "postcode": "SE11 6NQ",
      "country": "GB",
      "phone": "",
      "email": ""
    }
  },
  "status": "paid",
  "currency": "GBP",
  "pay_method": "",
  "total_amount": 12000,
  "tax_amount": 2000,
  "order_date": "2018-04-25",
  "invoice_date": "2018-04-25",
  "due_date": "2018-05-25",
  "paid_date": "2018-06-10",
  "pay_method": "bank",
  "items": [],
  "metadata": null,
  "payment_offer": null,
  "deferred_payment": null
}

Errors

errors description
400 a required field is missing or some of the fields have incorrect value
409 the order is already insured, modification is not allowed

Delete order

Request

DELETE /v1/payment/orders/<order_id> HTTP/1.1
Authorization: Token <your_api_key>
curl --request DELETE \
     --url https://api-sandbox.hokodo.co/v1/payment/orders/<order_id> \
     --header "Authorization: <your_api_key>"

Responses

  • regular response
204 No Content
  • order not found
404 Not Found
Content-Type: application/json
{
  "detail": "Not found."
}
  • order can not be deleted
409 Conflict
Content-Type: application/json

Delete a previously created order.

Errors

errors description
404 the order_id is probably invalid, the order has not been found
409 the order can not be deleted

Order Documents

OrderDocuments are documents such as an invoice, credit note, or a shipping document associated with a particular order.

Invoices

Invoices are normally sent by the merchant to the customer at the time of delivery. Hokodo need these invoices to support the collections process, because it is very common for customers to ask for the invoice to be re-sent to them before they make payment. Therefore, once the merchant generates the invoice, it should also be shared with Hokodo using this endpoint.

Credit Notes

Credit notes are sent by the merchant to the customer whenever a post-sale action such as a discount or return is applied to an order. If you issue credit notes when processing discounts or returns, you can save your operations team a significant amount of time by uploading the credit note to Hokodo using this endpoint at the time they are raised. This allows Hokodo to respond to the customer and resolve any queries without the need to liaise with your operations team.

Shipping documents

Shipping documents are documents associated with delivery, such as a copy of the delivery confirmation signed by the recipient. These documents are useful should there be any disputes about whether delivery occurred. If merchants are routinely capturing delivery confirmation documents, then systematically sharing these with Hokodo using this endpoint will save on operational hassle for Hokodo and the merchant if/when they are ever needed.

Other

Other can be used for any other documents that the merchant wishes to share with Hokodo

OrderDocument Object

{
    "id": "odoc-afapG98cKaCL5VRjVfQQ2S",
    "order": "order-yQKxbtCg9aTS5JYnsRVA9B",
    "doc_type": "invoice",
    "description": "Invoice sent to customer",
    "amount": 10000,
    "metadata": {"unique_id": "some_unique_id"},
    "file": "https://hokodo-sandbox-clientdocuments.s3.amazonaws.com/media/order_documents/..."
}
field type description
id string(uuid) API unique identifier of the order document
order string(uuid) API identifier of the linked order
doc_type string Type of document, see below
description string Description of the document
amount int Value of the document in minor units (e.g. a credit note worth £100, will have amount=10000)
metadata dict Set of key-value pairs you can attach to the object. You can use this to store your custom data in the object and read it back later.
file string(uri) Link to the document hosted by Hokodo

OrderDocument type

Possible order document types are:

Create OrderDocument

POST /v1/payment/orders/<order_id>/documents HTTP/1.1
Host: api-sandbox.hokodo.co
Content-Type: multipart/form-data; boundary=X-CLIENT-BOUNDARY
Authorization: Token <your_api_key>
Accept: */*
Content-Length: <total_lenth>

--X-CLIENT-BOUNDARY
Content-Disposition: form-data; name="doc_type"

invoice
--X-CLIENT-BOUNDARY
Content-Disposition: form-data; name="description"

<invoice_description>
--X-CLIENT-BOUNDARY
Content-Disposition: form-data; name="amount"

<invoice_amount>
--X-CLIENT-BOUNDARY
Content-Disposition: form-data; name="metadata"
Content-Type: application/json

<invoice_metadata>
--X-CLIENT-BOUNDARY
Content-Disposition: form-data; name="file"; filename="invoice.pdf"
Content-Type: application/pdf

<...actual binary content of the file...>
--X-CLIENT-BOUNDARY
curl --request POST \
  --url https://api-sandbox.hokodo.co/v1/payment/orders/<order_id>/documents \
  --header 'Authorization: Token <your_api_key>' \
  --form doc_type=invoice \
  --form description=invoice_description \
  --form amount=invoice_amount \
  --form metadata=invoice_metadata \
  --form file=@/local/path/to/file/invoice.pdf

To create an OrderDocument, you'll need to make a post request with the Content-Type set to multipart form data. In the request body please include the binary content from the file you wish to upload.

You can optionally include doc_type, description, amount, and metadata.

field type flags description
file file required Content of the document
doc_type string optional Type of document, see above
description string optional Description of the document
amount int optional Value of the document in minor units (e.g. a credit note worth £100, will have amount=10000)
metadata dict optional Set of key-value pairs you can attach to the object. You can use this to store your custom data in the object and read it back later.

Errors

errors description
400 a required field is missing

View order document

Requests

GET /v1/payment/orders/<order_id>/documents/<document_id> HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>
curl --request GET \
     --url https://api-sandbox.hokodo.co/v1/payment/orders/<order_id>/documents/<document_id> \
     --header "Authorization: <your_api_key>"

Responses

200 Ok
Content-Type: application/json
{
    "id": "odoc-afapG98cKaCL5VRjVfQQ2S",
    "order": "order-yQKxbtCg9aTS5JYnsRVA9B",
    "doc_type": "invoice",
    "description": "Invoice Description",
    "amount": 10000,
    "metadata": {"unique_id": "some_unique_id"},
    "file": "https://hokodo-sandbox-clientdocuments.s3.amazonaws.com/media/order_documents/..."
}
  • order document not found
404 Not Found
Content-Type: application/json
{
  "detail": "Not found."
}

Look up a previously created order document.

Errors

errors description
404 the order_document_id is probably invalid, the order document has not been found

Payment Offers

The Offer API is used to create a set of payment plans for your customer. Simply provide an order id and Hokodo will return a list of payment plans that you can share with your customer at checkout, or over email or text message.

Offer Endpoints

Offer Object

{
  "url": "https://api-sandbox.hokodo.co/v1/payment/offers/offer-bqRyHAGaFrDEN8JNjXJirp",
  "id": "offer-bqRyHAGaFrDEN8JNjXJirp",
  "order": "order-dTHo9Q2idffT7CMPCVjztA",
  "offered_payment_plans": [
    {
      "id": "ppln-bqRyHAGaFrDEN8JNjXJirp",
      "name": "net30",
      "template": "pptemp-RySHMoFqSxfmkcfrYC2VeF",
      "currency": "GBP",
      "protected_amount": 100000,
      "unprotected_amount": 0,
      "scheduled_payments": [
        {
          "date": "2020-10-16",
          "amount": 100000,
          "discounted_amount": 100000,
          "customer_fee": {
            "percentage": "0.00",
            "amount": 0
          },
          "allowed_payment_methods": [
            {"type": "card"},
            {"type": "direct_debit"},
            {"type": "invoice"}
          ],
          "payment_method": {"type": "card"},
          "due_date_config": {
            "due_after_nb_days": 30,
            "due_end_of_nb_months": null,
            "amount_percentage": "100.0",
            "is_upfront_payment": false
          }
        }
      ],
      "payment_terms_relative_to": "order_creation",
      "merchant_fee": {
        "currency": "GBP",
        "amount": 1000
      },
      "customer_fee": {
        "currency": "GBP",
        "percentage": "0.00",
        "amount": 0
      },
      "customer_percentage_discount": "0.00",
      "customer_discount": {
        "currency": "GBP",
        "amount": 0
      },
      "valid_until": "2020-09-16T12:44:49.841Z",
      "payment_url": "https://payment.app.hokodo.co/plans/ppln-bqRyHAGaFrDEN8JNjXJirp",
      "status": "offered",
      "rejection_reason": null,
      "has_upfront_payment": false
    },
    {
      "id": "ppln-3NeZcmAw3rpQPN788mxKJi",
      "name": "90d + upfront",
      "template": "pptemp-LAMds7L6ENQ2BCwxQykHKE",
      "currency": "GBP",
      "protected_amount": 100000,
      "unprotected_amount": 0,
      "scheduled_payments": [
        {
          "date": "2020-09-16",
          "amount": 25000,
          "discounted_amount": 25000,
          "customer_fee": {
            "percentage": "0.00",
            "amount": 0
          },
          "allowed_payment_methods": [
            {"type": "card"}
          ],
          "payment_method": {"type": "card"},
          "due_date_config": {
            "due_after_nb_days": null,
            "due_end_of_nb_months": null,
            "amount_percentage": "25.0",
            "is_upfront_payment": true
          }
        },
        {
          "date": "2020-12-16",
          "amount": 75000,
          "discounted_amount": 75000,
          "customer_fee": {
            "percentage": "0.00",
            "amount": 0
          },
          "allowed_payment_methods": [
            {"type": "card"},
            {"type": "direct_debit"}
          ],
          "payment_method": {"type": "card"},
          "due_date_config": {
            "due_after_nb_days": 30,
            "due_end_of_nb_months": null,
            "amount_percentage": "75.0",
            "is_upfront_payment": false
          }
        }
      ],
      "payment_terms_relative_to": "order_creation",
      "merchant_fee": {
        "currency": "GBP",
        "amount": 1000
      },
      "customer_fee": {
        "currency": "GBP",
        "percentage": "0.00",
        "amount": 0
      },
      "customer_percentage_discount": "0.00",
      "customer_discount": {
        "currency": "GBP",
        "amount": 0
      },
      "valid_until": "2020-09-16T12:44:49.841Z",
      "payment_url": "https://payment.app.hokodo.co/plans/ppln-3NeZcmAw3rpQPN788mxKJi",
      "status": "offered",
      "rejection_reason": null,
      "has_upfront_payment": true
    }
  ],
  "urls": {
    "success": "https://merchant.com/payment/ok",
    "failure": "https://merchant.com/checkout",
    "cancel": "https://merchant.com/checkout",
    "notification": "https://backend.merchant.com/payment/notifications",
    "merchant_terms": "https://merchant.com/terms"
  },
  "locale": "en-gb",
  "metadata": {}
}
field type description
url string API endpoint to access the Offer
id string(uuid) API identifier for the Offer
order string(uuid) API identifier for the attached Transaction
offered_payment_plans list List of payment plans you can offer to your customer
legals dictionary An internal field which is subject to change
urls dictionary Redirection and callback URLs
urls[merchant_terms] string(url) URL for the terms and conditions of your platform, to display to the user
urls[success] string(url) URL to redirect the customer to if the deferred payment application is a success
urls[failure] string(url) URL to redirect the customer to if the deferred payment application is rejected. For example the checkout page to finish with another payment method
urls[cancel] string(url) URL to redirect the customer to if they cancel the application before completing it. For example the checkout page to finish with another payment method
urls[notification] string(url) Callback URL to receive notifications about the deferred payment application
locale string Language and region of the customer (RFC 1766), for example "en-gb" or "fr-fr"
metadata dictionary Set of key-value pairs to store additional information about the Offer

Payment Plan Object

field type description
id string(uuid) API identifier for the Payment Plan
name string Payment plan name (e.g. Pay in 30 days, Pay in 3 installments)
template string Hokodo identifier of the template from which the payment plan data object was created
currency string string
protected_amount int Amount that can be protected by Hokodo, in minor units (cents)
unprotected_amount int Amount without insurance against non-payment, in minor units (cents)
scheduled_payments list The re-payment schedule for the plan (e.g. your customer will pay £x amount on YYYY-MM-DD date)
scheduled_payments[date] string Date when the payment is due (e.g. 2020-09-16). If you offer your buyers payment terms upon fulfillment/capture (e.g. payment_terms_relative_to=first_capture), when order fulfillment/capture occurs, then this date may be recalculated and updated
scheduled_payments[amount] int Amount your customer will pay on this date in pence/cents
scheduled_payments[discounted_amount] int Projected amount in draft mode, amount including discount, in pence/cents, your customer will pay once this scheduled payment is no longer in draft
scheduled_payments[customer_fee] dictionary Amount, in pence/cents, and percentage of the fees for the customer for this scheduled payment (included in the scheduled payment amount)
scheduled_payments[allowed_payment_methods] list List of payment method types allowed to make a payment with
scheduled_payments[payment_method] string Payment method assigned to use. This gets assigned when the Deferred Payment is created (null if there is no DeferredPayment)
scheduled_payments[due_date_config] dictionary A Scheduled Payment Due Date Config object. The settings that determine how your buyers scheduled_payments will be generated
payment_terms_relative_to string An event in the lifecycle of an order. Your buyers scheduled payment dates will be calculated relative to the date of this event. Either order_creation, when your buyer is checking-out. Or first_capture, when you mark any part of the order as fulfilled/captured
merchant_fee dictionary Amount and currency of the fees for you for this payment plan
customer_fee dictionary Amount, percentage, and currency of the fees for the customer for this payment plan (included in the scheduled payments)
customer_percentage_discount string Percentage to discount on the order for this payment plan
customer_discount dictionary Amount and currency of the discount for the customer for this payment plan
valid_until date Time when payment plan offer expires. After this date, your customer cannot avail of this plan
payment_url string Link where your customer can apply for the payment plan
status string Current status of the payment plan (e.g. offered, accepted, declined, expired, cancelled)
rejection_reason dictionary Rejection reason if Offer is declined, see rejection reasons
rejection_reason[code] string A text label identifying the reason
rejection_reason[detail] string A detailed explanation of why the Offer was declined. This can be shared with your customer
rejection_reason[params] dictionary A dictionary of dynamic key-value pairs which can be used to customize the rejection reason
has_upfront_payment boolean If this template contain a scheduled payment to be paid upfront, False otherwise

protected_amount and unprotected_amount can be used to check what part of a payment plan will be protected by Hokodo or not. If your contract permits it, payment offers can be created that are not totally protected by Hokodo.

Note: When your customer clicks on the Payment plan's payment_url a Deferred Payment object will be created automatically.

Scheduled Payment Due Date Config Object

field type description
due_after_nb_days int A rule for deciding how the scheduled_payments.date will be calculated. It will be relative to the event specified in the payment plan payment_terms_relative_to. This will be null if due_end_of_nb_months has been specified instead
due_end_of_nb_months int A rule for deciding how the scheduled_payments.date will be calculated. The payment will be due on the last day of a month. The month it will be due on, is the current month, plus the value of this field. This is relative to the event specified in the payment plan payment_terms_relative_to. A value of 0 means it will be due at the end of the current month. 1 means at the end of next month. This will be null if due_end_of_nb_days has been specified instead
amount_percentage decimal The amount your buyer will pay at this time, as a percentage of the total order value. This value may be null for old/historical payment offers.
is_upfront_payment boolean Is True if this scheduled payment should be paid upfront

Request a New Offer

Request

POST /v1/payment/offers HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "order": "order-dTHo9Q2idffT7CMPCVjztA",
  "urls": {
    "success": "https://merchant.com/payment/ok",
    "failure": "https://merchant.com/checkout",
    "cancel": "https://merchant.com/checkout",
    "notification": "https://backend.merchant.com/payment/notifications",
    "merchant_terms": "https://merchant.com/terms"
  },
  "locale": "en-gb",
  "metadata": {}
}
curl --request POST \
     --url https://api-sandbox.hokodo.co/v1/payment/offers \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>" \
     --data-binary '{
  "order": "order-dTHo9Q2idffT7CMPCVjztA",
  "urls": {
    "success": "https://merchant.com/payment/ok",
    "failure": "https://merchant.com/checkout",
    "cancel": "https://merchant.com/checkout",
    "notification": "https://backend.merchant.com/payment/notifications",
    "merchant_terms": "https://merchant.com/terms"
  },
  "locale": "en-gb",
  "metadata": {}
}'

Responses

  • Offer Offered
201 Created
Content-Type: application/json
{
  "url": "https://api-sandbox.hokodo.co/v1/payment/offers/offer-EzH6BixNSHvaByEpXcFW5h",
  "id": "offer-bqRyHAGaFrDEN8JNjXJirp",
  "order": "order-dTHo9Q2idffT7CMPCVjztA",
  "offered_payment_plans": [
    {
      "id": "ppln-gJdDHAGaFrDLDvJNXJird",
      "name": "4xEOM",
      "template": "pptemp-RySHMoFqSxfmkcfrYC2VeF",
      "currency": "GBP",
      "protected_amount": 100400,
      "unprotected_amount": 0,
      "scheduled_payments": [
        {
          "date": "2020-09-30",
          "amount": 25100,
          "discounted_amount": 25100,
          "customer_fee": {
            "percentage": "0.00",
            "amount": 0
          },
          "allowed_payment_methods": [
            {"type": "card"},
            {"type": "direct_debit"},
            {"type": "invoice"}
          ],
          "payment_method": null,
          "due_date_config": {
            "due_after_nb_days": null,
            "due_end_of_nb_months": 0,
            "amount_percentage": "25.0",
            "is_upfront_payment": false
          }
        },
        {
          "date": "2020-10-31",
          "amount": 25100,
          "discounted_amount": 25100,
          "customer_fee": {
            "percentage": "0.00",
            "amount": 0
          },
          "allowed_payment_methods": [
            {"type": "card"}
          ],
          "payment_method": null,
          "due_date_config": {
            "due_after_nb_days": null,
            "due_end_of_nb_months": 1,
            "amount_percentage": "25.0",
            "is_upfront_payment": false
          }
        },
        {
          "date": "2020-11-30",
          "amount": 25100,
          "discounted_amount": 25100,
          "customer_fee": {
            "percentage": "0.00",
            "amount": 0
          },
          "allowed_payment_methods": [
            {"type": "card"}
          ],
          "payment_method": null,
          "due_date_config": {
            "due_after_nb_days": null,
            "due_end_of_nb_months": 2,
            "amount_percentage": "25.0",
            "is_upfront_payment": false
          }
        },
        {
          "date": "2020-12-31",
          "amount": 25100,
          "discounted_amount": 25100,
          "customer_fee": {
            "percentage": "0.00",
            "amount": 0
          },
          "allowed_payment_methods": [
            {"type": "card"}
          ],
          "payment_method": null,
          "due_date_config": {
            "due_after_nb_days": null,
            "due_end_of_nb_months": 3,
            "amount_percentage": "25.0",
            "is_upfront_payment": false
          }
        }
      ],
      "payment_terms_relative_to": "order_creation",
      "merchant_fee": {
        "currency": "GBP",
        "amount": 1000
      },
      "customer_fee": {
        "currency": "GBP",
        "percentage": "0.00",
        "amount": 0
      },
      "customer_percentage_discount": "0.00",
      "customer_discount": {
        "currency": "GBP",
        "amount": 0
      },
      "valid_until": "2020-09-16T12:44:49.841Z",
      "payment_url": "https://payment.app.hokodo.co/plans/ppln-bqRyHAGaFrDEN8JNjXJirp",
      "status": "offered",
      "rejection_reason": null,
      "has_upfront_payment": false
    }
  ],
  "urls": {
    "success": "https://merchant.com/payment/ok",
    "failure": "https://merchant.com/checkout",
    "cancel": "https://merchant.com/checkout",
    "notification": "https://backend.merchant.com/payment/notifications",
    "merchant_terms": "https://merchant.com/terms"
  },
  "locale": "en-gb",
  "metadata": {}
}
  • Offer Rejected
201 Created
Content-Type: application/json
{
  "url": "https://api-sandbox.hokodo.co/v1/payment/offers/offer-3VezfMFGKX6U247jRhXAkQ",
  "id": "offer-3VezfMFGKX6U247jRhXAkQ",
  "order": "order-yQKxbtCg9aTS5JYnsRVA9B",
  "offered_payment_plans": [
    {
      "id": "ppln-bqRyHAGaFrDEN8JNjXJirp",
      "name": "net30",
      "template": "pptemp-RySHMoFqSxfmkcfrYC2VeF",
      "currency": "GBP",
      "protected_amount": 100000,
      "unprotected_amount": 0,
      "scheduled_payments": [
        {
          "date": "2020-10-16",
          "amount": 100000,
          "discounted_amount": 100000,
          "customer_fee": {
            "percentage": "0.00",
            "amount": 0
          },
          "allowed_payment_methods": [
            {"type": "card"},
            {"type": "direct_debit"},
            {"type": "invoice"}
          ],
          "payment_method": {"type": "card"},
          "due_date_config": {
            "due_after_nb_days": 30,
            "due_end_of_nb_months": null,
            "amount_percentage": "100.0",
            "is_upfront_payment": false
          }
        }
      ],
      "payment_terms_relative_to": "order_creation",
      "merchant_fee": {
        "currency": "GBP",
        "amount": 1000
      },
      "customer_fee": {
        "currency": "GBP",
        "percentage": "0.00",
        "amount": 0
      },
      "customer_percentage_discount": "0.00",
      "customer_discount": {
        "currency": "EUR",
        "amount": 0
      },
      "valid_until": "2020-09-16T12:44:49.841Z",
      "payment_url": "https://payment.app.hokodo.co/plans/ppln-bqRyHAGaFrDEN8JNjXJirp",
      "status": "declined",
      "rejection_reason": {
        "code": "buyer-country",
        "detail": "We're currently unable to provide payment plans to Buyers domiciled in {debtor_country}.",
        "params": {
          "debtor_country": "Ireland"
        }
      },
      "has_upfront_payment": false
    }
  ],
  "urls": {
    "success": "https://merchant.com/payment/ok",
    "failure": "https://merchant.com/checkout",
    "cancel": "https://merchant.com/checkout",
    "notification": "https://backend.merchant.com/payment/notifications",
    "merchant_terms": "https://merchant.com/terms"
  },
  "locale": "en-gb",
  "metadata": {}
}

This endpoint is used to create a list of payment options for your customer. The required fields are

You can optionally include a metadata object to store additional information about the Offer.

field type flags description
order string(uuid) required API unique identifier of the order
urls dictionary required Redirection and callback URLs
urls[merchant_terms] string(url) required URL for the terms and conditions of your platform, to display to the user
urls[success] string(url) required URL to redirect the customer to if the deferred payment application is a success
urls[failure] string(url) required URL to redirect the customer to if the deferred payment application is rejected. For example the checkout page to finish with another payment method
urls[cancel] string(url) required URL to redirect the customer to if they cancel the application before completing it. For example the checkout page to finish with another payment method
urls[notification] string(url) required Callback URL to receive notifications about the deferred payment application
locale string optional Language and region of the customer (RFC 1766), for example "en-gb" or "fr-fr"
metadata dictionary optional Set of key-value pairs to store additional information about the Offer.

Errors

errors description
400 a required field is missing
409 can't obtain an offer as order has already been paid

List Offers

Request

GET /v1/payment/offers HTTP/1.1
Authorization: Token <your_api_key>
curl --request GET \
     --url https://api-sandbox.hokodo.co/v1/payment/offers \
     --header "Authorization: <your_api_key>"

Response

200 Ok
Content-Type: application/json
{
  "count": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "url": "https://api-sandbox.hokodo.co/v1/payment/offers/offer-EzH6BixNSHvaByEpXcFW5h",
      "id": "offer-bqRyHAGaFrDEN8JNjXJirp",
      "order": "order-dTHo9Q2idffT7CMPCVjztA",
      "offered_payment_plans": [
        {
          "id": "ppln-bqRyHAGaFrDEN8JNjXJirp",
          "name": "net30",
          "template": "pptemp-RySHMoFqSxfmkcfrYC2VeF",
          "currency": "GBP",
          "protected_amount": 100000,
          "unprotected_amount": 0,
          "scheduled_payments": [
            {
              "date": "2020-10-16",
              "amount": 100000,
              "discounted_amount": 100000,
              "customer_fee": {
                "percentage": "0.00",
                "amount": 0
              },
              "allowed_payment_methods": [
                {"type": "card"},
                {"type": "direct_debit"},
                {"type": "invoice"}
              ],
              "payment_method": {"type": "card"},
              "due_date_config": {
                "due_after_nb_days": 30,
                "due_end_of_nb_months": null,
                "amount_percentage": "100.0",
                "is_upfront_payment": false
              }
            }
          ],
          "payment_terms_relative_to": "order_creation",
          "merchant_fee": {
            "currency": "GBP",
            "amount": 1000
          },
          "customer_fee": {
            "currency": "GBP",
            "percentage": "0.00",
            "amount": 0
          },
          "customer_percentage_discount": "0.00",
          "customer_discount": {
            "currency": "EUR",
            "amount": 0
          },
          "valid_until": "2020-09-16T12:44:49.841Z",
          "payment_url": "https://payment.app.hokodo.co/plans/ppln-bqRyHAGaFrDEN8JNjXJirp",
          "status": "offered",
          "rejection_reason": null,
          "has_upfront_payment": false
        }
      ],
      "urls": {
        "success": "https://merchant.com/payment/ok",
        "failure": "https://merchant.com/checkout",
        "cancel": "https://merchant.com/checkout",
        "notification": "https://backend.merchant.com/payment/notifications",
        "merchant_terms": "https://merchant.com/terms"
      },
      "locale": "en-gb",
      "metadata": {}
    },
    {
      "url": "https://api-sandbox.hokodo.co/v1/payment/offers/offer-3VezfMFGKX6U247jRhXAkQ",
      "id": "offer-3VezfMFGKX6U247jRhXAkQ",
      "order": "order-yQKxbtCg9aTS5JYnsRVA9B",
      "offered_payment_plans": [
        {
          "id": "ppln-bqRyHAGaFrDEN8JNjXJirp",
          "name": "net30",
          "template": "pptemp-gXPguT3zqDQamD5N3KEjp2",
          "currency": "GBP",
          "protected_amount": 100000,
          "unprotected_amount": 0,
          "scheduled_payments": [
            {
              "date": "2020-10-16",
              "amount": 100000,
              "discounted_amount": 100000,
              "customer_fee": {
                "percentage": "0.00",
                "amount": 0
              },
              "allowed_payment_methods": [
                {"type": "card"},
                {"type": "direct_debit"},
                {"type": "invoice"}
              ],
              "payment_method": {"type": "card"},
              "due_date_config": {
                "due_after_nb_days": 30,
                "due_end_of_nb_months": null,
                "amount_percentage": "100.0",
                "is_upfront_payment": false
              }
            }
          ],
          "payment_terms_relative_to": "order_creation",
          "merchant_fee": {
            "currency": "GBP",
            "amount": 1000
          },
          "customer_fee": {
            "currency": "GBP",
            "percentage": "0.00",
            "amount": 0
          },
          "customer_percentage_discount": "0.00",
          "customer_discount": {
            "currency": "EUR",
            "amount": 0
          },
          "valid_until": "2020-09-16T12:44:49.841Z",
          "payment_url": "https://payment.app.hokodo.co/plans/ppln-bqRyHAGaFrDEN8JNjXJirp",
          "status": "declined",
          "rejection_reason": {
            "code": "buyer-country",
            "detail": "We're currently unable to provide payment plans to Buyers domiciled in {debtor_country}.",
            "params": {
              "debtor_country": "Ireland"
            }
          },
          "has_upfront_payment": false
        }
      ],
      "urls": {
        "success": "https://merchant.com/payment/ok",
        "failure": "https://merchant.com/checkout",
        "cancel": "https://merchant.com/checkout",
        "notification": "https://backend.merchant.com/payment/notifications",
        "merchant_terms": "https://merchant.com/terms"
      },
      "locale": "en-gb",
      "metadata": {}
    }
  ]
}

List all previously requested Offers

View Offer

Request

GET /v1/payment/offers/<offer_id> HTTP/1.1
Authorization: Token <your_api_key>
curl --request GET \
     --url https://api-sandbox.hokodo.co/v1/payment/offers/<offer_id> \
     --header "Authorization: <your_api_key>"

Responses

  • regular response
200 Ok
Content-Type: application/json
{
  "url": "https://api-sandbox.hokodo.co/v1/payment/offers/offer-EzH6BixNSHvaByEpXcFW5h",
  "id": "offer-bqRyHAGaFrDEN8JNjXJirp",
  "order": "order-dTHo9Q2idffT7CMPCVjztA",
  "offered_payment_plans": [
    {
      "id": "ppln-bqRyHAGaFrDEN8JNjXJirp",
      "name": "net30",
      "template": "pptemp-RySHMoFqSxfmkcfrYC2VeF",
      "currency": "GBP",
      "protected_amount": 100000,
      "unprotected_amount": 0,
      "scheduled_payments": [
      {
          "date": "2020-10-16",
          "amount": 100000,
          "discounted_amount": 100000,
          "customer_fee": {
            "percentage": "0.00",
            "amount": 0
          },
          "allowed_payment_methods": [
            {"type": "card"},
            {"type": "direct_debit"},
            {"type": "invoice"}
          ],
          "payment_method": {"type": "card"},
          "due_date_config": {
            "due_after_nb_days": 30,
            "due_end_of_nb_months": null,
            "amount_percentage": "100.0",
            "is_upfront_payment": false
          }
        }
      ],
      "payment_terms_relative_to": "order_creation",
      "merchant_fee": {
        "currency": "GBP",
        "amount": 1000
      },
      "customer_fee": {
        "currency": "GBP",
        "percentage": "0.00",
        "amount": 0
      },
      "customer_percentage_discount": "0.00",
      "customer_discount": {
        "currency": "EUR",
        "amount": 0
      },
      "valid_until": "2020-09-16T12:44:49.841Z",
      "payment_url": "https://payment.app.hokodo.co/plans/ppln-bqRyHAGaFrDEN8JNjXJirp",
      "status": "offered",
      "rejection_reason": null,
      "has_upfront_payment": false
    }
  ],
  "urls": {
    "success": "https://merchant.com/payment/ok",
    "failure": "https://merchant.com/checkout",
    "cancel": "https://merchant.com/checkout",
    "notification": "https://backend.merchant.com/payment/notifications",
    "merchant_terms": "https://merchant.com/terms"
  },
  "locale": "en-gb",
  "metadata": {}
}
  • Not Found
404 Not Found
Content-Type: application/json
{
  "detail": "Not found."
}

Retrieve a Previously Requested Offer

Errors

Errors Description
404 The Offer id is probably incorrect, a Offer has not been found

Delete Offer

Request

DELETE /v1/payment/offers/<offer_id> HTTP/1.1
Authorization: Token <your_api_key>
curl --request DELETE \
     --url https://api-sandbox.hokodo.co/v1/payment/offers/<offer_id> \
     --header "Authorization: <your_api_key>"

Responses

  • regular response
204 No Content
  • Not Found
404 Not Found
Content-Type: application/json
{
  "detail": "Not found."
}
  • Unable to Delete Accepted Offer
409 Conflict
Content-Type: application/json

Delete a Previously Requested Offer

Errors

errors description
404 The Offer id is probably incorrect, a Offer has not been found
409 Can't delete the Offer, probably because it's already been accepted

Mail offer to customer

Request

PUT /v1/payment/payment_plans/ppln-bqRyHAGaFrDEN8JNjXJirp/send_offer_email HTTP/1.1
Authorization: Token <your_api_key>
curl --request PUT \
     --url https://api-sandbox.hokodo.co/v1/payment/payment_plans/ppln-bqRyHAGaFrDEN8JNjXJirp/send_offer_email \
     --header "Authorization: <your_api_key>"

Responses

  • Offer sent to customer by email
200 OK
Content-Type: application/json
{
    "detail": "Payment plan email sent."
}

You can use this endpoint to have Hokodo send an email to the customer, with a link to a specific payment plan.

Errors

errors description
400 Payment Plan invalid (for example declined)

Deferred Payments

A Deferred Payment object is created when your customer completes the process to pay with Hokodo.

Deferred Payment Endpoints

Deferred Payment Object

{
  "url": "https://api-sandbox.hokodo.co/v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp",
  "id": "defpay-bqRyGIGaORKiK8bhMVPirp",
  "number": "P-7WR2-PR0S",
  "created": "2022-07-11T12:48:02.788770Z",
  "payment_plan": "ppln-gJdDHAGaFrDLDvJNXJird",
  "order": "order-dTHo9Q2idffT7CMPCVjztA",
  "rejection_reason":
  {
    "code": "insufficient_funds",
    "detail": "Insufficient funds"
  },
  "status": "pending_review",
  "currency": "GBP",
  "authorisation": 50000,
  "protected_captures": 0,
  "unprotected_captures": 0,
  "refunds": 10000,
  "voided_authorisation": 15000,
  "expired_authorisation": 0,
  "events": []
}
field type description
url string API endpoint to access the Deferred Payment
id string(uuid) API unique identifier for the Deferred Payment
number string The Deferred Payment's customer friendly public identifier (e.g. "P-7WR2-PR0S")
created datetime Date & Time the Deferred Payment was created
payment_plan string(uuid) API unique identifier of the personalised payment plan attached to the deferred payment
order string(uuid) API identifier for the Order
rejection_reason dictionary Rejection reason, null if not rejected
rejection_reason[code] string A text label identifying the reason
rejection_reason[detail] string An explanation of why the deferred payment was rejected
status string Deferred Payment status
currency currency Currency of deferred payment amounts
authorisation int Amount that can still be captured and protected by Hokodo, in minor units (cents)
protected_captures int Amount that will be asked from the buyer with insurance against non-payment, in minor units (cents)
unprotected_captures int Amount that will be asked from the buyer without insurance against non-payment, in minor units (cents)
refunds int Amount that the buyer might have been asked to pay at some point but is not due anymore, in minor units (cents)
voided_authorisation int Amount that used to be authorised but has been released by API, in minor units (cents)
expired_authorisation int Amount that used to be authorised but has been automatically released, in minor units (cents)
events[*] Post Sale event List of events created by post-sale actions (see below for details)

Values of all amounts above from authorisation to expired_authorisation are guaranteed to sum to a constant amount, equal to the order total amount. See next section about post-sale actions for more details on how these amounts can change.

The amount that has been captured (and not refunded) is split between protected_captures and unprotected_captures. All captures will be protected_captures up to the protected_amount of the Payment Plan. For details on the difference between these two types of capture, see Protected Captures vs. Unprotected Captures.

Rejection reason

Provides information on the reason for rejection.

{
  "rejection_reason":
  {
    "code": "insufficient_funds",
    "detail": "Insufficient funds"
  },
  "status": "rejected"
}

Possible reasons for rejection:

Deferred Payment status

When it is created, the deferred payment status can be one of:

code description
accepted the payment has been accepted
pending_review the payment is pending manual review by Hokodo, you will be notified of the result
customer_action_required more information is required by the customer (e.g. upload KYC documents)
rejected the payment has been rejected by Hokodo

After that, dependent upon the post sale API version in use, the deferred payment status can become one of:

code description post sale version
part_fulfilled the payment has been partially fulfilled, and there is more to be fulfilled v1
fulfilled the payment has been fulfilled (partially or all), and there is nothing left to fulfil v1
reversed the payment might have been fulfilled, but everything has been returned and there is nothing left to fulfil v1
cancelled no fulfilment has been attempted, the payment has been entirely cancelled v1
part_captured the payment has been partially captured, and there is some authorisation remaining v2
captured the payment has been captured (partially or fully), and there is no authorisation remaining v2
refunded the payment might have been captured, but everything has been refunded and there is no authorisation left v2
voided no capture has been attempted, the payment has been entirely voided v2
expired the payment has expired before anything had been captured v2

View Deferred Payment

Request

GET /v1/payment/deferred_payments/<deferredpayment_id> HTTP/1.1
Authorization: Token <your_api_key>
curl --request GET \
     --url https://api-sandbox.hokodo.co/v1/payment/deferred_payments/<deferredpayment_id> \
     --header "Authorization: <your_api_key>"

Responses

  • regular response
200 Ok
Content-Type: application/json
{
  "url": "https://api-sandbox.hokodo.co/v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp",
  "id": "defpay-bqRyGIGaORKiK8bhMVPirp",
  "number": "P-7WR2-PR0S",
  "payment_plan": "ppln-gJdDHAGaFrDLDvJNXJird",
  "order": "order-dTHo9Q2idffT7CMPCVjztA",
  "status": "accepted",
  "currency": "GBP",
  "authorisation": 50000,
  "protected_captures": 20000,
  "unprotected_captures": 0,
  "refunds": 10000,
  "voided_authorisation": 15000,
  "expired_authorisation": 5000
}
  • Not Found
404 Not Found
Content-Type: application/json
{
  "detail": "Not found."
}

Retrieve an existing Deferred Payment object.

Post Sale actions

After the deferred payment has been created, you must use the post-sale endpoints to inform Hokodo about order completion (usually shipment) and other events happening after the sale process.

In terms of API objects: to complete the checkout, the buyer accepts a PaymentOffer and a DeferredPayment is created. The post-sale endpoints relate to that particular DeferredPayment, and make modifications to notify Hokodo of how much of the Order the buyer should be charged for.

These will not all be necessary for every order. The base flow would be:

  1. Create the Order.
  2. Request the PaymentOffer.
  3. The customer accepts one of the payment plans and confirms the order.
  4. You ask us to capture an amount from the customer equal to the value of goods shipped.
  5. Hokodo generates a payout to you according to schedule.
  6. Hokodo records that customer shall repay that amount later, based upon the customer's payment plan.

Post sale endpoints

Post sale event

{
  "created": "2020-10-15T19:53:42.345Z",
  "type": "capture",
  "amount": 5000,
  "currency": "GBP",
  "metadata": {
    "reference": "Bob's burger patties",
    "supplier": "Krusty Krabs Factory"
  },
  "changes": {
    "authorisation": -5000,
    "protected_captures": 5000,
    "unprotected_captures": 0,
    "refunds": 0,
    "voided_authorisation": 0,
    "expired_authorisation": 0,
    "customer_fee": {
      "authorisation": 0,
      "captures": 0,
      "refunds": 0,
      "voided_authorisation": 0,
      "expired_authorisation": 0
    }
  }
}
field type flags description
created datetime read-only API endpoint to access the order
type string read-only Type of the event (e.g. capture, refund, void, expiry, adjustment)
amount int required Amount of money moved as part of the event, in minor units (cents)
currency currency read-only Currency of all monetary amounts recorded by this event
metadata dictionary optional Set of key-value pairs to store additional information about the event
changes[authorisation] int read-only Change in the Deferred Payment's authorisation caused by this event, in minor units (cents)
changes[protected_captures] int read-only Change in the Deferred Payment's protected_captures caused by this event, in minor units (cents)
changes[unprotected_captures] int read-only Change in the Deferred Payment's unprotected_captures caused by this event, in minor units (cents)
changes[refunds] int read-only Change in the Deferred Payment's refunds caused by this event, in minor units (cents)
changes[voided_authorisation] int read-only Change in the Deferred Payment's voided_authorisation caused by this event, in minor units (cents)
changes[expired_authorisation] int read-only Change in the Deferred Payment's expired_authorisation caused by this event, in minor units (cents)
changes[customer_fee] dictionary read-only Contains changes affecting the customer fee post sale values, caused by this event, in minor units (cents)

Each event is to be interpreted as an accounting entry moving money from an account to another. Because of that following conditions are guaranteed:

Events of type expiry are equivalent to void events but are created automatically by Hokodo after some time define in your contract. This exists to ensure that authorisation is eventually freed for your customer to continue using Hokodo's BNPL solution.

Events of type adjustment might be created by Hokodo operations to help you tidy up bookkeeping in case of mistakes or to handle corner cases. These should however be rare to best enjoy the power of the API.

You may want to notify Hokodo that a specific event relates to an individual supplier or is related to a specific item. You might also want to record the tracking number of the shipment. The metadata field can be used to record any of this information for future use. Data in this metadata field can be included in the payout information we send to you to ease reconciliation.

Post Sale API supports idempotent requests, detailed in the section on Idempotent requests.

Capture

Request

POST /v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/capture HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "amount": 100000,
  "metadata": {
    "reference": "Bobs burger patties"
  }
}
curl --request POST \
     --url https://api-sandbox.hokodo.co/v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/capture \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>" \
     --data-binary '{
  "amount": 100000,
  "metadata": {
    "reference": "Bobs burger patties"
  }
}'

Response

201 Ok
Content-Type: application/json
{
  "created": "2020-10-15T19:53:42.345Z",
  "type": "capture",
  "amount": 100000,
  "currency": "GBP",
  "metadata": {
    "reference": "Bobs burger patties"
  },
  "changes": {
    "authorisation": -100000,
    "protected_captures": 100000,
    "unprotected_captures": 0,
    "refunds": 0,
    "voided_authorisation": 0,
    "expired_authorisation": 0,
    "customer_fee": {
      "authorisation": 0,
      "captures": 0,
      "refunds": 0,
      "voided_authorisation": 0,
      "expired_authorisation": 0
    }
  }
}

Notifies Hokodo that goods have been shipped or services provided to the customer. The given amount of money is now due by the customer on top of what had already been captured before. Money is moved from authorisation to protected_captures first and possibly unprotected_captures.

It is important to notify Hokodo when the order is shipped because this is the trigger for Hokodo to make a payment to you and is the value that we will charge the customer according to the agreed payment plan. This endpoint is usually called when the package has been handed over to the carrier or the customer given access to services. Make sure that your fulfilment department, or external fulfilment partner, has access to the API. If the order is sent out by multiple shipments, you should make a request for each shipment.

Protected Captures vs. Unprotected Captures

The amount that has been captured (and not refunded) is split between the protected_captures and unprotected_captures fields.

All captures will be protected_captures up to the protected_amount of the Payment Plan. There are two ways to get unprotected_captures:

  1. If you have the Merchant Limits feature enabled, you may have an unprotected_amount on your Payment Plan. In this case, any captures above the protected_amount will appear as unprotected_captures. The Deferred Payment's authorisation includes both the protected and unprotected part.
  2. If you have the Overcaptures feature enabled, any captures above the Deferred Payment's authorisation will be taken as unprotected_captures. The Deferred Payment's authorisation will become negative.

Constraints

Capture data must contain an amount and can include metadata.

The value of amount should be the cost of the goods that have been captured at this time, including any tax or shipment fee:

You will receive an HTTP error 400 in case these conditions aren't met.

Capture all the remaining authorisation

Request

POST /v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/capture_remaining HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "metadata": {
    "reference": "Bobs burger patties"
  }
}
curl --request POST \
     --url https://api-sandbox.hokodo.co/v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/capture_remaining  \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>" \
     --data-binary '{
  "metadata": {
    "reference": "Bobs burger patties"
  }
}'

Responses

  • authorisation > 0
201 Ok
Content-Type: application/json
{
  "created": "2020-10-15T19:53:42.345Z",
  "type": "capture",
  "amount": 100000,
  "currency": "GBP",
  "metadata": {
    "reference": "Bobs burger patties"
  },
  "changes": {
    "authorisation": -100000,
    "protected_captures": 100000,
    "unprotected_captures": 0,
    "refunds": 0,
    "voided_authorisation": 0,
    "expired_authorisation": 0,
    "customer_fee": {
      "authorisation": 0,
      "captures": 0,
      "refunds": 0,
      "voided_authorisation": 0,
      "expired_authorisation": 0
    }
  }
}
  • authorisation == 0
200 Ok No content

Capture all the remaining authorisation. This behaves differently based on the remaining authorisation:

Refund

Request

POST /v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/refund HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "amount": 30000,
  "metadata": {
    "reference": "Bobs burger patties"
  }
}
curl --request POST \
     --url https://api-sandbox.hokodo.co/v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/refund \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>" \
     --data-binary '{
  "amount": 30000,
  "metadata": {
    "reference": "Bobs burger patties"
  }
}'

Response

201 Ok
Content-Type: application/json
{
  "created": "2020-10-15T19:53:42.345Z",
  "type": "refund",
  "amount": 30000,
  "currency": "GBP",
  "metadata": {
    "reference": "Bobs burger patties"
  },
  "changes": {
    "authorisation": 0,
    "protected_captures": -30000,
    "unprotected_captures": 0,
    "refunds": 30000,
    "voided_authorisation": 0,
    "expired_authorisation": 0,
    "customer_fee": {
      "authorisation": 0,
      "captures": 0,
      "refunds": 0,
      "voided_authorisation": 0,
      "expired_authorisation": 0
    }
  }
}

Notifies Hokodo that a customer has been refunded goods or services or and that we should charge less than previously told.

You should use this endpoint when a customer returns goods or you want to reduce the captured amount for any other reason (like applying an immediate discount as a gesture of good will). A refund can be any value up to the amount that has been previously captured using v1/payment/deferred_payment/<deferred_payment_id>/capture.

Note that any amount previously captured above the authorisation and counted toward unprotected_captures is refunded first so that as much as possible of the amount due buy the buyer is insured against non-payment.

Constraints

Refund data must contain an amount and can include metadata.

The value of amount should be how much you wish to refund to the customer:

Void

Request

POST /v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/void HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "amount": 5000,
  "metadata": {
    "reference": "Bobs burger patties"
  }
}
curl --request POST \
     --url https://api-sandbox.hokodo.co/v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/void \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>" \
     --data-binary '{
  "amount": 5000,
  "metadata": {
    "reference": "Bobs burger patties"
  }
}'

Response

201 Ok
Content-Type: application/json
{
  "created": "2020-10-15T19:53:42.345Z",
  "type": "void",
  "amount": 5000,
  "currency": "GBP",
  "metadata": {
    "reference": "Bobs burger patties"
  },
  "changes": {
    "authorisation": -5000,
    "protected_captures": 0,
    "unprotected_captures": 0,
    "refunds": 0,
    "voided_authorisation": 5000,
    "expired_authorisation": 0,
    "customer_fee": {
      "authorisation": 0,
      "captures": 0,
      "refunds": 0,
      "voided_authorisation": 0,
      "expired_authorisation": 0
    }
  }
}

Notifies Hokodo that a part of the order has been cancelled and you don't intend on capturing some of the initial authorisation. The purpose of this is to release part or all of the buyers remaining authorisation with Hokodo and thus increase their credit limit.

Constraints

Void data must contain an amount and can include metadata.

The value of amount should be how much you wish to cancel from the order and not charge the customer:

You will receive an HTTP error 400 in case these conditions aren't met.

Void all the remaining authorisation

Request

POST /v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/void_remaining HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "metadata": {
    "reference": "Bobs burger patties"
  }
}
curl --request POST \
     --url https://api-sandbox.hokodo.co/v1/payment/deferred_payments/defpay-bqRyGIGaORKiK8bhMVPirp/void_remaining  \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>" \
     --data-binary '{
  "metadata": {
    "reference": "Bobs burger patties"
  }
}'

Responses

  • authorisation > 0
201 Ok
Content-Type: application/json
{
  "created": "2020-10-15T19:53:42.345Z",
  "type": "void",
  "amount": 100000,
  "currency": "GBP",
  "metadata": {
    "reference": "Bobs burger patties"
  },
  "changes": {
    "authorisation": -100000,
    "protected_captures": 0,
    "unprotected_captures": 0,
    "refunds": 0,
    "voided_authorisation": 100000,
    "expired_authorisation": 0,
    "customer_fee": {
      "authorisation": 0,
      "captures": 0,
      "refunds": 0,
      "voided_authorisation": 0,
      "expired_authorisation": 0
    }
  }
}
  • authorisation == 0
200 Ok No content

Void all the remaining authorisation. This behaves differently based on the remaining authorisation:

Post-sale Order actions (Legacy)

After a PaymentOffer has been accepted by the customer, you will need to use the following endpoints to make modifications to the Order.

These will not all be necessary for every order. The base flow would be:

  1. Create the Order.
  2. Request the PaymentOffer.
  3. The customer accepts one of the payment plans and confirms the order.
  4. You mark the order as fulfilled as you ship it.
  5. Hokodo sends you the money immediately.
  6. The customer pays Hokodo later.

Post-sale Order endpoints

Fulfillment

Request

PUT /v1/payment/orders/<order_id>/fulfill HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "items": [
    {
      "item_id": "1",
      "quantity": "10.000",
      "total_amount": 10000,
      "tax_amount": 2000,
      "shipping_id": "DX49581904385",
      "shipping_provider": "Postal service"
    },
    {
      "item_id": "2",
      "quantity": "1.000",
      "total_amount": 2000,
      "tax_amount": 400,
      "shipping_id": "DX49581904385",
      "shipping_provider": "Postal service"
    }
  ]
}
curl --request PATCH \
     --url https://api-sandbox.hokodo.co/v1/payment/orders/<order_id>/fulfill \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>" \
     --data-binary '{
  "items": [
    {
      "item_id": "1",
      "quantity": "10.000",
      "total_amount": 10000,
      "tax_amount": 1667,
      "shipping_id": "DX49581904385",
      "shipping_provider": "Postal service"
    },
    {
      "item_id": "2",
      "quantity": "1.000",
      "total_amount": 2000,
      "tax_amount": 333,
      "shipping_id": "DX49581904385",
      "shipping_provider": "Postal service"
    }
  ]
}'

Response

200 Ok
Content-Type: application/json
{
  "url": "https://api-sandbox.hokodo.co/v1/payment/orders/order-yQKxbtCg9aTS5JYnsRVA9B",
  "id": "order-yQKxbtCg9aTS5JYnsRVA9B",
  "unique_id": "876987-987uinjojna-I8UH98Jnj",
  "customer": {
    "type": "registered",
    "organisation": "org-ypTaHiLv5kgqSn4TzCr7xb",
    "user": "user-nNqgg5AFymQMumaU7EdrLa",
    "delivery_address": {
      "name": "John Smith",
      "address_line1": "1 Station Street",
      "address_line2": "Flat B",
      "address_line3": "",
      "city": "London",
      "region": "",
      "postcode": "SE11 6NQ",
      "country": "GB",
      "phone": "",
      "email": ""
    }
  },
  "status": "pending",
  "currency": "GBP",
  "pay_method": "",
  "total_amount": 12000,
  "tax_amount": 2000,
  "order_date": "2018-04-25",
  "invoice_date": "2018-04-25",
  "due_date": "2018-06-25",
  "paid_date": null,
  "items": [
    {
      "item_id": "1",
      "type": "product",
      "description": "Super ergonomic chair",
      "metadata": {"color": "black", "name": "Karmus", "variant": "M"},
      "reference": "702.611.50",
      "category": "Furniture > Chairs",
      "supplier_id": "7363",
      "supplier_name": "",
      "quantity": "10.000",
      "unit_price": 1000,
      "tax_rate": "20.00",
      "total_amount": 10000,
      "tax_amount": 2000,
      "fulfilled_quantity": 10,
      "fulfillment_info": [
        {
          "quantity": "10.000",
          "total_amount": 10000,
          "tax_amount": 2000,
          "shipping_id": "DX49581904385",
          "shipping_provider": "Postal service",
          "shipping_date": "2018-04-26"
        }
      ],
      "cancelled_quantity": 0,
      "cancelled_info": null,
      "returned_quantity": 0,
      "returned_info": null
    },
    {
      "item_id": "2",
      "type": "shipping",
      "description": "Delivery fee",
      "metadata": {},
      "reference": "",
      "category": "",
      "supplier_id": "",
      "supplier_name": "",
      "quantity": "1.000",
      "unit_price": 2000,
      "tax_rate": "20.00",
      "total_amount": 2000,
      "tax_amount": 400,
      "fulfilled_quantity": 1,
      "fulfillment_info": [
        {
          "quantity": "1.000",
          "total_amount": 2000,
          "tax_amount": 400,
          "shipping_id": "DX49581904385",
          "shipping_provider": "Postal service",
          "shipping_date": "2018-04-26"
        }
      ],
      "cancelled_quantity": 0,
      "cancelled_info": null,
      "returned_quantity": 0,
      "returned_info": null
    }
  ],
  "metadata": {
    "customer_id": "2055b445-3d95-4d2f-bd80-3e336217905f",
    "checkout_id": "c0185e68-89aa-42d5-93e9-476d01d4c97f"
  },
  "payment_offer": "offer-cqfxJVUwXBrkyZHRQaknJS",
  "deferred_payment": "defpay-7PiKMX2gEpJmasb8Du65zn"
}

Fulfillment refers to the process of shipping the goods to the customer, or providing them with the service they have purchased. It is important that you notify Hokodo when fulfillment occurs since this is the trigger for our payment to you. This endpoint is usually called when the package has been handed over to the logistics carrier. Hint: Make sure that your fulfillment department (or external partner) has access to the API. Often, this requires some planning ahead.

Fulfillment information must include date and all items that have actually been delivered to the customer in the format similar to the list of items in the Order.

You can either ship the full order or only parts of the order. In case you initially only ship parts of the order:

field type flags description
items list required The list of items that got shipped, each with the fields described below
item_id string required Your identifier for this line of the order, e.g. 1, 2, 3...
quantity decimal required Number of items shipped
total_amount int required Total amount including tax of the items that shipped, in minor units (cents)
tax_amount int required Total amount of the taxes of the items that shipped, in minor units (cents)
shipping_id string optional Tracking id of the shipping provider
shipping_provider string optional Name of the shipping provider

Errors

errors description
404 the order_id is probably invalid, the order has not been found
400 a required field is missing or some of the fields have incorrect value

Cancellation

Request

  • partial cancellation of half the items in the Order
PUT /v1/payment/orders/<order_id>/cancel HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "items": [
    {
      "item_id": "2",
      "quantity": "1",
      "total_amount": 2000,
      "tax_amount": 400
    }
  ]
}
curl --request PATCH \
     --url https://api-sandbox.hokodo.co/v1/payment/orders/<order_id>/cancel \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>" \
     --data-binary '{
  "items": [
    {
      "item_id": "2",
      "quantity": "1",
      "total_amount": 2000,
      "tax_amount": 400
    }
  ]
}'

Response

200 Ok
Content-Type: application/json
{
  "url": "https://api-sandbox.hokodo.co/v1/payment/orders/order-yQKxbtCg9aTS5JYnsRVA9B",
  "id": "order-yQKxbtCg9aTS5JYnsRVA9B",
  "unique_id": "876987-987uinjojna-I8UH98Jnj",
  "customer": {
    "type": "registered",
    "organisation": "org-ypTaHiLv5kgqSn4TzCr7xb",
    "user": "user-nNqgg5AFymQMumaU7EdrLa",
    "delivery_address": {
      "name": "John Smith",
      "address_line1": "1 Station Street",
      "address_line2": "Flat B",
      "address_line3": "",
      "city": "London",
      "region": "",
      "postcode": "SE11 6NQ",
      "country": "GB",
      "phone": "",
      "email": ""
    }
  },
  "status": "pending",
  "currency": "GBP",
  "pay_method": "",
  "total_amount": 7000,
  "tax_amount": 1166,
  "order_date": "2018-04-25",
  "invoice_date": "2018-04-25",
  "due_date": "2018-06-25",
  "paid_date": null,
  "items": [
    {
      "item_id": "1",
      "type": "product",
      "description": "Super ergonomic chair",
      "metadata": {"color": "black", "name": "Karmus", "variant": "M"},
      "reference": "702.611.50",
      "category": "Furniture > Chairs",
      "supplier_id": "7363",
      "supplier_name": "",
      "quantity": "5.000",
      "unit_price": 1000,
      "tax_rate": "20.00",
      "total_amount": 5000,
      "tax_amount": 1000,
      "fulfilled_quantity": 0,
      "fulfillment_info": null,
      "cancelled_quantity": 0,
      "cancelled_info": null,
      "returned_quantity": 0,
      "returned_info": null
    },
    {
      "item_id": "2",
      "type": "shipping",
      "description": "Delivery fee",
      "metadata": {},
      "reference": "",
      "category": "",
      "supplier_id": "",
      "supplier_name": "",
      "quantity": "1.000",
      "unit_price": 2000,
      "tax_rate": "20.00",
      "total_amount": 2000,
      "tax_amount": 400,
      "fulfilled_quantity": 0,
      "fulfillment_info": null,
      "cancelled_quantity": 1,
      "cancelled_info": [
        {
          "quantity": "1.000",
          "total_amount": 2000,
          "tax_amount": 400
        }
      ],
      "returned_quantity": 0,
      "returned_info": null
    }
  ],
  "metadata": {
    "customer_id": "2055b445-3d95-4d2f-bd80-3e336217905f",
    "checkout_id": "c0185e68-89aa-42d5-93e9-476d01d4c97f"
  },
  "payment_offer": "offer-cqfxJVUwXBrkyZHRQaknJS",
  "deferred_payment": "defpay-7PiKMX2gEpJmasb8Du65zn"
}

If an order or individual items from an order are being cancelled by the customer before shipping, you need to notify us of the cancellation.

You can either cancel the full order or only parts of the order. In case you only cancel parts of the order:

Returns

Request

  • partial return of half the items in the Order
PUT /v1/payment/orders/<order_id>/return HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "items": [
    {
      "item_id": "2",
      "quantity": "1",
      "total_amount": 2000,
      "tax_amount": 400
    }
  ]
}
curl --request PATCH \
     --url https://api-sandbox.hokodo.co/v1/payment/orders/<order_id>/return \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>" \
     --data-binary '{
  "items": [
    {
      "item_id": "2",
      "quantity": "1",
      "total_amount": 2000,
      "tax_amount": 400
    }
  ]
}'

Response

200 Ok
Content-Type: application/json
{
  "url": "https://api-sandbox.hokodo.co/v1/payment/orders/order-yQKxbtCg9aTS5JYnsRVA9B",
  "id": "order-yQKxbtCg9aTS5JYnsRVA9B",
  "unique_id": "876987-987uinjojna-I8UH98Jnj",
  "customer": {
    "type": "registered",
    "organisation": "org-ypTaHiLv5kgqSn4TzCr7xb",
    "user": "user-nNqgg5AFymQMumaU7EdrLa",
    "delivery_address": {
      "name": "John Smith",
      "address_line1": "1 Station Street",
      "address_line2": "Flat B",
      "address_line3": "",
      "city": "London",
      "region": "",
      "postcode": "SE11 6NQ",
      "country": "GB",
      "phone": "",
      "email": ""
    }
  },
  "status": "pending",
  "currency": "GBP",
  "pay_method": "",
  "total_amount": 7000,
  "tax_amount": 1166,
  "order_date": "2018-04-25",
  "invoice_date": "2018-04-25",
  "due_date": "2018-06-25",
  "paid_date": null,
  "items": [
    {
      "item_id": "1",
      "type": "product",
      "description": "Super ergonomic chair",
      "metadata": {"color": "black", "name": "Karmus", "variant": "M"},
      "reference": "702.611.50",
      "category": "Furniture > Chairs",
      "supplier_id": "7363",
      "supplier_name": "",
      "quantity": "5.000",
      "unit_price": 1000,
      "tax_rate": "20.00",
      "total_amount": 5000,
      "tax_amount": 1000,
      "fulfilled_quantity": 5,
      "fulfillment_info": [
        {
          "quantity": "5.000",
          "total_amount": 5000,
          "tax_amount": 1000,
          "shipping_id": "DX49581904385",
          "shipping_provider": "Postal service",
          "shipping_date": "2018-04-26"
        }
      ],
      "cancelled_quantity": 0,
      "cancelled_info": null,
      "returned_quantity": 0,
      "returned_info": null
    },
    {
      "item_id": "2",
      "type": "shipping",
      "description": "Delivery fee",
      "metadata": {},
      "reference": "",
      "category": "",
      "supplier_id": "",
      "supplier_name": "",
      "quantity": "1.000",
      "unit_price": 2000,
      "tax_rate": "20.00",
      "total_amount": 2000,
      "tax_amount": 400,
      "fulfilled_quantity": 1,
      "fulfillment_info": [
        {
          "quantity": "1.000",
          "total_amount": 2000,
          "tax_amount": 400,
          "shipping_id": "DX49581904385",
          "shipping_provider": "Postal service",
          "shipping_date": "2018-04-26"
        }
      ],
      "cancelled_quantity": 0,
      "cancelled_info": null,
      "returned_quantity": 1,
      "returned_info": [
        {
          "quantity": "1.000",
          "total_amount": 2000,
          "tax_amount": 400
        }
      ]
    }
  ],
  "metadata": {
    "customer_id": "2055b445-3d95-4d2f-bd80-3e336217905f",
    "checkout_id": "c0185e68-89aa-42d5-93e9-476d01d4c97f"
  },
  "payment_offer": "offer-cqfxJVUwXBrkyZHRQaknJS",
  "deferred_payment": "defpay-7PiKMX2gEpJmasb8Du65zn"
}

If a shipped order (or individual items from an order) are being returned by the customer after shipping, you need to notify us of the return.

You can either return the full order or only parts of the order. In case you only return parts of the order:

Refunds / discounts

Request

PUT /v1/payment/orders/<order_id>/discount HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>

{
  "items": [
    {
      "item_id": "99",
      "description": "Discount following our email conversation",
      "quantity": "1.000",
      "unit_price": -120,
      "tax_rate": "20.00",
      "total_amount": -120,
      "tax_amount": -20
    }
  ]
}
curl --request PATCH \
     --url https://api-sandbox.hokodo.co/v1/payment/orders/<order_id>/discount \
     --header "Content-Type: application/json" \
     --header "Authorization: <your_api_key>" \
     --data-binary '{
  "items": [
    {
      "item_id": "99",
      "description": "Discount following our email conversation",
      "quantity": "1.000",
      "unit_price": -120,
      "tax_rate": "20.00",
      "total_amount": -120,
      "tax_amount": -20
    }
  ]
}'

Response

200 Ok
Content-Type: application/json
{
  "url": "https://api-sandbox.hokodo.co/v1/payment/orders/order-yQKxbtCg9aTS5JYnsRVA9B",
  "id": "order-yQKxbtCg9aTS5JYnsRVA9B",
  "unique_id": "876987-987uinjojna-I8UH98Jnj",
  "customer": {
    "type": "registered",
    "organisation": "org-ypTaHiLv5kgqSn4TzCr7xb",
    "user": "user-nNqgg5AFymQMumaU7EdrLa",
    "delivery_address": {
      "name": "John Smith",
      "address_line1": "1 Station Street",
      "address_line2": "Flat B",
      "address_line3": "",
      "city": "London",
      "region": "",
      "postcode": "SE11 6NQ",
      "country": "GB",
      "phone": "",
      "email": ""
    }
  },
  "status": "pending",
  "currency": "GBP",
  "pay_method": "",
  "total_amount": 11880,
  "tax_amount": 1980,
  "order_date": "2018-04-25",
  "invoice_date": "2018-04-25",
  "due_date": "2018-06-25",
  "paid_date": null,
  "items": [
    {
      "item_id": "1",
      "type": "product",
      "description": "Super ergonomic chair",
      "metadata": {"color": "black", "name": "Karmus", "variant": "M"},
      "reference": "702.611.50",
      "category": "Furniture > Chairs",
      "supplier_id": "7363",
      "supplier_name": "",
      "quantity": "10.000",
      "unit_price": 1000,
      "tax_rate": "20.00",
      "total_amount": 10000,
      "tax_amount": 2000,
      "fulfillment_info": [
        {
          "quantity": "10.000",
          "total_amount": 10000,
          "tax_amount": 2000,
          "shipping_id": "DX49581904385",
          "shipping_provider": "Postal service",
          "shipping_date": "2018-04-26"
        }
      ]
    },
    {
      "item_id": "2",
      "type": "shipping",
      "description": "Delivery fee",
      "metadata": {},
      "reference": "",
      "category": "",
      "supplier_id": "",
      "supplier_name": "",
      "quantity": "1.000",
      "unit_price": 2000,
      "tax_rate": "20.00",
      "total_amount": 2000,
      "tax_amount": 400,
      "fulfilled_quantity": 1,
      "fulfillment_info": [
        {
          "quantity": "1.000",
          "total_amount": 2000,
          "tax_amount": 400,
          "shipping_id": "DX49581904385",
          "shipping_provider": "Postal service",
          "shipping_date": "2018-04-26"
        }
      ],
      "cancelled_quantity": 0,
      "cancelled_info": null,
      "returned_quantity": 0,
      "returned_info": null
    },
    {
      "item_id": "99",
      "type": "discount",
      "description": "Discount following our email conversation",
      "metadata": {},
      "reference": "",
      "category": "",
      "supplier_id": "",
      "supplier_name": "",
      "quantity": "1.000",
      "unit_price": -120,
      "tax_rate": "20.00",
      "total_amount": -120,
      "tax_amount": -20,
      "fulfilled_quantity": 0,
      "fulfillment_info": null,
      "cancelled_quantity": 0,
      "cancelled_info": null,
      "returned_quantity": 0,
      "returned_info": null
    }
  ],
  "metadata": {
    "customer_id": "2055b445-3d95-4d2f-bd80-3e336217905f",
    "checkout_id": "c0185e68-89aa-42d5-93e9-476d01d4c97f"
  },
  "payment_offer": "offer-cqfxJVUwXBrkyZHRQaknJS",
  "deferred_payment": "defpay-7PiKMX2gEpJmasb8Du65zn"
}

If a customer files a complaint, but does not return any items, and you want to refund some of the money, you can send us an unspecified refund or discount.

This refund or discount becomes a new line of the Order.

Disputes

If a customer files a complaint on a shipped order, and you can’t settle the dispute in a timely manner, we need to make sure, that we don’t debit the customer before the dispute is resolved. For that reason you need to send us a dispute notification, that then needs to be lifted once the dispute has been resolved.

As a result of an accepted dispute notification Hokodo will refrain from debiting the customer until the dispute has been actively resolved.

Note: If we already paid you, we will hold back the disputed sum from your next merchant payment until the dispute is resolved.

This endpoint is not available yet.

Payouts

A Payout represents a payment made from Hokodo to your bank account. It consists of the amount, date, and currency of the payout, as well as a list of individual Order changes and adjustments which were used to calculate the payout amount.

To facilitate cash reconciliation, each Payout object includes a unique payout reference id which can be found on your bank statement.

Payout endpoints

Payout object

{
  "url": "https://api-sandbox.hokodo.co/v1/payment/payouts/po-yQKxbtCg9aTS5JYnsRVA9B",
  "id": "po-yQKxbtCg9aTS5JYnsRVA9B",
  "payout_reference_id": "HK-XYZ",
  "payout_date": "2022-01-01",
  "amount_from_payout_items": 12000,
  "amount_from_adjustments": 1000,
  "fees": 1000,
  "type": "net_of_fees",
  "amount": 12000,
  "currency": "GBP",
  "min_balance": {
    "fixed": 1000,
    "relative": 500,
    "actual": 1000,
    "withheld_amount": 2000
  },
  "items": [
    {
      "url": "https://api-sandbox.hokodo.co/v1/payment/payout_items/poitm-yQKxbtCg9aTS5JYnsRVA9B",
      "id": "poitm-yQKxbtCg9aTS5JYnsRVA9B",
      "type": "fulfillment",
      "payout": "po-yQKxbtCg9aTS5JYnsRVA9B",
      "deferred_payment": "defpay-yQKxbtCg9aTS5JYnsRVA9B",
      "order": "order-yQKxbtCg9aTS5JYnsRVA9B",
      "status": "paid",
      "creation_date": "2021-12-26",
      "earliest_payout_date": "2022-01-01",
      "actual_payout_date": "2022-01-01",
      "amount": 1100,
      "fees": 100,
      "amount_net_of_fees": 1000,
      "currency": "GBP"
    },
    {
      "url": "https://api-sandbox.hokodo.co/v1/payment/payout_items/poitm-yQKxbtCg9aTS5JYnsRVA9B",
      "id": "poitm-yQKxbtCg9aTS5JYnsRVA9B",
      "type": "fulfillment",
      "payout": "po-yQKxbtCg9aTS5JYnsRVA9B",
      "deferred_payment": "defpay-yQKxbtCg9aTS5JYnsRVA9B",
      "order": "order-yQKxbtCg9aTS5JYnsRVA9B",
      "status": "paid",
      "creation_date": "2021-12-26",
      "earliest_payout_date": "2022-01-01",
      "actual_payout_date": "2022-01-01",
      "amount": 1100,
      "fees": 100,
      "amount_net_of_fees": 1000,
      "currency": "GBP"
    }
  ],
  "adjustments": [
    {
      "id": "poadj-yQKxbtCg9aTS5JYnsRVA9B",
      "type": "credit_review_fee",
      "net_amount": 400,
      "tax_rate": 25,
      "amount": 500,
      "currency": "GBP"
    },
    {
      "id": "poadj-yQKxbtCg9aTS5JYnsRVA9B",
      "type": "minimum_fee",
      "net_amount": 400,
      "tax_rate": 25,
      "amount": 500,
      "currency": "GBP"
    }
  ]
}
field type description
url string API endpoint to access the Payout
id string(uuid) API unique identifier for the Payout
payout_reference_id string Id which appears on your bank statement
payout_date date Date the payout was made (i.e. when Hokodo initiated the transfer of funds to your bank account)
amount_from_payout_items int Total amount of payout_items including any applicable fees, in minor units (cents)
amount_from_adjustments int Total amount of adjustments in minor units (cents)
fees int Total amount of fees in minor units (cents)
type string How are your Payouts structured? net_of_fees or gross_of_fees
amount int Amount paid to your bank account in minor units (cents). See calculating the payout amount
currency string ISO 4217 currency code (e.g. GBP, EUR)
min_balance dictionary Minimum account balance parameters at the time the payout was made
min_balance[fixed] int Your fixed minimum account balance at the time the payout was made
min_balance[relative] int Your relative minimum account balance (as a % of unpaid Orders) at the time the payout was made
min_balance[actual] int The actual minimum balance used when calculating the payout amount. It is the max of fixed or relative
min_balance[withheld_amount] int Total amount of payout items (e.g. fulfilled Order items) which were not included in this payout, in order to maintain your minimum account balance
payout_items list List of payout items included in the payout
adjustments list List of adjustments which were included in the payout_amount
adjustments[*][id] string(uuid) API identifier for the Adjustment
adjustments[*][type] string Type of adjustment (see Adjustment Type section)
adjustments[*][net_amount] int Net amount for this adjustment (excluding tax) in minor units (cents)
adjustments[*][tax_rate] decimal Tax rate on this adjustment, in percent (e.g. "19.50" for 19.5%)
adjustments[*][amount] int Total amount for this adjustment (including tax) in minor units (cents)
adjustments[*][currency] string ISO 4217 currency code (e.g. GBP, EUR)

Calculating the payout amount

The final payout amount takes a number of factors into account:

Minimum account balance

Your Hokodo account contains two minimum account balance parameters:

When calculating the amount for an upcoming payout, Hokodo will compute your current minimum account balance min_balance[actual]. This is the maximum of your fixed or relative minimum account balance. Hokodo may withhold a number of PayoutItems needed to maintain this balance. The total amount of the withheld Payout items is stored in the Payout's min_balance[withheld_amount] field.

Adjustment amount

The Adjustment amount can be positive or negative.

Adjustment type

An adjustment can have one of the following types:

status description
balancing_item this is only used if adjustments are needed between successive payouts. Balancing items should always offset with items in preceding or subsequent months such that they should sum to zero
minimum_fee adjustment required if monthly transaction volumes don't achieve minimum fee
credit_review_fee fee for any credit reviews
balance_carried_to_next_payout amount carried over to next payout
balance_carried_from_last_payout amount carried over from last payout
fee_discount applied when any fees are waived
fx_fee fee incurred if any currency conversions are required as part of the payout
other

List Payouts

Request

GET /v1/payment/payouts HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>
curl --request GET \
     --url https://api-sandbox.hokodo.co/v1/payment/payouts \
     --header "Authorization: <your_api_key>"

Response

200 Ok
Content-Type: application/json
{
  "count": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "url": "https://api-sandbox.hokodo.co/v1/payment/payout/po-yQKxbtCg9aTS5JYnsRVA9B",
      "id": "po-yQKxbtCg9aTS5JYnsRVA9B",
      "payout_reference_id": "HK-XYZ",
      "payout_date": "2022-01-01",
      "amount_from_payout_items": 12000,
      "amount_from_adjustments": 1000,
      "fees": 1000,
      "type": "net_of_fees",
      "amount": 12000,
      "currency": "GBP",
      "min_balance": {
        "fixed": 1000,
        "relative": 500,
        "actual": 1000,
        "withheld_amount": 2000
      },
      "items": [
        ...
      ],
      "adjustments": [
        ...
      ]
    },
    {
      "url": "https://api-sandbox.hokodo.co/v1/payment/payout/po-yQKxbtCg9aTS5JYnsRVA9B",
      "id": "po-yQKxbtCg9aTS5JYnsRVA9B",
      "payout_reference_id": "HK-XYZ",
      "payout_date": "2022-01-01",
      "amount_from_payout_items": 12000,
      "amount_from_adjustments": 1000,
      "fees": 1000,
      "type": "net_of_fees",
      "amount": 12000,
      "currency": "GBP",
      "min_balance": {
        "fixed": 1000,
        "relative": 500,
        "actual": 1000,
        "withheld_amount": 2000
      },
      "items": [
        ...
      ],
      "adjustments": [
        ...
      ]
    }
  ]
}

View Payout

Request

GET /v1/payment/payouts/<payout_id> HTTP/1.1
Authorization: Token <your_api_key>
curl --request GET \
     --url https://api-sandbox.hokodo.co/v1/payment/payouts/<payout_id> \
     --header "Authorization: <your_api_key>"

Responses

  • regular response
200 Ok
Content-Type: application/json
{
  "url": "https://api-sandbox.hokodo.co/v1/payment/payouts/po-yQKxbtCg9aTS5JYnsRVA9B",
  "id": "po-yQKxbtCg9aTS5JYnsRVA9B",
  "payout_reference_id": "HK-XYZ",
  "payout_date": "2022-01-01",
  "amount_from_payout_items": 12000,
  "amount_from_adjustments": 1000,
  "fees": 1000,
  "type": "net_of_fees",
  "amount": 12000,
  "currency": "GBP",
  "min_balance": {
    "fixed": 1000,
    "relative": 500,
    "actual": 1000,
    "withheld_amount": 2000
  },
  "items": [
    {
      "url": "https://api-sandbox.hokodo.co/v1/payment/payout_items/poitm-yQKxbtCg9aTS5JYnsRVA9B",
      "id": "poitm-yQKxbtCg9aTS5JYnsRVA9B",
      "type": "fulfillment",
      "payout": "po-yQKxbtCg9aTS5JYnsRVA9B",
      "deferred_payment": "defpay-yQKxbtCg9aTS5JYnsRVA9B",
      "order": "order-yQKxbtCg9aTS5JYnsRVA9B",
      "status": "paid",
      "creation_date": "2021-12-26",
      "earliest_payout_date": "2022-01-01",
      "actual_payout_date": "2022-01-01",
      "amount": 1100,
      "fees": 100,
      "amount_net_of_fees": 1000,
      "currency": "GBP"
    },
    {
      "url": "https://api-sandbox.hokodo.co/v1/payment/payout_items/poitm-yQKxbtCg9aTS5JYnsRVA9B",
      "id": "poitm-yQKxbtCg9aTS5JYnsRVA9B",
      "type": "fulfillment",
      "payout": "po-yQKxbtCg9aTS5JYnsRVA9B",
      "deferred_payment": "defpay-yQKxbtCg9aTS5JYnsRVA9B",
      "order": "order-yQKxbtCg9aTS5JYnsRVA9B",
      "status": "paid",
      "earliest_payout_date": "2022-01-01",
      "actual_payout_date": "2022-01-01",
      "amount": 1100,
      "fees": 100,
      "amount_net_of_fees": 1000,
      "currency": "GBP"
    }
  ],
  "adjustments": [
    {
      "id": "poadj-yQKxbtCg9aTS5JYnsRVA9B",
      "type": "credit_review_fee",
      "net_amount": 100,
      "tax_rate": 10,
      "amount": 110,
      "currency": "GBP"
    },
    {
      "id": "poadj-yQKxbtCg9aTS5JYnsRVA9B",
      "type": "minimum_fee",
      "net_amount": 200,
      "tax_rate": 10,
      "amount": 220,
      "currency": "GBP"
    }
  ]
}
  • Not Found
404 Not Found
Content-Type: application/json
{
  "detail": "Not found."
}

Query Params

GET /v1/payment/payouts?start_date=2022-01-01&end_date=2022-02-01 HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>
curl --request GET \
     --url "https://api-sandbox.hokodo.co/v1/payment/payouts?start_date=2022-01-01&end_date=2022-02-01" \
     --header "Authorization: <your_api_key>"

Response

200 Ok
Content-Type: application/json
{
  "count": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "url": "https://api-sandbox.hokodo.co/v1/payment/payout/po-yQKxbtCg9aTS5JYnsRVA9B",
      "id": "po-yQKxbtCg9aTS5JYnsRVA9B",
      "payout_reference_id": "HK-XYZ",
      "payout_date": "2022-01-01",
      "amount_from_payout_items": 12000,
      "amount_from_adjustments": 1000,
      "fees": 1000,
      "type": "net_of_fees",
      "amount": 12000,
      "currency": "GBP",
      "min_balance": {
        "fixed": 1000,
        "relative": 500,
        "actual": 1000,
        "withheld_amount": 2000
      },
      "items": [
        ...
      ],
      "adjustments": [
        ...
      ]
    },
    {
      "url": "https://api-sandbox.hokodo.co/v1/payment/payout/po-yQKxbtCg9aTS5JYnsRVA9B",
      "id": "po-yQKxbtCg9aTS5JYnsRVA9B",
      "payout_reference_id": "HK-XYZ",
      "payout_date": "2022-01-01",
      "amount_from_payout_items": 12000,
      "amount_from_adjustments": 1000,
      "fees": 1000,
      "type": "net_of_fees",
      "amount": 12000,
      "currency": "GBP",
      "min_balance": {
        "fixed": 1000,
        "relative": 500,
        "actual": 1000,
        "withheld_amount": 2000
      },
      "items": [
        ...
      ],
      "adjustments": [
        ...
      ]
    }
  ]
}

When you want to search for a specific Payout (e.g. a Payout with a certain payout_reference_id) or a specific set of Payouts (e.g. all Payouts from the last quarter), the query params below can be applied to the Payout's endpoint.

param type description
start_date date Include payouts made to your account on or after this date
end_date date Include payouts made to your account on or before this date
payout_reference_id string Only include the Payout with this payout_reference_id

PayoutItem object

{
  "url": "https://api-sandbox.hokodo.co/v1/payment/payout_items/poitm-yQKxbtCg9aTS5JYnsRVA9B",
  "id": "poitm-yQKxbtCg9aTS5JYnsRVA9B",
  "type": "fulfillment",
  "payout": null,
  "deferred_payment": "defpay-yQKxbtCg9aTS5JYnsRVA9B",
  "order": "order-yQKxbtCg9aTS5JYnsRVA9B",
  "status": "scheduled",
  "creation_date": "2021-12-26",
  "earliest_payout_date": "2022-02-01",
  "actual_payout_date": null,
  "amount": 1100,
  "fees": 100,
  "amount_net_of_fees": 1000,
  "currency": "GBP"
}

A Payout typically contains one or more PayoutItems. A PayoutItem provides a direct link between a post sale Order event (e.g. fulfillment, discount, etc.) and the subsequent Payout.

field type description
url string API endpoint to access the PayoutItem
id string(uuid) API identifier for the PayoutItem
type string Type of Order change (e.g. fulfillment) which triggered the creation of this PayoutItem
payout string(uuid) API identifier of the underlying Payout. This will be null for PayoutItems which are scheduled to be paid but haven't been paid yet.
deferred_payment string(uuid) API identifier of the underlying DeferredPayment. To view all fields for this DeferredPayment, include expand=deferred_payment in your request's query params
order string(uuid) API identifier of the underlying Order. To view all fields for this Order, include expand=order in your request's query params
status string Status of the PayoutItem (scheduled or paid)
creation_date date Date the PayoutItem was created
earliest_payout_date date Earliest possible date this item will be paid
actual_payout_date date Actual date this item was paid. This will be null for items which haven't been paid
amount int Total amount of the PayoutItem (i.e. total amount of the underlying Order change) in minor units (cents) before any fees
fees int Fees which have been applied (or will apply) to this PayoutItem in minor units (cents)
amount_net_of_fees int Net amount for this PayoutItem (i.e. amount - fees) in minor units (cents). Note that depending on your payout settings the actual cash paid to you may be the amount or the amount_net_of_fees. This is stated in the Payout payout_structure field
currency string ISO 4217 currency code (e.g. GBP, EUR)

Order Change Type

type description
fulfillment occurs when you notify us of a fulfillment
cancellation occurs when you notify us of a cancellation
return occurs when you notify us of a return
discount occurs when you notify us of a refund/discount
reversal occurs when we reverse back to you a transaction which we have previously financed
settlement used when payouts are linked to customer settlements (may be positive or negative)
chargeback used when payouts are linked to customer settlements & a customer executes a chargeback
other

List PayoutItems

Request

GET /v1/payment/payout_items HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>
curl --request GET \
     --url https://api-sandbox.hokodo.co/v1/payment/payout_items \
     --header "Authorization: <your_api_key>"

Response

200 Ok
Content-Type: application/json
{
  "count": 2,
  "next": null,
  "previous": null,
  "results": [
     {
          "url": "https://api-sandbox.hokodo.co/v1/payment/payout_items/poitm-yQKxbtCg9aTS5JYnsRVA9B",
          "id": "poitm-yQKxbtCg9aTS5JYnsRVA9B",
          "type": "fulfillment",
          "payout": null,
          "deferred_payment": "defpay-yQKxbtCg9aTS5JYnsRVA9B",
          "order": "order-yQKxbtCg9aTS5JYnsRVA9B",
          "status": "scheduled",
          "creation_date": "2021-12-26",
          "earliest_payout_date": "2022-02-01",
          "actual_payout_date": null,
          "amount": 1100,
          "fees": 100,
          "amount_net_of_fees": 1000,
          "currency": "GBP"
     },
     {
          "url": "https://api-sandbox.hokodo.co/v1/payment/payout_items/poitm-yQKxbtCg9aTS5JYnsRVA9B",
          "id": "poitm-yQKxbtCg9aTS5JYnsRVA9B",
          "type": "fulfillment",
          "payout": null,
          "deferred_payment": "defpay-yQKxbtCg9aTS5JYnsRVA9B",
          "order": "order-yQKxbtCg9aTS5JYnsRVA9B",
          "status": "scheduled",
          "creation_date": "2021-12-26",
          "earliest_payout_date": "2022-02-01",
          "actual_payout_date": null,
          "amount": 1100,
          "fees": 100,
          "amount_net_of_fees": 1000,
          "currency": "GBP"
     }
  ]
}

View PayoutItem

Request

GET /v1/payment/payout_items/<payout_item_id> HTTP/1.1
Authorization: Token <your_api_key>
curl --request GET \
     --url https://api-sandbox.hokodo.co/v1/payment/payout_items/<payout_item_id> \
     --header "Authorization: <your_api_key>"

Responses

  • regular response
200 Ok
Content-Type: application/json
{
  "url": "https://api-sandbox.hokodo.co/v1/payment/payout_items/poitm-yQKxbtCg9aTS5JYnsRVA9B",
  "id": "poitm-yQKxbtCg9aTS5JYnsRVA9B",
  "type": "fulfillment",
  "payout": null,
  "deferred_payment": "defpay-yQKxbtCg9aTS5JYnsRVA9B",
  "order": "order-yQKxbtCg9aTS5JYnsRVA9B",
  "status": "scheduled",
  "creation_date": "2021-12-26",
  "earliest_payout_date": "2022-02-01",
  "actual_payout_date": null,
  "amount": 1100,
  "fees": 100,
  "amount_net_of_fees": 1000,
  "currency": "GBP"
}
  • Not Found
404 Not Found
Content-Type: application/json
{
  "detail": "Not found."
}

Query Params

GET /v1/payment/payout_items?order_unique_id=xxx HTTP/1.1
Content-Type: application/json
Authorization: Token <your_api_key>
curl --request GET \
     --url "https://api-sandbox.hokodo.co/v1/payment/payout_items?order_unique_id=xxx" \
     --header "Authorization: <your_api_key>"

Response

200 Ok
Content-Type: application/json
{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "url": "https://api-sandbox.hokodo.co/v1/payment/payout_items/poitm-yQKxbtCg9aTS5JYnsRVA9B",
      "id": "poitm-yQKxbtCg9aTS5JYnsRVA9B",
      "type": "fulfillment",
      "payout": null,
      "deferred_payment": "defpay-yQKxbtCg9aTS5JYnsRVA9B",
      "order": "order-yQKxbtCg9aTS5JYnsRVA9B",
      "status": "scheduled",
      "creation_date": "2021-12-26",
      "earliest_payout_date": "2022-02-01",
      "actual_payout_date": null,
      "amount": 1100,
      "fees": 100,
      "amount_net_of_fees": 1000,
      "currency": "GBP"
    }
  ]
}

When you want to search for a specific set of PayoutItems (e.g. all PayoutItems attached to a specific Order), the query params below can be applied to the PayoutItems endpoint.

param type description
order_id string(uuid) API identifier for the Order
order_unique_id string(uuid) Unique identifier of the order on your platform
start_date date Include payouts made to your account on or after this date.
end_date date Include payouts made to your account on or before this date.

Webhooks / Notifications / Callbacks

Hokodo uses webhooks to notify your application when an event happens in your account. For example, when one of your customers has their deferred payment application approved.

Webhooks allow you to avoid polling and instead receive notifications when changes related to an Order, Offer or DeferredPayment object occur.

Webhook Payload

Sample content

Deferred Payment Application Complete

{
    "created": "2021-01-01T12:00:00Z",
    "data": {
        "order": {
            "id": "order-QWLGzh3ciDXo3P4QkPtrnH",
            "unique_id": "",
            "po_number": "",
            "customer": {
                "organisation": {
                    "id": "org-mSuTHdaodb5pjDmKsBj5Z4",
                    "unique_id": "1",
                    "registered": "2010-06-30T00:00:00Z",
                    "company": null,
                    "users": [
                        "96608083-4783-44e3-a474-4bad3fa6e82a"
                    ]
                },
                "user": {
                    "id": "user-pHm3kfFQXwzs8ND8HYNTYV",
                    "email": "syTnvfVbZjFv@email.com",
                    "unique_id": "",
                    "name": "name_SUUgVUVuRVaB",
                    "phone": "",
                    "registered": "2010-06-30T00:00:00Z",
                    "type": "registered"
                },
                "invoice_address": {
                    "name": "name_LGDZJAFYLRus",
                    "company_name": "company_name_touyMqWkVyAn",
                    "address_line1": "address_line1_gKmCACesrqbd",
                    "address_line2": "address_line2_shliflLciPie",
                    "address_line3": "",
                    "city": "city_edqpaQOKqUXI",
                    "region": "",
                    "postcode": "E1 1D0",
                    "country": "GB",
                    "phone": "",
                    "email": ""
                },
                "delivery_address": {
                    "name": "name_tLoyeGeGMXlc",
                    "company_name": "company_name_DgcvLcFejRbl",
                    "address_line1": "address_line1_XKWMakHAilHa",
                    "address_line2": "address_line2_MzczHXdoRqQR",
                    "address_line3": "",
                    "city": "city_jSjusADEJkuE",
                    "region": "",
                    "postcode": "E1 1D1",
                    "country": "GB",
                    "phone": "",
                    "email": ""
                },
                "billing_address": {
                    "name": "name_LGDZJAFYLRus",
                    "company_name": "company_name_touyMqWkVyAn",
                    "address_line1": "address_line1_gKmCACesrqbd",
                    "address_line2": "address_line2_shliflLciPie",
                    "address_line3": "",
                    "city": "city_edqpaQOKqUXI",
                    "region": "",
                    "postcode": "E1 1D0",
                    "country": "GB",
                    "phone": "",
                    "email": ""
                }
            },
            "created": "2020-11-10T08:31:39.915557Z",
            "currency": "EUR",
            "order_date": "2020-11-10",
            "invoice_date": null,
            "due_date": null,
            "paid_date": null,
            "total_amount": 1000,
            "tax_amount": 200,
            "metadata": null,
            "items": [
                {
                    "item_id": "0",
                    "type": "",
                    "description": "",
                    "metadata": null,
                    "reference": "",
                    "category": "",
                    "supplier_id": "",
                    "supplier_name": "",
                    "quantity": "10.000",
                    "unit_price": 100,
                    "total_amount": 1000,
                    "tax_amount": 200,
                    "tax_rate": "25.00"
                }
            ],
            "payment_offer": {
                "url": "/v1/payment/offers/offr-SFRufpfb4wMh8Jkr84W8Gf",
                "id": "offr-SFRufpfb4wMh8Jkr84W8Gf",
                "order": "order-QWLGzh3ciDXo3P4QkPtrnH",
                "offered_payment_plans": [
                    {
                        "id": "ppln-E8tWZ3MahpeDp798k9fzVH",
                        "name": "",
                        "template": "pptemp-MNhaDZyoRatSZTyizGTgtb",
                        "currency": "EUR",
                        "protected_amount": 1000,
                        "unprotected_amount": 0,
                        "scheduled_payments": [
                            {
                                "date": "2021-01-31",
                                "amount": 1000,
                                "discounted_amount": 1000,
                                "customer_fee": {
                                    "percentage": "0.00",
                                    "amount": 0
                                },
                                "allowed_payment_methods": [
                                    {
                                        "type": "direct_debit"
                                    },
                                    {
                                        "type": "invoice"
                                    },
                                    {
                                        "type": "card"
                                    }
                                ],
                                "payment_method": {"type": "invoice"},
                                "due_date_config": {
                                    "due_after_nb_days": null,
                                    "due_end_of_nb_months": 0,
                                    "amount_percentage": "100.0",
                                    "is_upfront_payment": false
                                }
                            }
                        ],
                        "payment_terms_relative_to": "order_creation",
                        "merchant_fee": {
                            "currency": "EUR",
                            "amount": 0
                        },
                        "customer_fee": {
                            "currency": "EUR",
                            "percentage": "0.00",
                            "amount": 0
                        },
                        "customer_percentage_discount": "0.00",
                        "customer_discount": {
                            "currency": "EUR",
                            "amount": 0
                        },
                        "valid_until": "2020-11-17T08:31:40.059Z",
                        "payment_url": "https://api-sandbox.hokodo.co/?order=order-QWLGzh3ciDXo3P4QkPtrnH&plan=ppln-E8tWZ3MahpeDp798k9fzVH&key=cjuHbDjF3txeTaHgtDUilQ9UdYqHllC2iFFarKdJemU&template=pptemp-MNhaDZyoRatSZTyizGTgtb",
                        "status": "offered",
                        "rejection_reason": null,
                        "has_upfront_payment": false
                    }
                ],
                "urls": {
                    "success": "",
                    "failure": "",
                    "cancel": "",
                    "notification": "",
                    "merchant_terms": ""
                },
                "locale": "",
                "metadata": null
            },
            "deferred_payment": {
                "url": "/v1/payment/deferred_payments/defpay-8BvTZ9T6K5gj6LeSqvfqzm",
                "id": "defpay-8BvTZ9T6K5gj6LeSqvfqzm",
                "number": "P-PMNE-DN6C",
                "payment_plan": {
                    "id": "ppln-E8tWZ3MahpeDp798k9fzVH",
                    "name": "",
                    "template": "pptemp-MNhaDZyoRatSZTyizGTgtb",
                    "currency": "EUR",
                    "protected_amount": 1000,
                    "unprotected_amount": 0,
                    "scheduled_payments": [
                        {
                            "date": "2021-01-31",
                            "amount": 1000,
                            "discounted_amount": 1000,
                            "customer_fee": {
                                "percentage": "0.00",
                                "amount": 0
                            },
                            "allowed_payment_methods": [
                                {
                                    "type": "direct_debit"
                                },
                                {
                                    "type": "invoice"
                                },
                                {
                                    "type": "card"
                                }
                            ],
                            "payment_method": {"type": "invoice"},
                            "due_date_config": {
                                "due_after_nb_days": null,
                                "due_end_of_nb_months": 0,
                                "amount_percentage": "100.0",
                                "is_upfront_payment": false
                            }
                        }
                    ],
                    "payment_terms_relative_to": "order_creation",
                    "merchant_fee": {
                        "currency": "EUR",
                        "amount": 0
                    },
                    "customer_fee": {
                        "currency": "EUR",
                        "percentage": "0.00",
                        "amount": 0
                    },
                    "customer_percentage_discount": "0.00",
                    "customer_discount": {
                        "currency": "EUR",
                        "amount": 0
                    },
                    "valid_until": "2020-11-17T08:31:40.059Z",
                    "payment_url": "https://api-sandbox.hokodo.co/?order=order-QWLGzh3ciDXo3P4QkPtrnH&plan=ppln-E8tWZ3MahpeDp798k9fzVH&key=cjuHbDjF3txeTaHgtDUilQ9UdYqHllC2iFFarKdJemU&template=pptemp-MNhaDZyoRatSZTyizGTgtb",
                    "status": "offered",
                    "rejection_reason": null,
                    "has_upfront_payment": false
                },
                "order": "order-QWLGzh3ciDXo3P4QkPtrnH",
                "outstanding_balance": {
                    "amount": null,
                    "currency": "EUR"
                },
                "next_payment_date": null,
                "payments": null,
                "status": "part_captured",
                "authorisation": 800,
                "currency": "EUR",
                "protected_captures": 200,
                "unprotected_captures": 0,
                "refunds": 0,
                "voided_authorisation": 0,
                "expired_authorisation": 0,
                "events": [
                   {
                       "created": "2023-01-05T09:55:38.091854Z",
                       "type": "capture",
                       "amount": 200,
                       "currency": "EUR",
                       "metadata": {
                           "note": "Capturing 1000 worth of bonbons"
                       },
                       "changes": {
                           "authorisation": -200,
                           "protected_captures": 200,
                           "unprotected_captures": 0,
                           "refunds": 0,
                           "voided_authorisation": 0,
                           "expired_authorisation": 0,
                           "customer_fee": {
                               "authorisation": 0,
                               "captures": 0,
                               "refunds": 0,
                               "voided_authorisation": 0,
                               "expired_authorisation": 0
                           }
                       }
                   }
                ]

            },
            "status": "draft",
            "pay_method": "unknown"
        }
    }
}

The webhook payload will include a full Order object.

field type description
created string Time the notification was sent (e.g. 2021-01-01T12:00:00Z)
data dictionary Dictionary containing the Order object
data[order] dictionary The Order object

The Order object will have the following fields expanded(if available):

Events

You will receive a notification when any of the following events occur:

Please note that the payload for all of the events will contain the latest version of the Order object with the expanded fields (if available) as described above.

Getting Started

1. Select Integration Option

Depending on your use-case Hokodo can configure your account so that all notifications will be sent to the same webhook. Alternatively, when you create an Offer you can include a notification url in the request, and we'll send all notifications related to that specific Offer to this url. Changes to related objects such as the underlying Order or a DeferredPayment will also be sent to this url.

If you prefer the first option please let us know at support@hokodo.co and we will be happy to configure your account.

No additional setup is required if you prefer the second option. Note, if you do select this option, you won't receive any notifications about Order changes until you create an Offer.

2. Secure Your Webhook (optional)

For enhanced security, Hokodo can include an authentication string in the Authorization header of all notifications. If you're interested in this option please let us know at support@hokodo.co

Notes

  1. Your endpoint must be using HTTPS.

  2. In production, our API will verify the validity of the HTTPS certificate. In sandbox, you can use a self-signed certificate.

  3. Our API will send a POST request, with the content of the Order in the POST request body as JSON.

  4. Our API expects a 2xx status code from your endpoint for a successful response.

  5. Our API will retry up to 3 times if it can't connect successfully to your endpoint. It will wait 0, 2, and 4 seconds respectively before the 1st, 2nd and 3rd retry.

Error codes

The Hokodo API uses the following error codes:

Error Code Meaning
400 Bad Request -- Your request is invalid.
401 Unauthorized -- Your API key is wrong.
403 Forbidden -- The requested function is not available for your account.
404 Not Found -- The specified object could not be found.
405 Method Not Allowed -- You tried to access an object with an invalid method.
409 Conflict -- The requested action conflicts with the current state of the object.
500 Internal Server Error -- We had a problem with our server. Try again later.
503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.

Testing in sandbox

Bypass underwriting engine

To facilitate testing in Sandbox, you can bypass the underwriting engine to create Offers with specific statuses and so test their behaviour in your checkout. This bypasses our Underwriting engine, which determines the Offer status.

To create an Offer with a specific status, you need to create a User with an email corresponding to a specific pattern, and use that User to create your order. For example, if you would like to test an Offer that is rejected during underwriting, set the User email to myuser+paymentplan_declined@mail.com.

Searched pattern Payment Plan Status Example
paymentplan_offered offered sandrine_bouchon+paymentplan_offered@yourdomain.com
paymentplan_declined declined gerard_colins+paymentplan_declined@yourdomain.com
paymentplan_partly_offered one offered, the others declined gerard_colins+paymentplan_partly_offered@yourdomain.com

Bypass fraud engine

To facilitate testing in Sandbox, you can create DeferredPayments with specific statuses and so test their behaviour in your checkout. This bypasses our fraud engine, which determines the DeferredPayment status.

To create a DeferredPayment with a specific status, you need to create a User with an email corresponding to a specific pattern, and use that User to create your order. For example, if you would like to test a DP with an accepted status, set the User email to myuser_dp_fraud_accepted@yourdomain.com.

Searched pattern Deferred Payment Status Example
dp_fraud_accepted accepted sandrine_bouchon+dp_fraud_accepted@yourdomain.com
dp_fraud_rejected rejected gerard_colins+dp_fraud_rejected@yourdomain.com
dp_fraud_customer_action_required customer_action_required dp_fraud_customer_action_required_fatou_ndial@yourdomain.com
dp_fraud_pending_review pending_review kevin_fischer+dp_fraud_pending_review@yourdomain.com

Combine underwriting and fraud pattern

You can combine both patterns to test different combinations of Offer and DeferredPayment status. For example:

Searched pattern Payment Plan Status Deferred Payment Status
paymentplan_offered_dp_fraud_accepted offered accepted
paymentplan_offered_dp_fraud_rejected offered rejected
paymentplan_declined_dp_fraud_accepted declined never get to fraud detection
paymentplan_partly_offered_dp_fraud_pending_review one offered, the others declined pending_review

If the offer is declined, you cannot create a Deferred Payment.

Important note

If two different fraud or payment plan status are found (dp_fraud_accepted_dp_fraud_rejected@mail.com), the first match is taken.

When testing from sandbox, we are sending emails, to properly test: