Webhooks
Learn how to listen to events whenever certain actions occur on your integration.
What are webhooks?
Whenever certain transaction actions occur on your Paystack integration, we trigger events which your application can listen to. This is where webhooks come in. A webhook is a URL on your server where we send payloads for such events. For example, if you implement webhooks, once a payment is successful, we will immediately notify your server with a charge.success
event. Here is a list of events we can send to your webhook URL.
Helpful Tip
You can specify your webhook URL on your dashboard where we would send POST
requests to whenever an event occurs.
Here are some things to note when setting up a webhook URL:
- If using
.htaccess
, remember to add the trailing/
to the url you set. - Do a test post to your URL and ensure the script gets the post body.
- Ensure your webhook URL is publicly available (localhost URLs cannot receive events)
Receiving an event
All you have to do to receive the event is to create an unauthenticated POST
route on your application. The event object is sent as JSON in the request body.
- Node
- PHP
1// Using Express2app.post("/my/webhook/url", function(req, res) {3 // Retrieve the request's body4 var event = req.body;5 // Do something with event6 res.send(200);7});
Verifying events
It is important to verify that events originate from Paystack to avoid delivering value based on a countefeit event.
You can do any or both of the below to verify events from Paystack:
- Validate the Signature - Valid events are raised with an header
X-Paystack-Signature
which is essentially aHMAC SHA512
signature of the event payload signed using your secret key. - Watch the IPs - We only call your webhooks from these IPs:
52.31.139.75
,52.49.173.169
,52.214.14.220
You can whitelist these IPs. Any webhook from outside of these can safely be considered counterfeit.
1var crypto = require('crypto');2var secret = process.env.SECRET_KEY;3// Using Express4app.post("/my/webhook/url", function(req, res) {5 //validate event6 var hash = crypto.createHmac('sha512', secret).update(JSON.stringify(req.body)).digest('hex');7 if (hash == req.headers['x-paystack-signature']) {8 // Retrieve the request's body9 var event = req.body;10 // Do something with event11 }12 res.send(200);13});
1
Responding to an event
You should respond to an event with a 200 OK
. We consider this an acknowledgement by your application. If your application responds with any status outside of the 2xx
range, we will consider it unacknowledged and thus, continue to send it every hour for 72 hours. You don't need to send a request body or some other parameter as it would be discarded - we only pay attention to the status code.
If your application is likely to start a long running task in response to the event, Paystack may timeout waiting for the response and would ultimately consider the event unacknowledged and queue to be raised later. You can mitigate duplicity by having your application respond immediately with a 200 before it goes on to perform the rest of the task.
Supported events
- Customer Identification Failed
- Customer Identification Successful
- Dispute Created
- Dispute Reminder
- Dispute Resolved
- Invoice Created
- Invoice Failed
- Invoice Updated
- Payment Request Pending
- Payment Request Successful
- Subscription Created
- Subscription Disabled
- Transaction Successful
- Transfer Successful
- Transfer Failed
- Transfer Reversed
1{2 "event": "customeridentification.failed",3 "data": {4 "customer_id": "9387490384",5 "customer_code": "CUS_xnxdt6s1zg1f4nx",6 "email": "bojack@horsinaround.com",7 "identification": {8 "country": "NG",9 "type": "bvn",10 "value": "200*****677"11 }12 }
Types of events
Here are the events we currently raise. We would add more to this list as we hook into more actions in the future.
Event | Description |
---|---|
charge.dispute.create | A dispute was logged against your business |
charge.dispute.remind | A logged dispute has not been resolved |
charge.dispute.resolve | A dispute has been resolved |
charge.success | A successful charge was made |
customeridentification.failed | A customer ID validation has failed |
customeridentification.success | A customer ID validation was successful |
invoice.create | An invoice has been created for a subscription on your account. This usually happens 3 days before the subscription is due or whenever we send the customer their first pending invoice notification |
invoice.payment_failed | A payment for an invoice failed |
invoice.update | An invoice has been updated. This usually means we were able to charge the customer successfully. You should inspect the invoice object returned and take necessary action |
paymentrequest.pending | A payment request has been sent to a customer |
paymentrequest.success | A payment request has been paid for |
subscription.create | A subscription has been created |
subscription.disable | A subscription on your account has been disabled |
subscription.enable | A subscription on your account has been enabled |
transfer.failed | A transfer you attempted has failed |
transfer.success | A successful transfer has been completed |
transfer.reversed | A transfer you attempted has been reversed |