Webhooks
TropiPay webhooks allow you to receive real-time notifications about events that occur in your account. This is especially useful for keeping your systems synchronized with TropiPay events, such as received payments, completed transactions, card status changes, and more.
What are webhooks?
Webhooks are HTTP callbacks that are sent to a specific URL when certain events occur in your TropiPay account. Instead of having to constantly poll the API to check if something has changed, webhooks automatically notify you when something relevant happens.
Benefits of using webhooks
- Real-time: Receive immediate notifications when events occur
- Efficiency: Reduces the need for periodic API polling
- Automation: Enables automated workflows based on TropiPay events
- Synchronization: Keep your systems updated with the latest data
The Webhook Event Object
All webhook notifications have the following basic structure:
{
"event": "payment.completed",
"data": {
"id": "pay_123456789",
"amount": 10000,
"currency": "EUR",
"status": "completed",
"created_at": "2023-07-22T12:30:00.000Z",
"completed_at": "2023-07-22T12:34:56.789Z",
"metadata": {
"order_id": "order_987654321"
}
},
"timestamp": "2023-07-22T12:34:56.789Z"
}
Attributes
| Attribute | Type | Description |
|---|---|---|
event | string | Name of the event that triggered the webhook |
data | object | Event-specific data payload |
timestamp | string | ISO 8601 timestamp when the event occurred |
Event Types
Payment Events
| Event | Description |
|---|---|
payment.created | A new payment has been created |
payment.completed | A payment has been completed successfully |
payment.failed | A payment has failed |
payment.refunded | A payment has been refunded |
Card Events
| Event | Description |
|---|---|
card.created | A new card has been created |
card.activated | A card has been activated |
card.blocked | A card has been blocked |
card.transaction | A transaction has been made with a card |
Account Events
| Event | Description |
|---|---|
account.updated | Account data has been updated |
account.verified | The account has been verified |
account.login | A login has occurred on the account |
Merchant Hooks
Merchant hooks are webhooks that are managed at the merchant/business level. These endpoints allow you to manage webhook subscriptions for your merchant account.
List Merchant Hooks
Returns a list of all events that the merchant is subscribed to via webhooks.
/merchant/hookscurl -X GET https://sandbox.tropipay.me/api/v3/merchant/hooks \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json"
Response
[
{
"event": "user_signup",
"target": "email",
"value": "user@example.com",
"createdAt": "2021-02-13T21:30:59.154Z",
"updatedAt": "2021-02-13T21:30:59.154Z"
},
{
"event": "payment_created",
"target": "web",
"value": "https://example.com/webhooks/payment-created",
"createdAt": "2021-02-13T21:30:59.154Z",
"updatedAt": "2021-02-13T21:30:59.154Z"
}
]
Response Parameters
| Parameter | Type | Description |
|---|---|---|
event | string | Name of the subscribed event |
target | string | Type of webhook target (web, email) |
value | string | Target value (URL for web, email address for email) |
createdAt | string | ISO 8601 timestamp when subscription was created |
updatedAt | string | ISO 8601 timestamp when subscription was last updated |
Subscribe to Merchant Event
Allows a merchant to subscribe to an event, specifying the options to receive information at the time it is triggered.
/merchant/hookscurl -X POST https://sandbox.tropipay.me/api/v3/merchant/hooks \
-H "Authorization: Bearer {merchant-token}" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"event": "user_signup",
"target": "web",
"value": "https://www.merchant_domain.com/api/user/signup/listen"
}'
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
event | string | Yes | String that represents the name of the event. You must select from the list of available events, otherwise it will not produce an error but will not be executed. For the full list of available events see endpoint GET /hook/events. |
target | string | Yes | String representing the type of event supported. Currently available: web (allows to receive information in a URL), email (allows to receive information in an email address). |
value | string | Yes | String that represents the value depending on the type of selected event determined by the 'target' property. For example, if the selected 'target' is email the value would be an email address, likewise if the selected 'target' is web the expected value corresponds to a URL that receives information through the HTTP POST method. |
Response
Status Code: 200 OK
{
"action": "update",
"status": "success",
"details": "user_signup"
}
Response Parameters
| Parameter | Type | Description |
|---|---|---|
action | string | The action performed (e.g., "update") |
status | string | Status of the operation ("success" or "error") |
details | string | Additional details about the operation, typically the event name |
Update Merchant Hook Subscription
Allows a merchant to update an event subscription, specifying the options to receive information at the time it is triggered. Take into account that the value of the name or denomination of the event cannot be modified. In case it is required to change this field, it is recommended to delete it and create a new subscription.
/merchant/hookscurl -X PUT https://sandbox.tropipay.me/api/v3/merchant/hooks \
-H "Authorization: Bearer {merchant-token}" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"event": "user_signup",
"target": "email",
"value": "merchant@example.com"
}'
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
event | string | Yes | String that represents the name of the event. This field cannot be modified - if you need to change the event, delete the subscription and create a new one. |
target | string | Yes | String representing the type of event supported. Currently available: web (allows to receive information in a URL), email (allows to receive information in an email address). |
value | string | Yes | String that represents the value depending on the type of selected event determined by the 'target' property. For example, if the selected 'target' is email the value would be an email address, likewise if the selected 'target' is web the expected value corresponds to a URL. |
Response
Status Code: 200 OK
{
"action": "update",
"status": "success",
"details": "user_signup"
}
Response Parameters
| Parameter | Type | Description |
|---|---|---|
action | string | The action performed ("update") |
status | string | Status of the operation ("success" or "error") |
details | string | Additional details about the operation, typically the event name |
Delete Merchant Hook Subscription
Allows a merchant to unsubscribe from an event by name or denomination.
/merchant/hookscurl -X DELETE https://sandbox.tropipay.me/api/v3/merchant/hooks \
-H "Authorization: Bearer {merchant-token}" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"event": "user_signup"
}'
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
event | string | Yes | String that represents the name of the event to unsubscribe from |
Response
Status Code: 200 OK
{
"action": "update",
"status": "success",
"details": "user_signup"
}
Response Parameters
| Parameter | Type | Description |
|---|---|---|
action | string | The action performed ("update") |
status | string | Status of the operation ("success" or "error") |
details | string | Additional details about the operation, typically the event name |
Get Available Events for Merchant
Endpoint for getting the full list of available events that allow subscription for merchant hooks.
/merchant/hooks/eventscurl -X GET https://sandbox.tropipay.me/api/v3/merchant/hooks/events \
-H "Authorization: Bearer {merchant-token}" \
-H "Accept: application/json"
Response
Status Code: 200 OK
[
{
"name": "user_signup",
"description": "Event launched once a user completes registration on the TropiPay platform."
},
{
"name": "user_login",
"description": "Event launched once a user completes login on the TropiPay platform."
},
{
"name": "user_kyc",
"description": "Event launched once a user completes KYC process, indicated in each case the process status."
},
{
"name": "payment_in_state_change",
"description": "The event is fired once a user changes their status payment in entry method."
},
{
"name": "payment_out_state_change",
"description": "The event is fired once a user changes their status payment out entry method."
}
]
Response Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | The name of the event that can be subscribed to |
description | string | Detailed description of when the event is triggered |
Available Events
Events are made up of an object with two fundamental properties (name, description):
- user_signup: Event launched once a user completes registration on the TropiPay platform.
- user_login: Event launched once a user completes login on the TropiPay platform.
- user_kyc: Event launched once a user completes KYC process, indicated in each case the process status. Payload of response includes:
{
"userId": "string",
"status": "string",
"event": "string",
"user": {}
} - payment_in_state_change: The event is fired once a user changes their status payment in entry method.
- payment_out_state_change: The event is fired once a user changes their status payment out entry method.
User Hooks
User hooks are webhooks that are managed at the individual user level. These endpoints allow users to manage their personal webhook subscriptions.
List User Hooks
Returns a list of user hook subscriptions for the authenticated user.
/user/hookscurl -X GET https://sandbox.tropipay.me/api/v3/user/hooks \
-H "Authorization: Bearer {user-token}" \
-H "Accept: application/json"
Response
Status Code: 200 OK
[
{
"event": "user_login",
"target": "web",
"value": "https://webhook.site/680826a5-199e-4455-babc-f47b7f26ee7e",
"createdAt": "2022-02-11T18:36:48.300Z",
"updatedAt": "2022-02-11T18:36:48.300Z"
},
{
"event": "user_kyc",
"target": "email",
"value": "user@example.com",
"createdAt": "2022-02-11T18:53:30.397Z",
"updatedAt": "2022-02-11T18:53:30.397Z"
},
{
"event": "beneficiary_added",
"target": "email",
"value": "user@example.com",
"createdAt": "2022-02-11T18:53:54.027Z",
"updatedAt": "2022-02-11T18:53:54.027Z"
}
]
Response Parameters
| Parameter | Type | Description |
|---|---|---|
event | string | Name of the subscribed event |
target | string | Type of webhook target (web, email) |
value | string | Target value (URL for web, email address for email) |
createdAt | string | ISO 8601 timestamp when subscription was created |
updatedAt | string | ISO 8601 timestamp when subscription was last updated |
Create User Hook
Insert a user hook to subscribe to webhook events.
/user/hookscurl -X POST https://sandbox.tropipay.me/api/v3/user/hooks \
-H "Authorization: Bearer {user-token}" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"event": "user_login",
"target": "web",
"value": "https://webhook.site/680826a5-199e-4455-babc-f47b7f26ee7e"
}'
Parameters
Events are made up of an object with three fundamental properties (event, target, value):
| Parameter | Type | Required | Description |
|---|---|---|---|
event | string | Yes | String that represents the name of the event. You must select from the list of available events, otherwise it will not produce an error but it will not be executed. For the full list of available events see endpoint GET /user/hooks/events. |
target | string | Yes | String representing the type of event supported. Currently available: web (allows to receive information in a URL), email (allows to receive information in an email address). |
value | string | Yes | String that represents the value depending on the type of selected event determined by the 'target' property. For example, if the selected 'target' is email the value would be an email address, likewise if the selected 'target' is web the expected value corresponds to a URL that receives information through the HTTP POST method. |
Response
Status Code: 200 OK
In general, valid responses are defined as an object with three elementary properties:
{
"action": "subscribe",
"status": "success",
"details": "user_login"
}
Response Parameters
| Parameter | Type | Description |
|---|---|---|
action | string | Represents the type of operation that was just executed |
status | string | Represents the status of the operation, taking value success in case everything goes well |
details | string | Displays additional values related to the operation, usually returns the name of the event |
Update User Hook
Explicit update hook on payload request.
/user/hookscurl -X PUT https://sandbox.tropipay.me/api/v3/user/hooks \
-H "Authorization: Bearer {user-token}" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"event": "user_login",
"target": "email",
"value": "user@example.com"
}'
Parameters
Events are made up of an object with three fundamental properties (event, target, value):
| Parameter | Type | Required | Description |
|---|---|---|---|
event | string | Yes | String that represents the name of the event. You must select from the list of available events, otherwise it will not produce an error but it will not be executed. For the full list of available events see endpoint GET /user/hooks/events. |
target | string | Yes | String representing the type of event supported. Currently available: web (allows to receive information in a URL), email (allows to receive information in an email address). |
value | string | Yes | String that represents the value depending on the type of selected event determined by the 'target' property. For example, if the selected 'target' is email the value would be an email address, likewise if the selected 'target' is web the expected value corresponds to a URL that receives information through the HTTP POST method. |
Response
Status Code: 200 OK
In general, valid responses are defined as an object with three elementary properties:
{
"action": "update",
"status": "success",
"details": "user_login"
}
Response Parameters
| Parameter | Type | Description |
|---|---|---|
action | string | Represents the type of operation that was just executed |
status | string | Represents the status of the operation, taking value success in case everything goes well |
details | string | Displays additional values related to the operation, usually returns the name of the event |
Get Available Events for User
Get user hook event list.
/user/hooks/eventscurl -X GET https://sandbox.tropipay.me/api/v3/user/hooks/events \
-H "Authorization: Bearer {user-token}" \
-H "Accept: application/json"
Response
Status Code: 200 OK
[
{
"name": "user_signup",
"description": "Event launched once a user completes registration on the TropiPay platform."
},
{
"name": "user_login",
"description": "Event launched once a user completes login on the TropiPay platform."
},
{
"name": "user_kyc",
"description": "Event launched once a user completes kyc process."
},
{
"name": "payment_in_state_change",
"description": "The event is fired once a user changes their status payment in entry method."
},
{
"name": "payment_out_state_change",
"description": "The event is fired once a user changes their status payment out entry method."
},
{
"name": "beneficiary_added",
"description": "Launched after new beneficiary is created."
},
{
"name": "beneficiary_updated",
"description": "Launched after a beneficiary is modified."
},
{
"name": "beneficiary_deleted",
"description": "Launched after a beneficiary is deleted."
}
]
Response Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | The name of the event that can be subscribed to |
description | string | Detailed description of when the event is triggered |
Available Events
The following events are available for user hook subscriptions:
- user_signup: Event launched once a user completes registration on the TropiPay platform.
- user_login: Event launched once a user completes login on the TropiPay platform.
- user_kyc: Event launched once a user completes kyc process.
- payment_in_state_change: The event is fired once a user changes their status payment in entry method.
- payment_out_state_change: The event is fired once a user changes their status payment out entry method.
- beneficiary_added: Launched after new beneficiary is created.
- beneficiary_updated: Launched after a beneficiary is modified.
- beneficiary_deleted: Launched after a beneficiary is deleted.
Get Specific User Hook
Select all hooks subscribed to a given event name. The URL for a certain event name would be as follows /user/hooks/user_login. For the previous case, all the hooks associated with the user_login event would be obtained, where basically a list would be returned where the target and the associated value would change.
/user/hooks/{event_name}curl -X GET https://sandbox.tropipay.me/api/v3/user/hooks/user_login \
-H "Authorization: Bearer {user-token}" \
-H "Accept: application/json"
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
event_name | string | Yes | The name of the event to retrieve hooks for (e.g., user_login, user_signup, beneficiary_added) |
Response
Status Code: 200 OK
[
{
"event": "user_login",
"target": "web",
"value": "https://webhook.site/680826a5-199e-4455-babc-f47b7f26ee7e",
"createdAt": "2022-02-11T18:36:48.300Z",
"updatedAt": "2022-02-11T18:36:48.300Z"
},
{
"event": "user_login",
"target": "email",
"value": "user@example.com",
"createdAt": "2022-02-11T18:43:24.882Z",
"updatedAt": "2022-02-11T18:43:24.882Z"
}
]
Response Parameters
| Parameter | Type | Description |
|---|---|---|
event | string | Name of the subscribed event |
target | string | Type of webhook target (web, email) |
value | string | Target value (URL for web, email address for email) |
createdAt | string | ISO 8601 timestamp when subscription was created |
updatedAt | string | ISO 8601 timestamp when subscription was last updated |
Get User Hook by Target
Select hook by event name and target name. Note that, to select the data of a very specific hook, you must filter by the name of the event and the target similar as below /user/hooks/user_login/web, in this case we try to request the data of the hook subscribed to the user_login event with notification via web hook.
/user/hooks/{event_name}/{target_name}curl -X GET https://sandbox.tropipay.me/api/v3/user/hooks/user_login/web \
-H "Authorization: Bearer {user-token}" \
-H "Accept: application/json"
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
event_name | string | Yes | The name of the event to filter by (e.g., user_login, user_signup, beneficiary_added) |
target_name | string | Yes | The target type to filter by (web, email) |
Response
Status Code: 200 OK
[
{
"event": "user_login",
"target": "email",
"value": "user@example.com",
"createdAt": "2022-02-11T18:43:24.882Z",
"updatedAt": "2022-02-11T18:43:24.882Z"
}
]
Response Parameters
| Parameter | Type | Description |
|---|---|---|
event | string | Name of the subscribed event |
target | string | Type of webhook target (web, email) |
value | string | Target value (URL for web, email address for email) |
createdAt | string | ISO 8601 timestamp when subscription was created |
updatedAt | string | ISO 8601 timestamp when subscription was last updated |
Delete User Hook
Delete or unsubscribe hook by event name and target name.
/user/hooks/{event_name}/{target_name}curl -X DELETE https://sandbox.tropipay.me/api/v3/user/hooks/user_login/web \
-H "Authorization: Bearer {user-token}" \
-H "Accept: application/json"
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
event_name | string | Yes | The name of the event to unsubscribe from (e.g., user_login, user_signup, beneficiary_added) |
target_name | string | Yes | The target type to unsubscribe from (web, email) |
Response
Status Code: 200 OK
In general, valid responses are defined as an object with three elementary properties:
{
"action": "unsubscribe",
"status": "success",
"details": "user_login"
}
Response Parameters
| Parameter | Type | Description |
|---|---|---|
action | string | Represents the type of operation that was just executed |
status | string | Represents the status of the operation, taking value success in case everything goes well |
details | string | Displays additional values related to the operation, usually returns the name of the event |
Event Structure
Events are composed of an object with three fundamental properties:
-
event: String representing the event name. You must select from the list of available events, otherwise it will not produce an error but will not be executed. For the complete list of available events, see the endpoint
GET /hook/events. -
target: String representing the supported event type. Currently available:
web: allows receiving information at a URLemail: allows receiving information at an email address
-
value: String representing the value depending on the selected event type determined by the 'target' property. For example, if the selected 'target' is 'email', the value would be an email address. Similarly, if the selected 'target' is 'web', the expected value corresponds to a URL that receives information through the HTTP POST method.
Webhook Implementation
Setting up your endpoint
To start receiving webhook notifications, you must register your endpoint URL in the TropiPay developer panel:
- Log in to your TropiPay account
- Go to Developers > Webhooks section
- Click "Add new webhook"
- Enter your endpoint URL (must be HTTPS)
- Select the events you want to receive
- Save the configuration
Once registered, you'll receive a webhook secret that you should use to verify notifications.
Example Implementation
Node.js (Express)
const express = require('express');
const crypto = require('crypto');
const bodyParser = require('body-parser');
const app = express();
// Important to use raw body for signature verification
app.use(bodyParser.json({
verify: (req, res, buf) => {
req.rawBody = buf;
}
}));
// Your webhook secret provided by TropiPay
const webhookSecret = 'your_webhook_secret';
// Function to verify signature
function verifySignature(signature, payload) {
const expectedSignature = crypto
.createHmac('sha256', webhookSecret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// Endpoint to receive webhooks
app.post('/tropipay-webhook', (req, res) => {
const signature = req.headers['x-tropipay-signature'];
// Verify that the signature is valid
try {
if (!signature || !verifySignature(signature, req.rawBody)) {
console.error('Invalid signature');
return res.status(401).send('Invalid signature');
}
// Process the event according to its type
const event = req.body.event;
const data = req.body.data;
console.log(`Event received: ${event}`);
switch (event) {
case 'payment.completed':
// Logic to process a completed payment
handlePaymentCompleted(data);
break;
case 'card.transaction':
// Logic to process a card transaction
handleCardTransaction(data);
break;
// Handle other event types...
default:
console.log(`Unhandled event: ${event}`);
}
// Always respond with 200 OK to confirm receipt
res.status(200).send('OK');
} catch (error) {
console.error('Error processing webhook:', error);
res.status(500).send('Error processing webhook');
}
});
function handlePaymentCompleted(data) {
// Implement your logic to handle completed payments
console.log('Payment completed:', data.id, data.amount, data.currency);
// For example: update order status in your database
}
function handleCardTransaction(data) {
// Implement your logic to handle card transactions
console.log('Card transaction:', data.card_id, data.amount, data.merchant);
// For example: log the transaction in your system
}
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}`);
});
PHP
<?php
// Get request body
$payload = file_get_contents('php://input');
$data = json_decode($payload, true);
// Get signature from header
$signature = $_SERVER['HTTP_X_TROPIPAY_SIGNATURE'] ?? '';
// Your webhook secret provided by TropiPay
$webhookSecret = 'your_webhook_secret';
// Verify signature
$expectedSignature = hash_hmac('sha256', $payload, $webhookSecret);
if (!hash_equals($expectedSignature, $signature)) {
http_response_code(401);
echo 'Invalid signature';
exit;
}
// Process the event according to its type
$event = $data['event'] ?? '';
$eventData = $data['data'] ?? [];
switch ($event) {
case 'payment.completed':
// Logic to process a completed payment
handlePaymentCompleted($eventData);
break;
case 'card.transaction':
// Logic to process a card transaction
handleCardTransaction($eventData);
break;
// Handle other event types...
default:
error_log("Unhandled event: $event");
}
// Functions to handle specific events
function handlePaymentCompleted($data) {
// Implement your logic to handle completed payments
error_log("Payment completed: {$data['id']}, {$data['amount']} {$data['currency']}");
// For example: update order status in your database
}
function handleCardTransaction($data) {
// Implement your logic to handle card transactions
error_log("Card transaction: {$data['card_id']}, {$data['amount']}, {$data['merchant']}");
// For example: log the transaction in your system
}
// Respond with 200 OK to confirm receipt
http_response_code(200);
echo 'OK';
?>
Webhook Security
To ensure that webhook notifications actually come from TropiPay, each request includes a signature in the X-Tropipay-Signature header. This signature is generated using the webhook secret associated with your account.
Verifying Signatures
Always verify the signature of webhook notifications:
- Get the signature from the
X-Tropipay-Signatureheader - Generate the expected signature using HMAC-SHA256 with your webhook secret
- Compare the signatures using a timing-safe comparison function
Best Practices
-
Signature verification: Always verify the signature of notifications to ensure they come from TropiPay.
-
Quick response: Respond quickly to notifications with a 200 OK code. If you need to perform extensive processing, do it asynchronously after responding.
-
Retry handling: TropiPay will retry sending notifications if your endpoint doesn't respond or returns an error code. Make sure your implementation is idempotent to avoid duplicates.
-
Event logging: Keep a log of all received events to facilitate debugging and tracking.
-
Timeout: Configure an appropriate timeout for your endpoint. TropiPay expects a response in less than 10 seconds.
Troubleshooting
If you're not receiving webhook notifications, check the following:
- The endpoint URL is correctly configured in TropiPay
- Your server is accessible from the Internet and accepts HTTPS connections
- There are no firewalls or security configurations blocking requests
- The webhook secret you're using is correct
- You're responding correctly to notifications with a 200 OK code
To test your implementation, you can use the "Send test" function in the TropiPay developer panel, which will allow you to send a test notification to your endpoint.
Error Handling
The Webhooks API uses conventional HTTP response codes to indicate the success or failure of webhook delivery.
Common Error Codes
| Code | Description |
|---|---|
200 | OK - Webhook delivered successfully |
400 | Bad Request - Invalid webhook configuration |
401 | Unauthorized - Invalid authentication |
403 | Forbidden - Insufficient permissions |
404 | Not Found - Webhook endpoint not found |
422 | Unprocessable Entity - Invalid webhook data |
429 | Too Many Requests - Rate limit exceeded |
500 | Internal Server Error |
Example Error Response
{
"error": {
"type": "webhook_error",
"code": "endpoint_unreachable",
"message": "Unable to reach webhook endpoint",
"endpoint": "https://example.com/webhook"
}
}