Webhook notifications [Payouts API]
Monitor the status of payouts and top-ups using webhooks, and validate webhook signatures.
Payouts API will notify you of the following events using webhooks:
Details on the overall structure of webhooks, as well as their payload schemas, are below.
Webhook retry policy
We consider a webhook as having been successfully delivered when we receive a success status code (2xx) from the webhook URI you specified in your Console settings for Payouts API.
If we receive any other status code (for example, your API is temporarily unavailable), we will start retrying.
Our retry policy is jittered exponential backoff: we will immediately perform some fast retries and then start waiting increasingly longer; we will keep retrying for up to 72 hours.
Webhook structure
All webhooks from the Payouts API are structured in the same way.
In the header, you will see the following fields:
Field | Type | Description |
---|---|---|
X-TL-Webhook-Timestamp | timestamp | Time that the webhook was sent to you. This will be in the following format: 2020-05-18T10:17:47Z |
TL-Signature | string | JSON web signature with a detached payload of the form {HEADER}..{SIGNATURE} |
In the body, you will see the following fields:
Field | Type | Description |
---|---|---|
event_type | string | Describing which event is detailed. |
event_schema_version | unsigned integer | The version of the event body schema (for example, 1). |
event_id | uuid | Unique ID of the event. |
event_body | object | Containing the object relating to the event. The body schema is specified in the following sections for each event type. |
Payout Authorised
The event body contains the following fields:
Field | Type | Description |
---|---|---|
transaction_id | uuid | The unique ID of the payout. |
authorised_at | Timestamp | The date and time that the payout was authorised at. |
X-TL-Webhook-Timestamp: 2020-05-18T10:17:52Z
{
"event_type": "payout_authorised",
"event_id": "33c9fc5b-69d7-4de0-83a9-8177f9af79d2",
"event_schema_version": 1,
"event_body": {
"transaction_id": "cc328607-e02e-49e2-81c9-5bd044c8f7d7",
"authorised_at": "2019-10-01T17:00:00.0000000Z",
}
}
Payout Submitted
The event body contains the following fields:
Field | Type | Description |
---|---|---|
transaction_id | uuid | The unique ID of the payout. |
submitted_at | Timestamp | The date and time that the payout was submitted to the scheme. |
X-TL-Webhook-Timestamp: 2020-05-18T10:17:52Z
{
"event_type": "payout_submitted",
"event_id": "33c9fc5b-69d7-4de0-83a9-8177f9af79d2",
"event_schema_version": 1,
"event_body": {
"transaction_id": "cc328607-e02e-49e2-81c9-5bd044c8f7d7",
"submitted_at": "2019-10-01T17:00:00.0000000Z",
}
}
Payout Settled
The event body contains the following fields:
Field | Type | Description |
---|---|---|
transaction_id | uuid | The unique ID of the payout. |
settled_at | Timestamp | The date and time that the payout was settled into the beneficiary account. |
X-TL-Webhook-Timestamp: 2020-05-18T10:17:52Z
{
"event_type": "payout_settled",
"event_id": "33c9fc5b-69d7-4de0-83a9-8177f9af79d2",
"event_schema_version": 1,
"event_body": {
"transaction_id": "cc328607-e02e-49e2-81c9-5bd044c8f7d7",
"settled_at": "2019-10-01T17:00:00.0000000Z",
}
}
Payout Rejected
The event body contains the following fields:
Field | Type | Description |
---|---|---|
transaction_id | uuid | The unique ID of the payout. |
rejected_at | Timestamp | The date and time that the payout was rejected. |
rejection_code | String | The reason the payout was rejected as a machine-parsable enum. |
rejection_details | String | The reason the payout was rejected as a human-friendly description. |
X-TL-Webhook-Timestamp: 2020-05-18T10:17:52Z
{
"event_type": "payout_rejected",
"event_id": "33c9fc5b-69d7-4de0-83a9-8177f9af79d2",
"event_schema_version": 1,
"event_body": {
"transaction_id": "cc328607-e02e-49e2-81c9-5bd044c8f7d7",
"rejected_at": "2019-10-01T18:00:00.0000000Z",
"rejection_code": "insufficient_funds",
"rejection_details": "There were not enough funds on the account to authorise the payout.",
}
}
Payout Failed
The event body contains the following fields:
Field | Type | Description |
---|---|---|
transaction_id | uuid | The unique ID of the payout. |
failed_at | Timestamp | The date and time that the payout status moved to failed. |
failure_code | String | The reason the payout as failed a machine-parsable enum. |
failure_details | String | The reason the payout failed as a human-friendly description. |
X-TL-Webhook-Timestamp: 2020-05-18T10:17:52Z
{
"event_type": "payout_failed",
"event_id": "33c9fc5b-69d7-4de0-83a9-8177f9af79d2",
"event_schema_version": 1,
"event_body": {
"transaction_id": "cc328607-e02e-49e2-81c9-5bd044c8f7d7",
"failed_at": "2019-10-01T18:00:00.0000000Z",
"failure_code": "server_error",
"failure_details": "We encountered a technical issue while processing your payment, please try again later.",
}
}
Top-up received
In the event body you will see the following fields:
Field | Type | Description |
---|---|---|
transaction_id | uuid | unique ID of the transaction. |
settled_at | Timestamp | The date and time the top-up was settled into the account. |
amount_in_minor | integer | The amount received in the smallest denomination of the currency of the account. |
currency | ISO 4217 Currency Code String | The currency the top-up was settled in. |
remitter_iban | string | The IBAN of the account that sent the funds to the account. |
remitter_name | string | The name of the account holder that sent the funds to the account. |
reference | string | The reference that will appear in your transaction history associated with this top-up. |
X-TL-Webhook-Timestamp: 2020-05-18T10:17:52Z
{
"event_type": "topup_received",
"event_id": "33c9fc5b-69d7-4de0-83a9-8177f9af79d2",
"event_schema_version": 1,
"event_body": {
"transaction_id": "cc328607-e02e-49e2-81c9-5bd044c8f7d7",
"settled_at": "2019-10-01T17:00:00.0000000Z",
"amount_in_minor": 10000,
"currency": "GBP",
"remitter_iban": "GB33BUKB20201555555555",
"remitter_name": "Payment Corp"
"reference": "Payment Corp Topup"
}
}
Validate the received webhook signature
We recommend developers to use our signing libraries to verify the Tl-Signature
of the received webhooks.
Java com.truelayer.truelayer-signing
Verifier.verifyWithJwks(jwks)
.method("POST")
.path(path)
.headers(allWebhookHeaders)
.body(body)
.verify(webhookSignature);
Updated 5 months ago