Skip to main content

Step 3: Post-sale

After the sale has taken place, there is now an agreement between the buyer and Hokodo that the buyer will pay for the order at some future date(s) as defined by the accepted Payment Plan in the Payment Offer. In the Hokodo backend, this agreement is represented by a Deferred Payment.

Your system needs to inform Hokodo about:

  • Capture of all or part of the order (e.g. goods have been shipped)
  • Refund of all or part of the order (e.g. shipped goods have been returned)
  • Documents the customer may ask us for, including invoices, credit notes and shipping documents

This is typically done in your back-office system by calling the relevant endpoints of Hokodo's API.

Read through each of these sections and ensure you have ways to apply each of the post-sale adjustments, and that you are ready to supply Hokodo with any Order Documents that may be relevant.

Once your system is set up to handle these post-sale tasks, your integration will be complete!

Capture

API Reference: Capture

Once a Deferred Payment is created, we reserve the total value of the order against the customer's credit limit as Authorisation.

We will charge your customer the captured amount. Capturing reduces the Authorisation for a Deferred Payment, and increases the Captured amount by the same value.

Capture once you have shipped the goods to the customer, or completed a service. It is important that you notify Hokodo when this occurs since this triggers Pay Outs to you.

If you only capture part of the Authorisation, some Authorisation will remain. You can:

  • Do nothing, and leave the remaining Authorisation to expire automatically, if that has been configured
  • Capture the remaining Authorisation at a later date
  • Void the remaining Authorisation immediately, or at a later date
Part Capturing with no Expiration

If you do not have Expiration activated, Buyers may also be charged for part of the order value that has not been Captured. Void the remaining Authorisation to avoid this. Unlike some PSPs, we do not always automatically void the remaining Authorisation upon a partial capture.

Capturing above the order value

If the order increases in size beyond the value that was given when the Deferred Payment was created, you can capture beyond the Deferred Payment's initial Authorisation. This can occur if you deliver a slightly larger quantity of goods than the original order, for example.

The extra value you capture will be 'unprotected'. This means the additional value is not protected against non-payment, although our collections team will still attempt to recover the value from the buyer.

See In Depth Knowledge for details.

Integration test

Integration test 1.4 checks that our API is notified about captures.

Full working example

There's an example of a capture request at the end of the Core Flow in the Postman collection.

The other Checkout Flows also have various post-sale scenarios such as partial order cancellation or applying a refund after shipping.

Request

The capture endpoint is:

/v1/payment/deferred_payments/<deferred_payment_id>/capture

Replace <deferred_payment_id> with the Deferred Payment ID that you stored in Step 2 when your customer checked out. It will be something like defpay-HiTrbSti37vE2nq9aJHgiP.

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

{
"amount": 100000,
"metadata": {"reference": "Bob's burger patties"}
}

Response

The status code for a successful capture request is 201.

The response will contain the impact the capture action had on the:

  • authorisation_amount
  • captured_amount
  • refunded_amount
  • void_amount

as well as the email of the merchant user that made the change.

201 Created
Content-Type: application/json

{
"created": "2020-10-15T19:53:42.345Z",
"type": "capture",
"amount": 100000,
"metadata": {"reference": "Bobs burger patties"},
"changes": {
"authorisation": -100000,
"protected_captures": 100000,
"unprotected_captures": 0,
"refunds": 0,
"voided_authorisation": 0,
"expired_authorisation": 0
}
}

}

See the API Reference for descriptions of each field.

Refund

API Reference: Refund.

Refunds decrease the captured amount and so the amount that we will charge the buyer. If we have already charged the buyer, we will remit cash to them or reduce a future repayment accordingly. As the captured amount decreases, the refunded amount increases.

Refunds reduce the captured amount

It's important to only try to use the Refund endpoint to reduce the amount we should charge the buyer for goods that have been shipped and Captured. See the table below "Do you have partial order shipment?" for recommendations on the endpoint to use in different scenarios.

Integration test

Integration test 4.2 checks that your back-office records refunds correctly in our API.

Request

The refund endpoint is:

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

{
"amount": 30000,
"metadata": {"reference": "Bobs burger patties"}
}

Response

The status code for a successful return request is 201.

The response body is similar to the response for captures, and includes the impact the action had.

201 Created
Content-Type: application/json

{
"created": "2020-10-15T19:53:42.345Z",
"type": "refund",
"amount": 30000,
"metadata": {"reference": "Bob's burger patties"},
"changes": {
"authorisation": 0,
"protected_captures": -30000,
"unprotected_captures": 0,
"refunds": 30000,
"voided_authorisation": 0,
"expired_authorisation": 0
}
}

Void

API Reference: Void

Voids reduce the authorisation_amount. You can use the void endpoint when an order has been cancelled by the buyer or items are out of stock. In these cases, you do not expect to capture that value in future. As the authorisation amount decreases, the void amount increases.

Your Customer Success Manager will activate Expiration if you request it. This means the remaining Authorisation automatically voids after a number of weeks (see "Expiration" below). If you do not activate Expiration, then you will probably want to void remaining Authorisation to avoid the buyer being charged amounts that have not been Captured (see table below).

Our recommendation for the use of the Void endpoint is indicated in the table below.

Do you have partial order shipment?Example scenarioHow to implement
No: only full order shipmentsOur order management system only supports shipment in full. We then apply credit notes sometimes.Just use the Capture Remaining endpoint, and then apply Refunds as appropriate
Partial order shipments then always cancel the remainderWe can record partial shipments, but the rest of the order is then always assumed to be cancelled for the time being. If we eventually ship it, we create another order.Apply a Capture for the appropriate amount, but then always Void Remaining afterwards.
Partial order shipments then sometimes cancel the remainderIf the whole order doesn't ship, we'll sometimes reduce the size of the order for some of the items that haven't shipped, but leave part of the order open to perhaps ship later.Use the Void endpoint to free up Authorisation for goods that are no longer part of the order.
Partial order shipments and then leaving the remainder available to be captured laterIf an item is not in stock, we don't cancel that part of the order, we just don't ship it. Sometimes, later on, items come in stock and then ship, as part of the same order.Use the Capture endpoint when shipments are made. If the order is not shipped in full, but no further items are shipped, then in 28 days the Authorisation will expire (if configured). After that, you can still Capture on an Unprotected basis, or create a new order for the now-available items.
Integration test

Integration test 4.1 checks that your back-office records voids correctly in our API.

Request

The void endpoint is similar to the refund endpoint:

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

{
"amount": 5000,
"metadata": {"reference": "Bob's burger patties"}
}

Response

The status code for a successful void request is 201.

The response body is similar to the response for captures and refunds, and also includes the impact the action had.

201 Created
Content-Type: application/json

{
"created": "2020-10-15T19:53:42.345Z",
"type": "capture",
"amount": 5000,
"metadata": {"reference": "Bob's burger patties"},
"changes": {
"authorisation": -5000,
"protected_captures": 0,
"unprotected_captures": 0,
"refunds": 0,
"voided_authorisation": 5000,
"expired_authorisation": 0
}
}

Expiry

The remaining Authorisation automatically voids 28 days after the creation of the Deferred Payments. This process avoids the need to inform Hokodo of cancelled goods, freeing credit limit for future orders automatically.

Therefore, integrating the Void endpoint is optional.

You can see what value of the Deferred Payment has expired in the expired_authorisation field of the Deferred Payment response, and the creation of an expiration event.

Your Customer Success Manager can change the time period or disable expiration upon request.

Following expiry, the status of the Deferred Payment is defined as follows. There will be a webhook event on account of the status change.

Final StatusWhen
cancelledThere are no post-sale events yet, or there are only voids.
reversedAll captures have been Refunded at the point of expiry.
capturedThere are some un-returned captures.

Invoices and other Order Documents

API Reference: Order Documents

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

Please note that invoice uploads are operationally mandatory for going live with Hokodo.

Integration test

Integration test 1.6 checks that invoices are automatically uploaded for each order.

Request

To upload an Order Document, make a request with Content-Type: multipart/form-data.

Content-Type: multipart/form-data

This is one of the rare API endpoints that does not take JSON input, multipart/form-data is used instead.

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: <some_length>

...

The file contents are included as the file field. There are also some optional fields allowing you to supply information about the document.

fieldtypeflagsdescription
filefilerequiredContent of the document
doc_typestringoptionalType of document, see below
descriptionstringoptionalDescription of the document
amountintoptionalValue of the document in minor units (e.g. a credit note worth £100, will have amount=10000)
metadatadictoptionalSet 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.

Response

The response body is a JSON object containing the URI of the uploaded file.

201 Created
Content-Type: application/json

{
"id": "odoc-afapG98cKaCL5VRjVfQQ2S",
"order": "order-YrG5y79iuxTTEpkzPbaqcX",
"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/..."
}`

Getting an existing Order Document

You can fetch an Order Document you previously uploaded by making a GET request using its id and the order ID:

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

(For example, GET /v1/payment/orders/order-YrG5y79iuxTTEpkzPbaqcX/documents/odoc-afapG98cKaCL5VRjVfQQ2S)

The response body is the same as the response body for the POST request, and the success status code is 200.

Order Document types

The doc_type may be:

  • invoice
  • credit_note
  • purchase_order
  • shipping (shipping documents)
  • other

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.

Next up

Once you've created the post-sale flows you need, the integration is complete.

The final stage before going live is to make sure everything's working, by running through our Testing Checklist.