Webhooks
Learn how to listen to events whenever certain actions occur on your account.
What are webhooks?
Webhooks are a powerful way to integrate Bitpowr with your applications. They allow Bitpowr to notify you about events that happen on your account, such as incoming transactions or failed transactions.
When an event occurs, Bitpowr will send a webhook notification to the URL that you specify in your webhook settings. The notification will contain a JSON payload with details about the event.
You can use this information to take any action that you want. For example, you could update your user interface, send an email notification, or log the event.
Webhooks are a great way to keep your applications up-to-date with the latest information from Bitpowr. They can help you automate tasks, improve your workflow, and provide a better user experience.
Here are some examples of how you can use webhooks with Bitpowr:
- Send an email notification when a new transaction is received.
- Update your user interface to reflect the current balance of your account.
- Log all transactions to a database for historical analysis.
- Trigger a workflow in another application, such as a CRM system or an accounting software.
Webhooks are a powerful tool that can help you get the most out of Bitpowr. If you're not already using them, I encourage you to give them a try.
The following is a list of events we can send to your webhook URL.
Helpful Tip
We advise using a webhook instead of a callback to deliver value to your clients. Callbacks can fail if a customer's device's network connection fails or is weak, or if the device turns off after a request, among other things that are beyond our and your control.
Enabling Webhooks
You can specify your webhook URL from the Webhook Page on your dashboard where we would send POST requests whenever an event occurs.
Setup webhooks
To set up your webhook:
- Ensure you are in the right environment, if you are not click on the toggle button on the dashboard to switch to the right environment or mode
- Click on the Developer side menu and click webhooks.
- Input your webhook details: Webhook URL and Webhook Secret.
- Webhook URL: the URL to receive the webhook notifications.
- Webhook Secret : an optional secret key to pass along to the request header to encrypt your webhook payload during HMAC verification and also a way to verify if the request is coming from Bitpowr.
✳️ Done! The webhook is now set up and your application will be notified of new events related to any product opted for.
Receiving an event
All you have to do to receive the event is to create an unauthenticated POST endpoint on your application.
The event object is sent as JSON in the request body.
// Using Express
app.post("/your/webhook/url", function(req, res) {
// Retrieve the request's body
const event = req.body;
// Do something with event
res.send(200);
});
A 200 OK
should be used to respond to an event. This is considered an acknowledgment of your application. If your application returns a status other than 2xx
, we will consider it unacknowledged and will continue to send it every hour for the next 72 hours. You don't need to provide a request body or any other parameters because they will be ignored - we only care about the status code.
Bitpowr may timeout waiting for a response if your application is likely to start a long-running task in response to the event, in which case the event will be considered unacknowledged and queued to be raised later. You can avoid duplication by having your application respond with a 200 right away before continuing with the rest of the task.
Testing Webhooks Locally
You can set your Webhook URL on your TEST environment to a local URL (e.g. http://localhost, 127.0.0.1, etc.). We recommend using a tool such as ngrok.
Verifying Webhook Request
When you set up a webhook, you can optionally specify a webhook secret. This secret is used to verify that incoming requests are from Bitpowr.
Webhooks are publicly accessible URLs, so anyone could send a request to your webhook URL. If you don't use a webhook secret, anyone could send a request to your webhook URL and pretend to be Bitpowr.
To use a webhook secret, you need to specify a value for the secret when you set up the webhook. We recommend using a random value. You should also store the secret as an environment variable on your server.
When Bitpowr sends a webhook request, it will include the webhook secret in the request header. The header is called x-webhook-secret
.
When you receive a webhook request, you need to check the x-webhook-secret
header. If the header is missing, then the request is not from Bitpowr and cross if its set from the webhook settings. If the header is present, you need to decode the value and compare it to the webhook secret that you set. If the values do not match, then the request is not from Bitpowr.
If you find a request that is not from Bitpowr, you should discard the request. You should not process the request or take any action based on the request.
Here are some tips for setting up a webhook secret:
- Use a random value for the secret.
- Store the secret as an environment variable on your server.
- Check the
x-webhook-secret
header on all incoming webhook requests. - Discard requests that do not have the
x-webhook-secret
header or that have a secret that does not match the secret that you set.
By following these tips, you can help to protect your webhooks from unauthorized access.
Webhook Payload Structure
Every webhook payloads request made by Bitpowr follow the below basic structure:
event
: describing the eventdata
: An object containing the data associated with the event. The data might varies base on the type of event.
Webhook Payload Example
Here are some examples of webhook payloads for transactions:
{
"event": "transaction.incoming",
"data": {
"status": "SUCCESS",
"confirmation": 1,
"type": "DEPOSIT",
"address": "0x940e2eda985aefa2ac2879e6ef2c20d709444c12",
"senderAddress": "0xf845f557b16f2399b9807129f40773f5c804fcf8",
"hash": "0x7ff0d6c55d208a1ea5c538d92d849e6fc97de064fdf4d0d37ef01e463b054c72",
"chain": "ETHEREUM",
"amount": "0.001948983410253212",
"assetType": "ETH",
"assetId": "913ea13d-f218-42f0-bc4e-9b102f5960e2",
"accountId": "fbe283f0-88d7-4a4e-8629-b75abb14c83f",
"subAccountId": null
}
}
{
"event": "transaction.awaiting_confirmation",
"data": {
"status": "AWAITING_CONFIRMATION",
"confirmation": 0,
"type": "TRANSFER",
"address": "0x33ac59cb78165ee8c80079469d10041b2430f054",
"from": [
{
"id": "1ac54cb2-aef6-436c-8e79-e7dd4407d44b",
"chain": "ETHEREUM",
"value": "0.001701651711734",
"address": "0x9da3fb1f544eae42d1b3ee87ce11b61757b416fc",
"asset_id": "868797c7-49d2-4b61-9b67-959b4509d883",
"currency": "ETH",
"account_id": "a5bd6a60-06f5-49af-8dc5-c9475c16b3e2"
}
],
"hash": "0xb336b774fe47ae61d4f4fe1e4189d5884d9a50076e498bfa495368134c9eddb3",
"chain": "ETHEREUM",
"amount": "0.00165602",
"fee": "0.000045631711734",
"assetType": "ETH",
"ref": "BTP-Se#GbXFtm$lJsryOHn0MJpit#BSoYk",
"assetId": "a0e27f7b-83c7-4f39-be3f-80603611db4e",
"accountId": "4bc7f58e-6d6c-47de-939b-9713605f02b0"
}
}
{
"event": "transaction.success",
"data": {
"status": "SUCCESS",
"confirmation": 1,
"type": "TRANSFER",
"address": "0x33ac59cb78165ee8c80079469d10041b2430f054",
"from": [
{
"id": "1ac54cb2-aef6-436c-8e79-e7dd4407d44b",
"chain": "ETHEREUM",
"value": "0.001701651711734",
"address": "0x9da3fb1f544eae42d1b3ee87ce11b61757b416fc",
"asset_id": "868797c7-49d2-4b61-9b67-959b4509d883",
"currency": "ETH",
"account_id": "a5bd6a60-06f5-49af-8dc5-c9475c16b3e2"
}
],
"hash": "0xb336b774fe47ae61d4f4fe1e4189d5884d9a50076e498bfa495368134c9eddb3",
"chain": "ETHEREUM",
"amount": "0.00165602",
"fee": "0.000045631711734",
"gasLimit": "21000",
"gasPrice": "2172938654",
"assetType": "ETH",
"ref": "BTP-Se#GbXFtm$lJsryOHn0MJpit#BSoYk",
"assetId": "a0e27f7b-83c7-4f39-be3f-80603611db4e",
"accountId": "4bc7f58e-6d6c-47de-939b-9713605f02b0"
}
}
{
"event": "transaction.failed",
"data": {
"status": "FAILED",
"confirmation": null,
"type": "TRANSFER",
"address": "TCxF8YwwR693jcZUzsJE93tnJAUo3BdpGB",
"from": null,
"hash": null,
"chain": "TRON",
"amount": "881.83421517",
"fee": "0",
"assetType": "TRON",
"ref": "BTP-2bldPPHJlkrzBimKZeBD4tRGduTs43",
"assetId": "ad69fa10-93c4-4bc7-ba61-6130af8ae568",
"accountId": "753c595d-0b53-471e-8ab5-ef9f151f9fa5"
}
}
{
"event": "transaction.new",
"data": {
"status": "PENDING",
"confirmation": null,
"type": "TRANSFER",
"address": "TCxF8YwwR693jcZUzsJE93tnJAUo3BdpGB",
"from": null,
"hash": null,
"chain": "TRON",
"amount": "881.83421517",
"fee": "0",
"assetType": "TRON",
"ref": "BTP-2bldPPHJlkrzBimKZeBD4tRGduTs43",
"assetId": "ad69fa10-93c4-4bc7-ba61-6130af8ae568",
"accountId": "753c595d-0b53-471e-8ab5-ef9f151f9fa5"
}
}
Webhook Best Practices
Here are some things to note when working with Webhooks
Webhook URL
- If using
.htaccess
, remember to add the trailing/
to the URL you set. - Do a test post to your URL and ensure you are able to access POST body.
- Ensure your webhook URL is publicly available (localhost URLs cannot receive events)
Always Verify Webhook Information
As rule of thumb, always verify webhook notification information before taking any action. Whenever you receive a webhook notification, before giving the customer value, where possible, you should call our API again to verify the received details and ensure that the data has not been compromised.
For instance, when you receive a successful incoming transactions notification, you can use our transaction endpoint to verify the status of the transaction before crediting the user.
This additional step helps guarantee the accuracy and security of the received data. Essentially it will help protect your customers and your business from fraudulent activities.
Respond Early
For best practices, ensure your webhook endpoint respond within 60-90 seconds, or we will consider it a failure and retry the request.
Bitpowr may timeout waiting for a response if your application is likely to start a long-running task in response to the event, in which case the event will be considered unacknowledged and queued to be resend later. You can avoid webhook duplication by having your application respond with a 200 right away before continuing with the rest of the task.
Use Idempotency Scheme
When working with webhook events that involves transactions, its best to handle the events in such a way to avoid duplication. You can do this by making your webhook processing idempotent ensuring that multiple webhook events gives the same effect.
There's a possibility that in some cases we might send same webhooks multiple times and making the process idempotent would ensure that you dont give a customer value multiple times.
For every transaction webhook we send, there's always an idempotencyKey
value attached to the webhook payload. You can use this value as a unique field on your database.
Another way is to record the events and check for the status of the events. If the events has not changed, you can basically ignore the request.
Updated 5 months ago