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:
- Order: An order represents an instance of buying or selling something on your platform. An order consists of a basket of order items, plus details about who the company making the purchase is. Orders can be paid for at the time of the order or benefit from credit terms. Fundamentally, Hokodo's solution gives you an easier way to offer credit terms to your customers when they transact on your platform.
- Payment Offer: When a customer reaches the check-out, you will need to check if that particular order is eligible for Deferred Payment. To do this you request a Payment Offer. The Payment Offer is a list of different payment terms which are available for that order (if any), for example, "Pay in 30 days" or "Pay in instalments". The payment offer defines the specific date(s) on which repayment will be due along with other information such as the cost of those particular payment terms. You will typically want to display each of the available Payment Offers as different payment options in your check-out, which customers can then click on to select.
- Deferred Payment: Once a customer clicks on a particular Payment option (such as Pay in 30 days), we will create a Deferred Payment object. This represents the financing that Hokodo will provide to enable that order to be completed on credit terms. The Deferred Payment is analogous to a loan, and it moves through various states from the application process (when the customer first clicks on it, through to being confirmed and ultimate being settled).
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:
- the data is real,
- the payment offers provided are real and binding for us,
- payments happen and money changes hands (or at least bank accounts).
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.
- Buyer countries:
/v1/countries/debtor
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:
- £50.00 would be represented as
5000
, - £12.34 would be represented as
1234
.
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:
- presenting your user with text box(es), where they can enter their company's name, and/or address, and/or registration number,
- using that information in our company search API, to obtain a list of companies which are potential matches to the text you supplied.
- asking the user to pick among the choices our company search API has returned.
Companies endpoints
POST /v1/companies/search
GET /v1/companies/<company_id>
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 |
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 |
Company search
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
andreg_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:
- presenting your user with text box(es), where they can enter their owner / proprietor's name and address
- presenting your user with text boxes where they can enter their company's name and address
- 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
POST /v1/soletraders
GET /v1/soletraders
GET /v1/soletraders/<soletrader_id>
PATCH /v1/soletraders/<soletrader_id>
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:
read-only
user can only see resources attached to the organisation (useful for an accountant for example).member
has the rights of a read-only user and can also get deferred payment.admin
has the rights of a member user and can also add members, remove members, or change role of members. of the organisation.
Organisation endpoints
POST /v1/organisations
GET /v1/organisations
GET /v1/organisations/<organisation_id>
PATCH /v1/organisations/<organisation_id>
DELETE /v1/organisations/<organisation_id>
Organisation object
{
"id": "org-9RxFsXTgnWqwjK4apxBAn8",
"unique_id": "c105b862-f1ba-4197-9d97-57db63196b00",
"registered": "2017-06-01T14:37:12Z",
"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 |
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",
"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"\,
\"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",
"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",
"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",
"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",
"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",
"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
POST /v1/organisations/<organisation_id>/users
GET /v1/organisations/<organisation_id>/users
GET /v1/organisations/<organisation_id>/users/<user_id>
PATCH /v1/organisations/<organisation_id>/users/<user_id>
DELETE /v1/organisations/<organisation_id>/users/<user_id>
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 |
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
POST /v1/users
GET /v1/users
GET /v1/users/<user_id>
PATCH /v1/users/<user_id>
DELETE /v1/users/<user_id>
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 |
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
POST /v1/users/<user_id>/organisations
GET /v1/users/<user_id>/organisations
GET /v1/users/<user_id>/organisations/<organisation_id>
PATCH /v1/users/<user_id>/organisations/<organisation_id>
DELETE /v1/users/<user_id>/organisations/<organisation_id>
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.
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.
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:
Eligible: the response will contain several blocks, such as:
- The customer's credit limit. This is the total credit Hokodo will accept for the customer (including utilised credit).
- The amount of credit currently utilised by the customer. In other words it is the sum of the credit Hokodo has already taken on for this customer via your platform. You can use the first and second responses to communicate a message such as "you are using £XXX out of your £YYY credit limit on our platform".
- The customer's remaining credit. This represents the maximum credit which can still be written for this customer right now, given the other credits already in place.
Declined: The amount of credit currently utilised by the customer will be displayed.
Credit limits endpoint
POST /v1/payment/credit_limits/company/<company_id>
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 |
credit_limit[amount_in_use] | int | Credit limit currently in use |
credit_limit[amount] | int | Total credit limit |
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 | description | requirement |
---|---|---|
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.
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.
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:
Rejected: no limit available
Accepted: the response will contain several blocks, such as:
- the available amount at this point in time for the given company: this is the maximum credit we are able to extend at this point in time, considering the credit already in use by this user, their maximum credit limit, our underwriting rules, etc.
- the amount of the company’s credit limit currently in use with Hokodo for this company in relation to the platform (this might be useful to show messages like "you are using £XXX out of your £YYYY credit limit at our marketplace"),
- history of past credit limits requested by your platform (as a reference, to help your customer support and operations department know the history of credit limit increases/decreases).
CreditLimit endpoints
GET /v1/payment/credit_limits/company/<company_id>
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] | date | read-only | From when the historical credit limit was valid |
credit_limit_history[*][valid_to] | date | 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:
- the status of the credit approval, eligible or declined,
- the amount of the credit limit if approved, as well as the amount currently in use and the amount still available,
- the history of previous credit limits for this customer, if available.
field | type | flags | description |
---|---|---|---|
company | string(uuid) | required | API unique identifier of the customer company queried |
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
POST /v1/payment/orders
GET /v1/payment/orders
GET /v1/payment/orders/<order_id>
PATCH /v1/payment/orders/<order_id>
DELETE /v1/payment/orders/<order_id>
POST /v1/payment/orders/<order_id>/documents
GET /v1/payment/orders/<order_id>/documents/<document_id>
There are also post-sale order endpoints described in a dedicated section:
PUT /v1/payment/orders/<order_id>/fulfill
PUT /v1/payment/orders/<order_id>/cancel
PUT /v1/payment/orders/<order_id>/return
PUT /v1/payment/orders/<order_id>/discount
PUT /v1/payment/orders/<order_id>/mark_disputed
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" / "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:
draft
, meaning the customer has not yet made the purchase, more information belowunpaid
, meaning the purchase has been completed, but not yet paid for - or at least not paid in full (typically because the customer has been given credit terms and has not yet settled)paid
, meaning the order has been settled in fulldisputed
, meaning the customer has not yet settled in full because they have raised a dispute about whether/how much they owe, which has not yet been resolved
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:
unknown
, when payment method is not determinedbank
, for a bank transfer sent by the customerdirectdebit
, for a bank transfer initiated by the merchant/payment providercard
, for credit/debit cardcash
, for cash
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:
Create User with the email address of the user (which may be an unverified email address for guest customers)
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.
If no organisation was linked to the user, or they wish to link a different one, search and identify the company via company search.
Create the Organisation linked to that Company.
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) |
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:
- A way to identify the customer (whether they're registered and logged in, or a guest)
- The order amount and currency
- The order date of the invoice
- The list of items constituting this order, including shipping and any other charges as separate line items
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 organisation, payment_offer
GET /v1/payment/orders/<order_id>?expand=organisation,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=organisation,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": "2017-06-01T14:37:12Z",
"company": "co-bqRyKAGaFrEEN8JMjWJiqk",
"users": ["user-nNqgg5AFymQMumaU7EdrLa"]
}
"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": {
"url": "https://api-sandbox.hokodo.co/v1/payment/offers/offer-EzH6BixNSHvaByEpXcFW5h",
"id": "offer-bqRyHAGaFrDEN8JNjXJirp",
"order": "order-dTHo9Q2idffT7CMPCVjztA",
"status": "eligible",
"offered_payment_plans": [
{
"id": "ppln-bqRyHAGaFrDEN8JNjXJirp",
"name": "net30",
"currency": "GBP",
"protected_amount": 100000,
"unprotected_amount": 0,
"scheduled_payments": [
{
"date": "2020-10-16",
"amount": 100000,
"allowed_payment_methods": [
{"type": "card"},
{"type": "direct_debit"},
{"type": "invoice"}
]
}
],
"merchant_fee": {
"currency": "GBP",
"amount": 1000
},
"customer_fee": {
"currency": "GBP",
"amount": 0
},
"valid_until": "2020-09-16T12:44:49.059Z",
"payment_url": "https://payment.app.hokodo.co/plans/ppln-bqRyHAGaFrDEN8JNjXJirp"
"status": "active"
},
{
"id": "ppln-gJdDHAGaFrDLDvJNXJird",
"name": "4x",
"currency": "GBP",
"protected_amount": 100400,
"unprotected_amount": 0,
"scheduled_payments": [
{
"date": "2020-09-16",
"amount": 25100,
"allowed_payment_methods": [
{"type": "card"}
]
},
{
"date": "2020-10-16",
"amount": 25100,
"allowed_payment_methods": [
{"type": "card"}
]
},
{
"date": "2020-11-16",
"amount": 25100,
"allowed_payment_methods": [
{"type": "card"}
]
},
{
"date": "2020-12-16",
"amount": 25100,
"allowed_payment_methods": [
{"type": "card"}
]
}
],
"merchant_fee": {
"currency": "GBP",
"amount": 2000
},
"customer_fee": {
"currency": "GBP",
"amount": 400
},
"valid_until": "2020-09-16T12:44:49.059Z",
"payment_url": "https://payment.app.hokodo.co/plans/ppln-gJdDHAGaFrDLDvJNXJird"
"status": "active"
},
],
"rejection_reason": null,
"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:
invoice
credit_note
purchase_order
shipping
(shipping documents)other
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
POST /v1/payment/offers
GET /v1/payment/offers/<offer_id>
GET /v1/payment/offers
DELETE /v1/payment/offers/<offer_id>
PUT /v1/payment/payment_plans/<plan_id>/send_offer_email
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",
"currency": "GBP",
"scheduled_payments": [
{
"date": "2020-10-16",
"amount": 100000,
"allowed_payment_methods": [
{"type": "card"},
{"type": "direct_debit"},
{"type": "invoice"}
]
}
],
"merchant_fee": {
"currency": "GBP",
"amount": 1000
},
"customer_fee": {
"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
},
{
"id": "ppln-gJdDHAGaFrDLDvJNXJird",
"name": "4x",
"currency": "GBP",
"scheduled_payments": [
{
"date": "2020-09-16",
"amount": 25100,
"allowed_payment_methods": [
{"type": "card"}
]
},
{
"date": "2020-10-16",
"amount": 25100,
"allowed_payment_methods": [
{"type": "card"}
]
},
{
"date": "2020-11-16",
"amount": 25100,
"allowed_payment_methods": [
{"type": "card"}
]
},
{
"date": "2020-12-16",
"amount": 25100,
"allowed_payment_methods": [
{"type": "card"}
]
}
],
"merchant_fee": {
"currency": "GBP",
"amount": 2000
},
"customer_fee": {
"currency": "GBP",
"amount": 400
},
"valid_until": "2020-09-16T12:44:49.841Z",
"payment_url": "https://payment.app.hokodo.co/plans/ppln-gJdDHAGaFrDLDvJNXJird"
"status": "offered",
"rejection_reason": null
},
],
"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[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 and currency of the fees for the customer for this payment plan (included in the scheduled payments) |
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 | bool | 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,
"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,
"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
}
}
],
"customer_fee": {
"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
}
],
"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,
"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",
"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
- the API identifier of the
Order
, - URLs to redirect the customer once the payment is successful, rejected or cancelled by the customer.
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,
"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",
"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,
"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",
"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,
"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",
"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
GET /v1/payment/deferred_payments/<deferredpayment_id>
Deferred Payment Object
{
"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",
"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") |
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.
Rejection reason
Provides information on the reason for rejection.
{
"rejection_reason":
{
"code": "insufficient_funds",
"detail": "Insufficient funds"
}
"status": "rejected"
}
Possible reasons for rejection:
- The offer was declined
- The payment authorisation with the given card payment method was declined, for various reasons. For example (non-exhaustive):
- insufficient_funds
- payment_declined
- card_error
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.
- capture: Let Hokodo know that some value of goods have been shipped or provided. This triggers Hokodo to charge captured amounts to Buyers according to their chosen PaymentPlan and pay you according to the agreed payout schedule.
- refund: Some value of shipped goods has been returned to you or you wish to apply a discount on the value of goods shipped.
- void: If part, or all, of the remaining authorisation should be released. Voids happen automatically in the form of expiry after a period determined in your contract, but if you wish to free up authorisation immediately (because you know goods will not be shipped, and you wish to free up Buyers' credit limit for further BNPL orders) you can use this endpoint. Voiding authorisation you don't plan on using is thus optional but heavily recommended.
These will not all be necessary for every order. The base flow would be:
- Create the
Order
. - Request the
PaymentOffer
. - The customer accepts one of the payment plans and confirms the order.
- You ask us to capture an amount from the customer equal to the value of goods shipped.
- Hokodo generates a payout to you according to schedule.
- Hokodo records that customer shall repay that amount later, based upon the customer's payment plan.
Post sale endpoints
POST /v1/payment/deferred_payments/<deferred_payment_id>/capture
POST /v1/payment/deferred_payments/<deferred_payment_id>/capture_remaining
POST /v1/payment/deferred_payments/<deferred_payment_id>/refund
POST /v1/payment/deferred_payments/<deferred_payment_id>/void
POST /v1/payment/deferred_payments/<deferred_payment_id>/void_remaining
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
}
}
field | type | flags | description |
---|---|---|---|
created | date | 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 eve, in minor units (cents)nt |
changes[expired_authorisation] | int | read-only | Change in the Deferred Payment 's expired_authorisation 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:
- The sum of all
changes
is equal to zero. - The sum of all positive
changes
is equal toamount
(and thus positive).
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.
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
}
}
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
.
As long as the deferred payment authorisation
is positive, unprotected_captures
is not used as destination. However,
if your contract allows it you can capture more than the authorisation
. The deferred payment authorisation
would
thus become negative and this negative amount has a positive unprotected_captures
as counterpart.
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.
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:
amount
should be positiveamount
shouldn't be greater than the deferred paymentauthorisation
, unless allowed within certain limits by your contract (see discussion above aboutunprotected_captures
)
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
}
}
- authorisation == 0
200 Ok No content
Capture all the remaining authorisation
. This behaves differently based on the remaining authorisation
:
- If the remaining
authorisation
> 0 then the endpoint will capture all the remainingauthorisation
. - If the remaining
authorisation
== 0 then the endpoint will do nothing.
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
}
}
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:
amount
should be positiveamount
must not be greater than theDeferredPayment.protected_captures + DeferredPayment.unprotected_captures
.
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
}
}
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:
amount
should be positiveamount
should be less than the deferred paymentauthorisation
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
}
}
- authorisation == 0
200 Ok No content
Void all the remaining authorisation
. This behaves differently based on the remaining authorisation
:
- If the remaining
authorisation
> 0 then the endpoint will void all the remainingauthorisation
. - If the remaining
authorisation
== 0 then the endpoint will do nothing.
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.
- mark fulfilled: to let Hokodo know the order (or part of the order) has been shipped, and trigger payment from Hokodo to you,
- cancel: if the order (or part of the order) has been cancelled,
- return: if the customer has returned the order (or part of the order) after shipping,
- discount: if you grant a refund or discount to the customer.
These will not all be necessary for every order. The base flow would be:
- Create the Order.
- Request the PaymentOffer.
- The customer accepts one of the payment plans and confirms the order.
- You mark the order as fulfilled as you ship it.
- Hokodo sends you the money immediately.
- The customer pays Hokodo later.
Post-sale Order endpoints
PUT /v1/payment/orders/<order_id>/fulfill
PUT /v1/payment/orders/<order_id>/cancel
PUT /v1/payment/orders/<order_id>/return
PUT /v1/payment/orders/<order_id>/discount
PUT /v1/payment/orders/<order_id>/mark_disputed
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:
- You have to send us further delivery confirmations until the entire order has been shipped (or cancelled).
- You always send the line items you have shipped with the original line number/id. For example, if you ship item 1 and item 4 of a 4 item basket, you send us lines 1+4 (and don’t change those numbers).
- You fill the fields "total_amount" and "tax_amount" with the sum of the items you shipped, not the original order total sum.
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:
- You always send the line items you cancel with the original line number. For example, if you cancel item "2" of a 4 item order, you send us line "2" (and don’t change this number).
- You fill the fields "total_amount" with the sum of the items you cancelled, not the original order total sum.
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:
- You always send the line items you return with the original line number. For example, if you return item "3" of a 4 item order, you send us line "3" (and don’t change this number).
- You fill the fields "total_amount" with the sum of the items you returned, not the original order total sum.
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
GET /v1/payment/payouts
GET /v1/payment/payouts/<payout_id>
GET /v1/payment/payout_items
GET /v1/payment/payout_items/<payout_item_id>
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:
- Total value of the payout items
- Total value of the any adjustments
- Your minimum account balance
- Whether your account is setup to receive payouts net or gross of fees
Minimum account balance
Your Hokodo account contains two minimum account balance parameters:
- Fixed: This is your fixed minimum account balance (e.g. €1,000). This amount will be determined before onboarding.
- Relative: This is your relative minimum account balance as a % of current unpaid Orders on your account. This % will be determined before onboarding.
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.
- A positive adjustment amount will increase the payout amount
- A negative adjustment amount will decrease the payout amount
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
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,
"allowed_payment_methods": [
{
"type": "direct_debit"
},
{
"type": "invoice"
},
{
"type": "card"
}
],
"payment_method": {"type": "invoice"}
}
],
"merchant_fee": {
"currency": "EUR",
"amount": 0
},
"customer_fee": {
"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
}
],
"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,
"allowed_payment_methods": [
{
"type": "direct_debit"
},
{
"type": "invoice"
},
{
"type": "card"
}
],
"payment_method": {"type": "invoice"}
}
],
"merchant_fee": {
"currency": "EUR",
"amount": 0
},
"customer_fee": {
"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
},
"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
}
}
]
},
"status": "draft",
"pay_method": "unknown"
}
}
}
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
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):
- customer: the
Customer
object - items: the list of order items
- payment_offer: the
Offer
object with the full list of linkedPaymentPlan
objects inside an expanded fieldoffered_payment_plans
- deferred_payment: the
DeferredPayment
object which has been created after customer approval, with the expanded fieldpayment_plan
that contains the correspondingPaymentPlan
object
Events
You will receive a notification when any of the following events occur:
Order
creationOrder
updateOffer
creationOffer
updateDeferredPayment
creationDeferredPayment
update
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
Your endpoint must be using HTTPS.
In production, our API will verify the validity of the HTTPS certificate. In sandbox, you can use a self-signed certificate.
Our API will send a POST request, with the content of the
Order
in the POST request body as JSON.Our API expects a
2xx
status code from your endpoint for a successful response.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 |
- This will automatically make your offer
offered
ordeclined
for underwriting reasons. Therejection_reason
will be filled with a generic reason. partly_offered
is not a realOffer
status, but allows you to have bothoffered
anddeclined
payment plans within the same offer: If we have configured your account such that multiplePaymentPlans
are generated following anOffer
request, onePaymentPlan
will beoffered
and the other one(s)declined
.
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:
- The domain should be a real one,
- We suggest to use subaddressing or alias for your test. (for example
sandrine_bouchon+dp_fraud_accepted@yourdomain.com
)