Webhook notifications

You can follow deposit and withdrawal events for PayDirect through webhook notifications.

A webhook is successfully delivered when we receive a success status code (2xx) from the webhook URI that you specified in your console settings for PayDirect API.

If we receive any other status code (for instance, if 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 24 hours waiting approximately 15 minutes between delivery attempts.

Webhook Structure

All webhooks from the PayDirect API are structured as follows:

Header

FieldTypeDescription
X-TL-Webhook-TimestamptimestampTime that the webhook was sent to you. This will be in the following format: 2020-05-18T10:17:47Z.

Body

FieldTypeDescription
event_typestringDescribing which event is detailed.
event_schema_versionunsigned integerThe version of the event body schema (for example, 1).
event_iduuidUnique ID of the event.
event_bodyobjectContaining the object relating to the event. The body schema is specified in the following sections for each event type.

Validating the webhook signature

The value of the X-TL-Signature header contains a JSON Web Signature (JWS) with a detached payload. It takes the form {HEADER}..{SIGNATURE}.

The JWS header contains the following values:

FieldTypeDescription
algstringThe algorithm used to sign the webhook. We currently use the RS256 algorithm.
jkustringThe URI of the JSON Web Key Set (JWKS), a hosted page where a list of public keys owned by TrueLayer can be found.
kidstringThe ID of the key used to sign the webhook, used to retrieve the correct key from the JWKS.
iatintThe time that the JWS was issued, represented in Unix time (number of seconds since 1970-01-01T00:00:00Z).

The steps for verifying the signature are as follows:

  1. Verify the jku field in the token header matches the expected value as listed below. If not, the signature should be rejected as invalid.
    • Sandbox: https://webhooks.truelayer-sandbox.com/.well-known/jwks
    • Production: https://webhooks.truelayer.com/.well-known/jwks
  2. Use the jku value to retrieve the JWKS. This may be cached for some time, but if verification fails, the JWKS must be retrieved again to ensure that all keys are up-to-date. TrueLayer may rotate or revoke keys at any time.
  3. Retrieve the relevant public key by using the kid to look up the relevant value from the JWKS.
  4. Use a JWT library to verify the JWS headers combined with the payload (the webhook request body) matches the signature provided in the token. The algorithm used to verify the signature must be that declared in the alg header of the JWS.

Deposits

You can find the relevant fields in the event_body for the following event_types:

Event type Field Parameter type Description
  • deposit_initiated
  • deposit_cancelled
  • deposit_auth_failed
  • deposit_expired
  • deposit_executing
  • deposit_rejected
  • deposit_executed
client_id string A unique string identifying a client.
deposit_id uuid Unique ID of the deposit.
user_id uuid Unique ID of the user.

The following example shows a deposit_initiated event:

X-TL-Webhook-Timestamp: 2020-05-18T10:17:52Z

{
  "event_type": "deposit_initiated",
  "event_id": "714040e3-288e-468d-9575-e5116ff0a9fc",
  "event_schema_version": 1,
  "event_body": {
    "client_id": "client-8806da",
    "deposit_id": "bd780cca-46a6-4f28-a0e4-d36e4e8c57c2",
    "user_id": "8c2f148a-c026-4ce4-8fe4-6afac4f71b6e"
  }
}

For the deposit_settled event_type, the event_body contains:

FieldTypeDescription
client_idstringA unique string identifying a client.
transaction_iduuidUnique ID of the transaction.
deposit_iduuidUnique ID of the deposit.
user_iduuidUnique ID of the user.
account_iduuidUnique ID of the user's account.
settled_attimestampThe date and time the deposit was settled into the account.
amount_in_minorintegerThe amount received in the smallest denomination of the currency of the account.
currencyISO 4217 Currency Code StringThe currency the topup was settled in.
remitter_ibanstringThe IBAN of the account that sent the funds to the account.
remitter_namestringThe name of the account holder that sent the funds to the account.

The following example shows a deposit_settled event:

X-TL-Webhook-Timestamp: 2020-05-18T10:17:52Z

{
  "event_type": "deposit_settled",
  "event_id":  "33c9fc5b-69d7-4de0-83a9-8177f9af79d2",
  "event_schema_version": 1,
  "event_body": {
    "client_id": "client-8806da",
    "transaction_id": "cc328607-e02e-49e2-81c9-5bd044c8f7d7",
    "deposit_id": "88e76e9e-811a-4f02-9624-f808c5925bfb",
    "user_id": "bec96bf3-788b-4266-92dc-77351b680ac5",
    "account_id": "5156e5af-7bf2-49a4-96b3-7fde5ec8ddfe",
    "settled_at": "2019-10-01T17:00:00.0000000Z",
    "amount_in_minor": 10000,
    "currency": "GBP",
    "remitter_iban": "GB33BUKB20201555555555",
    "remitter_name": "Bob Brown"
  }
}

For the external_deposit_received event_type, the event_body contains:

FieldTypeDescription
client_idstringA unique string identifying a client.
transaction_iduuidUnique ID of the transaction.
received_attimestampThe date and time the external deposit was received.
amount_in_minorintegerThe amount received in the smallest denomination of the currency of the account.
currencyISO 4217 Currency Code StringThe currency the topup was settled in.
remitter_ibanstringThe IBAN of the account that sent the funds to the account.
remitter_namestringThe name of the account holder that sent the funds to the account.
referencestringThe reference identifying the payment.

The following example shows an external_deposit_received event:

X-TL-Webhook-Timestamp: 2020-05-18T10:17:52Z

{
  "event_type": "external_deposit_received",
  "event_id":  "33c9fc5b-69d7-4de0-83a9-8177f9af79d2",
  "event_schema_version": 1,
  "event_body": {
    "client_id": "client-8806da",
    "transaction_id": "cc328607-e02e-49e2-81c9-5bd044c8f7d7",
    "received_at": "2019-10-01T17:00:00.0000000Z",
    "amount_in_minor": 10000,
    "currency": "GBP",
    "remitter_iban": "GB33BUKB20201555555555",
    "remitter_name": "Bob Brown",
    "reference": "7820IPXNJ1X6QFKRHR"
  }
}

Withdrawals

The withdrawal_authorised event body contains the following fields:

FieldTypeDescription
client_idstringA unique string identifying a client.
transaction_iduuidThe unique ID of the withdrawal.
authorised_atTimestampThe date and time that the withdrawal was authorised at.
X-TL-Webhook-Timestamp: 2020-05-18T10:17:52Z

{
  "event_type": "withdrawal_authorised",
  "event_id":  "33c9fc5b-69d7-4de0-83a9-8177f9af79d2",
  "event_schema_version": 1,
  "event_body": {
    "client_id": "client-8806da",
    "transaction_id": "cc328607-e02e-49e2-81c9-5bd044c8f7d7",
    "authorised_at": "2019-10-01T17:00:00.0000000Z"
  }
}

The withdrawal_submitted event body contains the following fields:

FieldTypeDescription
client_idstringA unique string identifying a client.
transaction_iduuidThe unique ID of the payout.
submitted_atTimestampThe date and time that the payout was submitted to the scheme.
X-TL-Webhook-Timestamp: 2020-05-18T10:17:52Z

{
  "event_type": "withdrawal_submitted",
  "event_id":  "33c9fc5b-69d7-4de0-83a9-8177f9af79d2",
  "event_schema_version": 1,
  "event_body": {
    "client_id": "client-8806da",
    "transaction_id": "cc328607-e02e-49e2-81c9-5bd044c8f7d7",
    "submitted_at": "2019-10-01T17:00:00.0000000Z"
  }
}

The withdrawal_settled event body contains the following fields:

FieldTypeDescription
client_idstringA unique string identifying a client.
transaction_iduuidThe unique ID of the payout.
settled_atTimestampThe date and time that the payout was settled into the beneficiary account.
X-TL-Webhook-Timestamp: 2020-05-18T10:17:52Z

{
  "event_type": "withdrawal_settled",
  "event_id":  "33c9fc5b-69d7-4de0-83a9-8177f9af79d2",
  "event_schema_version": 1,
  "event_body": {
    "client_id": "client-8806da",
    "transaction_id": "cc328607-e02e-49e2-81c9-5bd044c8f7d7",
    "settled_at": "2019-10-01T17:00:00.0000000Z"
  }
}

The withdrawal_rejected event body contains the following fields:

FieldTypeDescription
client_idstringA unique string identifying a client.
transaction_iduuidThe unique ID of the payout.
rejected_atTimestampThe date and time that the payout was rejected.
rejection_codeStringThe reason the payout was rejected in the form of a machine-parsable enum.
rejection_detailsStringThe reason the payout was rejected in the form of a human-friendly description.
X-TL-Webhook-Timestamp: 2020-05-18T10:17:52Z

{
  "event_type": "withdrawal_rejected",
  "event_id":  "33c9fc5b-69d7-4de0-83a9-8177f9af79d2",
  "event_schema_version": 1,
  "event_body": {
    "client_id": "client-8806da",
    "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."
  }
}

The withdrawal_failed event body contains the following fields:

FieldTypeDescription
client_idstringA unique string identifying a client.
transaction_iduuidThe unique ID of the payout.
failed_atTimestampThe date and time that the payout status moved to failed.
failure_codeStringThe reason the payout failed in the form of a machine-parsable enum.
failure_detailsStringThe reason the payout failed in the form of a human-friendly description.
X-TL-Webhook-Timestamp: 2020-05-18T10:17:52Z

{
  "event_type": "withdrawal_failed",
  "event_id":  "33c9fc5b-69d7-4de0-83a9-8177f9af79d2",
  "event_schema_version": 1,
  "event_body": {
    "client_id": "client-8806da",
    "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."
  }
}

Did this page help you?