Webhooks
Real-time HTTPS webhooks for stablecoin and fiat payment events on the Fipto API — RSA-SHA512 signatures, IP allowlist, exponential-backoff retries.
Fipto webhooks are HTTPS POST notifications that fire whenever a payment event happens in your workspace — a payin is created, a payout completes, a payment link is paid. They are signed with RSA-SHA512, sent from a fixed IP allowlist, and retried with exponential backoff. This page is the reference; the FAQ at the bottom answers the questions that usually come up during integration.
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 the webhook notification was received. In case of an unexpected status code or lack of response within 5 seconds, a retry will be issued according to our retry policy.
Retry Policy
If the Fipto server doesn't receive a 2XX HTTP response to the POST request within 5 seconds, it will retry the request with exponential backoff. 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 an 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, a unique event_id for 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 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, payout or payment_link. |
data.attributes | object | Contains the attributes related to the data object. |
Payin
Fields within data.attributes 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). |
created_at | string | The timestamp when the payin was created, in ISO 8601 format. |
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.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. |
status | string | The status of the payin. Possible values: in transit, completed. |
transaction_id | string | The UUID for the transaction. |
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.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
Fields within data.attributes 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. |
created_at | string | The timestamp when the payout was created, in ISO 8601 format. |
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.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. |
status | string | The status of the payout. |
transaction_id | string | The UUID for the transaction. |
valuations[].asset | string | The code of the asset for the valuation. |
valuations[].value | string | The value of the asset in the specified currency. |
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
Fields within data.attributes 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 date on which the payment link was created. |
expired_at | string | The date on which the payment link expires. |
destination.type | string | Type of destination: beneficiary or wallet. |
destination.beneficiary_id | string | UUID of the beneficiary receiving the payment link. |
destination.wallet_id | string | 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. |
status | string | completed, underpaid, overpaid or expired. |
link | string | The URL of 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": "USDC_ERC20",
"quote_amount": "1.23",
"quote_expired_at": "2024-08-13T09:15:27.124385Z",
"destination": { "type": "wallet", "wallet_id": "8dd02bfa-92c6-11ee-adf2-e696041ed0d1" }
}
}
}Frequently asked questions
How does Fipto sign webhook payloads?
Fipto signs webhook payloads with RSA-SHA512 and delivers the base64-encoded signature in the Fipto-Signature header. Verify it with the environment-specific public key above.
What IPs will Fipto's webhooks come from?
From the fixed IP allowlist above: three IPs in demo and three in production.
How long does Fipto wait for my endpoint to respond?
5 seconds. Anything longer, or any non-2XX response, triggers the retry policy.
How many times will Fipto retry a failed webhook?
Up to 10 retries with exponential backoff at 2, 4, 8, 16, 32, 64, 128, 256, 512, 900 seconds. The final retry lands about 32 minutes after the first failure.
How do I avoid processing the same event twice?
De-duplicate on event_id. Every retry of the same event carries the same event_id.
Which events can Fipto send?
PAYIN_CREATED, PAYIN_COMPLETED, PAYIN_REJECTED, PAYOUT_COMPLETED, PAYOUT_REJECTED, PAYMENT_LINK_COMPLETED.
Updated 15 days ago
