Webhooks
Table of Contents
- Overview
- Configuration
- IP Allowlist
- Request Validation
- Response
- Retry Policy
- Request De-duplication
- Payload
Overview
Webhooks provide real-time notifications for events occurring in your Fipto workspace, such as new transactions and transaction status updates. To monitor all these activities, configure a webhook, and Fipto will ensure that relevant events are broadcasted to your chosen endpoint.
Configuration
To add a new webhook, prepare an endpoint, and contact our customer support. The chosen endpoint must use HTTPS protocol to ensure a secure connection between Fipto and your service.
IP Allowlist
All incoming requests will be served, depending on environment, from these IPs:
- Demo
- 3.77.91.94
- 3.73.145.20
- 3.120.72.252
- Production
- 3.77.126.242
- 52.29.119.142
- 3.120.13.37
Request Validation
The authenticity of Fipto as the issuer of webhook notifications can be verified by checking the signature of the message attached to the header. The signature is generated as follows:
Fipto-Signature: Base64(RSASSA-PKCS1-v1_5(_WEBHOOK_PRIVATE_KEY_, SHA-512, SHA-512(eventBody)))
To validate the signature, depending on environment, please use the following public key:
- Demo
-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsfIjnlRELLgHMUb5EdIT MZt+N569AlGGyz0DNX8VKdBIyLwgVHSt1FU7F0hZTHeMGYnqwtbxEDX92JnTZji9 gDuD7es3jz7PpmKBn4xHJmvOu/UdEZ9YAHuR66x8DR5Pl2eHXItAozKraVzIRhbK WIowA60PGf5BvpLMRjN7sIX5ErGyffBP7IoqVWnIsAruEORYO3iiPbqwdaEAWK52 ayt1E9qdAvWZnQs3uCdkR30Xf4dduiTzx1+7oTwFURCnzayJui5PQ+sK6dOs4qjK /XrEL2QdChjmt2dG4N/HXSGvOfKFLxDPC5QF9T7plutF210AgdPZCGgPbRFqfV7L clNZ246fPaQ96faEhGz5287P5G3i98pcIM3r799m3Gkhmmc+2OjfCojdB7nQe77B ZtSyfDvLlOnwa+Q/wfuMqTlJ375MTBcM9PlQXIgV7SBOkVYyPtOzHDX6E9NgK1YJ fpCG9No8eOTvRnt2ZM04Kb2sxfiBNEHM0NHjC+A1pCXPjtsv18oJaGyaplDWIuqu zSWj83ni6o9NzHmTYtazNj9MOmUqGxDFrGc2Aa9UBM1DDYCtV+LITMK3+XXkZdbt cNxeFARvdi/P1uOo5xhuEOTykhU0RPSNXAxyGfKdkeyd9g1hfwco5eJKAKEMwPxt nxCa4IgAVAJxCCKyejAdqK0CAwEAAQ== -----END PUBLIC KEY-----
- Production
-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAx324lPvb4LK7E2QbqF+B tlQ4dzi0BoiWrZVeCBlBreNbFZqmT+1fmoEOTvB64aRyUCSZUNK2BzTnDVXFAWMA e3jQ9N+zrknPeUVR6/jWzvC/t9Z4RjiUzMA4fOOq1kHZRjnYUA3EEsA/MiUwLVFj M9ja9IyDHtVRpjuSs2uLdwLpTbNOtIdj1U6eU16GGr8PeoBm5kejy/OqUN0Le0Iy 3hAwDe7tdp7LxWS75bIk+5BDX4fP98yzqVvIk4ZJsjdYvk4eIfWBKtjZVSIHDmTk b/+bDHxoMazOMX8YlGgvXKLacyBwyXlSHtlze28fTR54H6mfTUpDLuDLHotQJ72X 6nCqLUOkum9V5tTqoTjiT8bjk1cX9imFXOmHx3s73KqZ4DqXaoodIDwuThWhQfZV 43SE4R1e5LzpbNjV9olxOnJkLMwGBfTlEc4jYzw7wMBeT84dwwju+TQHyuuMFlni mnQCl0YX3E9XbYoSi6m0h8wSyMKinOaZwdqp/yqD+6ErlGZlXhgb6IG10C0CzEzM j86flHmZ3PZvRPFmjBzBXjsxrKGMXV7G5WTTjf4BitBlZ4l6t8ySiILDIZFMIaMU 6VIQxHk4ePJpZ/QMC6qy9FaOPbPpl9qObMb+7wHiDBRP7zoOriQdRviwbYLnI32L BcESaj2xk2B4yZy9xQtwifECAwEAAQ== -----END PUBLIC KEY-----
Example function to verify signature in TypeScript:
import { createVerify } from "crypto";
/**
* Verifies the signature of a request sent by Fipto as a webhook.
*
* @param pubKey Fipto's public key.
* @param reqBody Request body as string.
* @param signature Content of "Fipto-Signature" header.
*/
export function verifySignature(
pubKey: string,
reqBody: string,
signature: string
): boolean {
return createVerify("RSA-SHA512")
.update(reqBody)
.verify(pubKey, signature, "base64");
}
Response
The Fipto server expects your endpoint to instantly respond with a 2XX
HTTP status code to confirm webhook notification was received. In case of unexpected status code or lack of response within 5 seconds
, a retry will be issued according to our retry policy.
Retry Policy
If Fipto server doesn't receive a 2XX
HTTP response to the POST
request within 5 seconds
, it will retry the request with exponential back off. A maximum of 10
retries can be issued, with the final triggered 15 minutes
after the last failure. The exact retry schedule (in seconds) is: 2, 4, 8, 16, 32, 64, 128, 256, 512, 900. Consequently, the final request will be made about 32 minutes
after the first failure.
Request De-duplication
A consequence of the retry policy is the possibility of delivering the same event twice, therefore, it is important to ignore events with event_id
that was already processed.
Payload
The webhook notification is sent as a POST
request with a JSON object payload that provides information about a specific event. Each payload contains a generic structure that outlines the event type that triggered the notification, unique event_id
for the request de-duplication, and the associated data object. The data object includes a unique identifier, the type of data, and a nested attributes object that holds detailed information specific to the data type.
Field | Type | Description |
---|---|---|
event | string | The type of event that triggered the webhook. Possible values: PAYIN_CREATED , PAYIN_COMPLETED , PAYIN_REJECTED , PAYOUT_COMPLETED , PAYOUT_REJECTED , PAYMENT_LINK_COMPLETED . |
event_id | string | The UUID of the event, designated for the request de-duplication. |
data | object | The main data object containing details about the event. |
data.id | string | The UUID of the data object. |
data.type | string | The type of data. Possible values: payin or payout . |
data.attributes | object | Contains the attributes related to the data object. |
Payin
The following table describes the fields within data.attributes
for when data.type
is payin
:
Field | Type | Description |
---|---|---|
amount | string | The amount of the payin, in decimal format. |
asset_code | string | The code of the asset being used (e.g., BTC for Bitcoin). |
created_at | string | The timestamp when the payin was created, in ISO 8601 format. |
source | object | The source information of the payin. |
source.address | string | The external wallet address that initiated the payment. |
source.iban | string | The IBAN of the bank account that initiated the payment. |
source.bic | string | The BIC of the bank account that initiated the payment. |
source.name | string | The name of the bank account that initiated the payment. |
source.physical_address | string | The physical address of the bank account that initiated the payment. |
source.country | string | The country of the bank account that initiated the payment. |
destination | object | The destination information for the payin. |
destination.wallet_id | string | The UUID of the wallet receiving the payin. |
destination.wallet_name | string | The name of the wallet receiving the payin. |
destination.wallet_details_name | string | The name of the wallet details. |
destination.wallet_details_address | string | The address of the wallet details. |
destination.wallet_details_tag | string | The tag associated with the wallet details. |
destination.wallet_details_iban | string | The IBAN associated with the wallet details. |
reference | string | Payment reference used in fiat transactions to convey information about the payment being made. |
status | string | The status of the payin. Possible values: in transit or completed . |
transaction_id | string | The UUID for the transaction. |
valuations | array | An array of valuation objects, each containing an asset and its corresponding value. |
valuations[].asset | string | The code of the asset for the valuation (e.g., USD, EUR). |
valuations[].value | string | The value of the asset in the specified currency. |
blockchain_data | object | Contains blockchain-specific data. |
blockchain_data.transaction_hash | string | The hash of the blockchain transaction. |
blockchain_data.block_explorer_link | string | A link to view the transaction on a blockchain explorer. |
Example PAYIN_CREATED
event in fiat currency:
{
"event": "PAYIN_CREATED",
"event_id": "0e8540ee-fcf9-4322-bc86-85eba7108a22",
"data": {
"id": "b99e9a17-1332-4e07-8c5a-1113b64c31c7",
"type": "payin",
"attributes": {
"amount": "100.55",
"created_at": "2023-07-10T14:30:00Z",
"asset_code": "EUR",
"source": {
"iban": "GB90MOCK00000003779553",
"bic": "MOCKGB21",
"name": "John Kowalski",
"physical_address": "25 rue François 1er, Paris, 75009",
"country": "FR"
},
"destination": {
"wallet_id": "cf3377f9-95d8-4371-9908-e700cd5025b1",
"wallet_name": "Savings",
"wallet_details_name": "Primary",
"wallet_details_iban": "FR93MOCK00000003340671"
},
"reference": "Payment for order 12345",
"status": "completed",
"transaction_id": "562108da-222d-4895-acf4-2135462d7821"
}
}
}
Example PAYIN_COMPLETED
event in digital currency:
{
"event": "PAYIN_COMPLETED",
"event_id": "205ad3f4-985e-413d-a9cc-1ce9b200a74e",
"data": {
"id": "b99e9a17-1332-4e07-8c5a-1113b64c31c7",
"type": "payin",
"attributes": {
"amount": "1.50",
"created_at": "2023-07-10T14:30:00Z",
"asset_code": "BTC",
"source": {
"address": "tz1MzL4XgAo84vpJJGzNRz7KuAYuS6biwKsz"
},
"destination": {
"wallet_id": "78526183-7755-4dfb-9f0b-b470ac9bb36a",
"wallet_name": "Bitcoin Wallet",
"wallet_details_name": "Primary",
"wallet_details_address": "tz1a4GT7THHaGDiTxgXoatDWcZfJ5j29z5RC",
"wallet_details_tag": ""
},
"status": "completed",
"transaction_id": "ed0ca371-625c-40e7-a64f-c0431b80370d",
"valuations": [
{ "asset": "USD", "value": "58140.31" },
{ "asset": "EUR", "value": "53633.26" }
],
"blockchain_data": {
"transaction_hash": "8ecfd4162367d5919cbbc071ec33df9800978cdc34c80d98cade61fa7d88be00",
"block_explorer_link": "https://chain.so/tx/BTC/8ecfd4162367d5919cbbc071ec33df9800978cdc34c80d98cade61fa7d88be00"
}
}
}
}
Example PAYIN_REJECTED
event in fiat currency:
{
"event": "PAYIN_REJECTED",
"event_id": "da5be5cf-63c1-55af-adb6-05a6bc254f10",
"data": {
"id": "725cb2c2-173c-4dcd-b62f-d589e9526b00",
"type": "payin",
"attributes": {
"asset_code": "EUR",
"amount": "400000",
"destination": {
"wallet_id": "597165e7-1860-4037-be8a-03c4cb52ffbf",
"wallet_name": "EUR wallet",
"wallet_details_name": "Primary wallet details",
"wallet_details_iban": "GB21MOCK00000003984495"
},
"source": {
"name": "John Doe",
"iban": "DE91100000000123456789",
"bic": "AGRIFRPI",
"country": "GB",
"physical_address": "Address Line 1 "
},
"status": "rejected",
"transaction_id": "9c96d8bf-e141-4891-9919-a479e0a650c8",
"created_at": "2024-08-13T07:44:57Z",
"reference": "Payment from John Doe"
}
}
}
Payout
The following table describes the fields within data.attributes
for when data.type
is payout
:
Field | Type | Description |
---|---|---|
amount | string | The amount of the payout, in decimal format. |
asset_code | string | The code of the asset being used (e.g., BTC for Bitcoin). |
created_at | string | The timestamp when the payout was created, in ISO 8601 format. |
source | object | The source information of the payout. |
source.wallet_id | string | The UUID of the wallet from which the payout originates. |
source.wallet_name | string | The name of the wallet from which the payout originates. |
destination | object | The destination information for the payout. |
destination.beneficiary_id | string | The UUID of the beneficiary receiving the payout. |
destination.beneficiary_description | string | The description of the beneficiary receiving the payout. |
destination.beneficiary_address | string | The blockchain address of the beneficiary receiving the payout. |
destination.beneficiary_iban | string | The IBAN of the beneficiary receiving the payout. |
reference | string | Payment reference used in fiat transactions to convey information about the payout being made. |
status | string | The status of the payout. The only possible value is: completed . |
transaction_id | string | The UUID for the transaction. |
valuations | array | An array of valuation objects, each containing an asset and its corresponding value. |
valuations[].asset | string | The code of the asset for the valuation (e.g., USD, EUR). |
valuations[].value | string | The value of the asset in the specified currency. |
blockchain_data | object | Contains blockchain-specific data. |
blockchain_data.transaction_hash | string | The hash of the blockchain transaction. |
blockchain_data.block_explorer_link | string | A link to view the transaction on a blockchain explorer. |
Example PAYOUT_COMPLETED
event in fiat currency:
{
"event": "PAYOUT_COMPLETED",
"event_id": "7c8e9a9f-8e5e-4b6e-a2b1-9c7e7fa1b14b",
"data": {
"id": "a12b3c45-d678-90ef-gh12-ijklmnopq345",
"type": "payout",
"attributes": {
"amount": "250.75",
"created_at": "2024-07-15T10:00:00Z",
"asset_code": "EUR",
"source": {
"wallet_id": "e7b9f2d0-1e5e-4b7e-855a-11e05cf87ed1",
"wallet_name": "Business Account"
},
"destination": {
"beneficiary_id": "f1c2d3e4-5678-90ab-cdef-1234567890ab",
"beneficiary_description": "John Doe's Savings",
"beneficiary_iban": "US12345678901234567890"
},
"reference": "Payout for invoice #67890",
"status": "completed",
"transaction_id": "f14d2e6b-1234-4567-89ab-cdef12345678",
"signatures": {
"quorum": 0,
"signatories": [],
"mfa": ["totp"]
}
}
}
}
Example PAYOUT_COMPLETED
event in digital currency:
{
"event": "PAYOUT_COMPLETED",
"event_id": "9c2d3f4a-6789-1234-5678-abcdef012345",
"data": {
"id": "a12b3c45-d678-90ef-gh12-ijklmnopq345",
"type": "payout",
"attributes": {
"amount": "0.75",
"created_at": "2024-07-15T10:00:00Z",
"asset_code": "BTC",
"source": {
"wallet_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"wallet_name": "Bitcoin Wallet"
},
"destination": {
"beneficiary_id": "b2c3d4e5-6789-1234-5678-abcdef123456",
"beneficiary_description": "Alice's Main Wallet",
"beneficiary_address": "tz1a4GT7THHaGDiTxgXoatDWcZfJ5j29z5RC"
},
"status": "completed",
"transaction_id": "e9f8a7b6-5c4d-3e2f-1a2b-34567890abcd",
"valuations": [
{ "asset": "USD", "value": "1250.00" },
{ "asset": "EUR", "value": "1150.00" }
],
"blockchain_data": {
"transaction_hash": "8ecfd4162367d5919cbbc071ec33df9800978cdc34c80d98cade61fa7d88be00",
"block_explorer_link": "https://chain.so/tx/BTC/8ecfd4162367d5919cbbc071ec33df9800978cdc34c80d98cade61fa7d88be00"
},
"signatures": {
"quorum": 0,
"signatories": [],
"mfa": ["totp"]
}
}
}
}
Example PAYOUT_REJECTED
event in fiat currency:
{
"event": "PAYOUT_REJECTED",
"event_id": "5a51d345-0308-59b7-b759-fdc99e34476c",
"data": {
"id": "14089fa4-9608-4974-be5b-cc56006a8fbf",
"type": "payout",
"attributes": {
"amount": "19999.75",
"created_at": "2024-07-15T10:00:00Z",
"asset_code": "EUR",
"source": {
"wallet_id": "e7b9f2d0-1e5e-4b7e-855a-11e05cf87ed1",
"wallet_name": "Business Account"
},
"destination": {
"beneficiary_id": "f1c2d3e4-5678-90ab-cdef-1234567890ab",
"beneficiary_description": "John Doe's Savings",
"beneficiary_iban": "US12345678901234567890"
},
"reference": "Payout for invoice #77350",
"status": "rejected",
"transaction_id": "8b9d0375-4aff-4950-b2f9-e38299678e94",
"signatures": {
"quorum": 0,
"signatories": [],
"mfa": ["totp"]
}
}
}
}
Payment link
The following table describes the fields within data.attributes
for when data.type
is payment_link
:
Field | Type | Description |
---|---|---|
base_amount | string | The desired payment amount expressed in the base_asset_code. |
base_asset_code | string | The currency used as the basis for calculating the amount to be paid. |
quote_amount | string | The amount of the payment expressed in the quote currency. |
quote_asset_code | string | The currency used as the basis for calculating the amount paid. |
created_at | string | The specific date on which the payment link was created. |
expired_at | string | The specific date on which the payment link will be expired. |
destination | object | The destination information for the payment link. |
destination.type | object | Type of the destination for the payment link (beneficiary or wallet ). |
destination.beneficiary_id | string | The UUID of the beneficiary receiving the payment link. |
destination.wallet_id | string | The UUID of the wallet receiving the payment link. |
external_reference | string | A reference to an external entity or resource. |
note | string | A custom message or note. This field allows for personalized communication or additional instructions to the payer. |
status | string | The status of the payment link. (completed, underpaid , overpaid , expired ). |
link | string | The URL to the payment page. |
network_name | string | The name of the network used for the transaction. |
transaction_amount | string | The amount of the payment expressed in the transaction currency. |
transaction_source | string | The source of the transaction. |
Example PAYMENT_LINK_COMPLETED
event:
{
"event": "PAYMENT_LINK_COMPLETED",
"event_id": "631ab6cd-a106-504d-a2ba-c908fe8b07fc",
"data": {
"id": "55ca325e-0ca5-4feb-b2a4-1603d7bb973f",
"type": "payment_link",
"attributes": {
"base_amount": "1.11",
"base_asset_code": "EUR",
"status": "completed",
"created_at": "2024-08-13T09:00:20.885644Z",
"transaction_amount": "1.23",
"transaction_source": "0xb38906c22C40981fcf116E2eaC1D82fca0bcf983",
"network_name": "Binance_Smart_Chain Test",
"link": "pay.testing.numias.tech/c7cace35-2b09-4100-a526-198829ab10fd",
"quote_asset_code": "USDT_BSC_TEST",
"quote_amount": "1.23",
"quote_expired_at": "2024-08-13T09:15:27.124385Z",
"destination": {
"type": "wallet",
"wallet_id": "8dd02bfa-92c6-11ee-adf2-e696041ed0d1"
}
}
}
}
Updated 4 months ago