Stay up to date with the latest events in your Widget implementation with webhooks
Overview
Webhooks provide real-time notifications when important events take place in your Okra integration. You can subscribe to these events by setting up a webhook URL and receive notifications to your system in simple JSON
payloads.
Webhook responses correspond to the Okra products that you enable in your Widget integration. Some examples when Okra sends webhook notifications:
- a user successfully connects their account
- a user's account needs reauthentication
- an identity profile is ready
- an income profile is ready
Use these notifications for tasks that require a response via the API, such as asynchronous requests, retries, or any other operation that needs processing on the backend of your application.
How to use
Okra recommends that you follow this workflow to ensure a smooth flow of information in your app:
- Ensure that your app can receive webhooks
- Subscribe to webhooks to receive event notifications and up-to-date data
- Check that your integration follows the best practices
Receiving events
To receive event notifications from Okra, you simply need to open an unauthenticated POST
route in your application. The Okra API sends event notifications as a JSON
payload in the request body.
Sample code on receiving events in NodeJs and PHP:
// 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);
});
<?php
// Retrieve the request's body and parse it as JSON
$input = @file_get_contents("php://input");
$event = json_decode($input);
// Do something with $event
http_response_code(200); // PHP 5.4 or higher
?>
Subscribe to webhooks
You can subscribe to webhook notifications in 3 ways:
In the App Builder
Add your preferred webhook URL to the callback_url
field in the App Builder when customizing your Widget experience. Okra uses this URL to deliver event notifications about all products as POST
requests. Using this subscription method, you can define an app-level webhook URL.
You can define this URL in both the Quick link and the Full customization options in the App Builder. Check out the Customization guide for more details.
In the Dashboard
Set up your preferred webhook URL on the Webhooks page in the Dashboard. Okra uses this URL to deliver event notifications about all products as POST
requests. Using this subscription method, you can define a project-level webhook URL.
- On the Configuration tab, select your preferred API environment.
- Add your URL that receives event notifications
- Add your secret API key as the bearer token and Save your changes.
When building with options
options
You can programmatically add your preferred webhook URL using the callback_url
Widget property. Okra uses this URL to deliver event notifications about all products as POST
requests. Using this subscription method, you can define an app-level webhook URL.
Visit the Integration guide to learn more about this integration option, and check out the available Widget properties.
Webhook levels
Okra provides webhooks on 2 levels: app and project.
App-level means that Okra sends notifications to your preferred webhook URL only about a specific Widget app. This enables you to define different webhook URLs for different Widget custiomizations, giving you more flexibility when working with multiple Widget integrations.
- Set up app-level webhooks in the App Builder or when building with
options
.
Project-level means that Okra sends notifications to your preferred webhook URL about every Widget app in your active project.
- Set up project-level webhooks in the Dashboard.
Webhook priority
The Okra API always tries sending webhooks to app-level webhook URLs first.
- If you do not define an app-level webhook URL, the API tries sending the webhooks again to the project-level URL.
- If you do not define a project-level webhook URL, the Okra API does not try sending the webhooks again.
Available events
See this table for a list of available webhook events for Okra's products:
Products | Events |
---|---|
Authentication | AUTH_SUCCES, AUTH_FAILED |
Identity | IDENTITY_IS_READY |
Accounts | ACCOUNTS_SUCCESS, ACCOUNTS_FAILED |
Balance | BALANCE_SUCCESS, BALANCE_FAILED |
Payments | PAYMENT_SUCCESS, PAYMENT_FAILED, PAYMENT_CANCELLED |
Transactions | TRANSACTIONS_IS_READY, TRANSACTIONS_FAILED |
Income | INCOME_IS_READY, INCOME_FAILED |
User authentication webhooks
Okra offers 2 webhooks that notify you about user authentication events:
USER_DISCONNECT
: when a user disconnects their accountUSER_REAUTH
: when reauthentication is needed for a user
Sample payloads for these events:
{
"message": <message about the connection/>,
"event": 'USER_DISCONNECT',
"data": {
"accounts": <id-of-accounts-disconnected/>
"customer": <id-of-user/>
"disconnected_at": <time-of-disconnection/>
}
}
{
"message": <message about the connection/>,
"event": 'USER_REAUTH',
"data": {
"customer": <id-of-user/>
"deauthorized_at": <time-of-disconnection/>
}
}
Sample webhook responses
You can check sample webhook responses for Okra's products here:
{
"method":"AUTH",
"callback_type":"AUTH",
"callback_code":"AUTH_SUCCESS",
"type":"CALLBACK",
"code":"AUTH_SUCCESS",
"callbackURL":"https://webhook.site/f9feec4c-3b12-4d10-82a6-7da824fb1aaf",
"env":"production-sandbox",
"status":"is_success",
"started_at":"2021-10-14T09:56:30.121Z",
"ended_at":"2021-10-14T09:56:30.474Z",
"message":"Record callback started!",
"meta_responses":null,
"meta":{
},
"bankName":"Stanbic IBTC Bank",
"bankType":"ind",
"bankId":"5d6fe57a4099cc4b210bbeb6",
"bankSlug":"stanbic-ibtc-bank",
"record":"6167febb7e0b622d072a3335",
"recordId":"6167febb7e0b622d072a3335",
"callback_url":"http://localhost:5000/v2/callback?record=6167febb7e0b622d072a3335&method=AUTH",
"login_type":"mobile",
"customerId":null,
"customerEmail":[
"[email protected]",
"[email protected]"
],
"customerBvn":null,
"country":"NG",
"extras":{
},
"current_project":"6050d01a9306f087a64462cf",
"owner":"5d9288ea182d3d000cb7c486"
}
{
"method":"IDENTITY",
"callback_type":"IDENTITY",
"callback_code":"PRODUCT_IS_READY",
"type":"CALLBACK",
"code":"PRODUCT_IS_READY",
"callbackURL":"https://webhook.site/#!/b9656de5-2803-40e0-8e8b-11bad56a1884",
"env":"production",
"status":"is_success",
"started_at":"2021-10-14T13:01:29.831Z",
"ended_at":"2021-10-14T13:01:30.884Z",
"message":"Record callback started!",
"meta_responses":null,
"options":{
"tester_id":"123"
},
"meta":{
},
"bankName":"Stanbic IBTC Bank",
"bankType":"ind",
"bankId":"5d6fe57a4099cc4b210bbeb6",
"bankSlug":"stanbic-ibtc-bank",
"record":"616829f0aed04439dc016b9e",
"recordId":"616829f0aed04439dc016b9e",
"login_type":"mobile",
"customerId":"613644c21eeb46b178f0d798",
"identityType":"bvn",
"customerEmail":[
""
],
"customerBvn":null,
"country":"NG",
"extras":{
},
"identity":{
"bvn":"22165416979",
"nin":"97340973633",
"firstname":"OLATUNDE",
"lastname":"GARUBA",
"middlename":"MICHAEL",
"email":[
""
],
"name":"OLATUNDE MICHAEL GARUBA",
"fullname":"OLATUNDE MICHAEL GARUBA",
"dob":"1984-04-16",
"gender":"M",
"marital_status":"Single",
"phone":[
"08038603506"
],
"address":[
"JACOB MEWS ADEBISI, STREET, YABA",
"2/4 FUSHO STREET QUEENS COLLEGE LAGOS"
],
"aliases":[
"OLATUNDE GARUBA",
"undefined undefined"
],
"verification_country":"NG",
"photo_id":[
],
"lga_of_origin":"Ogbomosho North",
"lga_of_residence":"Lagos Mainland",
"nationality":"Nigeria",
"state_of_origin":"Oyo State",
"state_of_residence":"Lagos State",
"options":{
"tester_id":"123"
},
"id":"613bb6d194f8133a31591f38",
"details":"https://api.okra.ng/v2/callback?record=616829f0aed04439dc016b9e&method=IDENTITY",
"customer":"613644c21eeb46b178f0d798",
"bank":"5d6fe57a4099cc4b210bbeb6",
"env":"production",
"projects":[
"6050d01a9306f087a64462cf"
]
},
"current_project":"6050d01a9306f087a64462cf",
"owner":"5d9288ea182d3d000cb7c486"
}
{
"method":"ACCOUNTS",
"callback_type":"ACCOUNTS",
"callback_code":"ACCOUNTS_SUCCESS",
"type":"CALLBACK",
"code":"ACCOUNTS_SUCCESS",
"callbackURL":"https://webhook.site/f9feec4c-3b12-4d10-82a6-7da824fb1aaf",
"env":"production-sandbox",
"status":"is_success",
"started_at":"2021-10-14T09:34:37.888Z",
"ended_at":"2021-10-14T09:34:38.538Z",
"message":"Record callback started!",
"accountId":"6167442f2791dde7e1cfeef5",
"meta_responses":null,
"options":{
},
"meta":{
},
"bankName":"Stanbic IBTC Bank",
"bankType":"ind",
"bankId":"5d6fe57a4099cc4b210bbeb6",
"bankSlug":"stanbic-ibtc-bank",
"record":"6167f8a9dfa6e32b9c8f4ed3",
"recordId":"6167f8a9dfa6e32b9c8f4ed3",
"callback_url":"http://localhost:5000/v2/callback?record=6167f8a9dfa6e32b9c8f4ed3&method=ACCOUNTS",
"login_type":"mobile",
"customerId":null,
"customerEmail":[
"[email protected]",
"[email protected]"
],
"customerBvn":null,
"country":"NG",
"extras":{
},
"nuban":"7433275284",
"account":{
"_id":"6167442f2791dde7e1cfeef5",
"bank":"5d6fe57a4099cc4b210bbeb6",
"env":"production-sandbox",
"nuban":"7433275284",
"created_at":"2021-10-13T20:40:14.870Z",
"customer":null,
"last_updated":"2021-10-14T09:34:30.488Z",
"name":"another test",
"type":"Savings",
"currency":"NGN"
},
"current_project":"6050d01a9306f087a64462cf",
"owner":"5d9288ea182d3d000cb7c486"
}
{
"method":"BALANCE",
"callback_type":"BALANCE",
"callback_code":"BALANCE_SUCCESS",
"type":"CALLBACK",
"code":"BALANCE_SUCCESS",
"callbackURL":"https://webhook.site/f9feec4c-3b12-4d10-82a6-7da824fb1aaf",
"env":"production-sandbox",
"status":"is_success",
"started_at":"2021-10-14T10:05:55.441Z",
"ended_at":"2021-10-14T10:06:02.141Z",
"message":"Record callback started!",
"accountId":"6167442f2791dde7e1cfeef5",
"meta_responses":null,
"options":{
},
"meta":{
},
"bankName":"Stanbic IBTC Bank",
"bankType":"ind",
"bankId":"5d6fe57a4099cc4b210bbeb6",
"bankSlug":"stanbic-ibtc-bank",
"record":"616800e94600fc2d7e6f10a9",
"recordId":"616800e94600fc2d7e6f10a9",
"callback_url":"http://localhost:5000/v2/callback?record=616800e94600fc2d7e6f10a9&method=BALANCE",
"login_type":"mobile",
"customerId":null,
"customerEmail":[
"[email protected]",
"[email protected]"
],
"customerBvn":null,
"country":"NG",
"extras":{
},
"nuban":"7433275284",
"balance":{
"_id":"616744312791dde7e1cfef27",
"available_balance":10134674,
"created_at":"2021-10-13T20:40:17.318Z",
"currency":"NGN",
"customer":null,
"env":"production-sandbox",
"last_updated":"2021-10-14T10:05:55.441Z",
"ledger_balance":10134674,
"$addToSet":{
"owner":"5d9288ea182d3d000cb7c486"
}
},
"current_project":"6050d01a9306f087a64462cf",
"owner":"5d9288ea182d3d000cb7c486"
}
{
"method":"TRANSACTIONS",
"callback_type":"TRANSACTIONS",
"callback_code":"PRODUCT_IS_READY",
"type":"CALLBACK",
"code":"PRODUCT_IS_READY",
"callbackURL":"https://webhook.site/f9feec4c-3b12-4d10-82a6-7da824fb1aaf",
"env":"production-sandbox",
"status":"is_success",
"started_at":null,
"ended_at":"2021-10-14T09:37:23.060Z",
"message":"Record callback started!",
"accountId":"6167442f2791dde7e1cfeef5",
"meta_responses":null,
"options":{
},
"meta":{
},
"bankName":"Stanbic IBTC Bank",
"bankType":"ind",
"bankId":"5d6fe57a4099cc4b210bbeb6",
"bankSlug":"stanbic-ibtc-bank",
"record":null,
"recordId":null,
"callback_url":"http://localhost:5000/v2/callback?record=null&method=TRANSACTIONS",
"login_type":"mobile",
"customerBvn":null,
"country":"NG",
"extras":{
},
"newTransactions":0,
"nuban":"7433275284"
}
{
"method":"INCOME",
"callback_type":"INCOME",
"callback_code":"PRODUCT_IS_READY",
"type":"CALLBACK",
"code":"PRODUCT_IS_READY",
"callbackURL":"https://16764cf0511d.ngrok.io/v1/callback",
"env":"production",
"status":"is_success",
"started_at":"2021-10-14T00:33:13.068Z",
"ended_at":"2021-10-14T00:36:44.195Z",
"message":"Record callback started!",
"accountId":"6089ddfba351d4b0d6e7f922",
"options":{
},
"meta":{
}
}
{
"method":"PAYMENT",
"callback_type":"PAYMENT",
"callback_code":"PAYMENT_SUCCESS",
"type":"CALLBACK",
"code":"PAYMENT_SUCCESS",
"callbackURL":"http://localhost:5000/v2/callback",
"env":"production",
"status":"is_success",
"started_at":"2021-09-13T16:36:46.997Z",
"ended_at":"2021-09-13T16:39:01.346Z",
"message":"Record callback started!",
"accountId":"609aa830dd46hfd2604a518f",
"meta_responses":null,
"options":{
},
"meta":{
},
"bankName":"Guaranty Trust Bank",
"bankType":"ind",
"bankId":"5d6o9hg4s099cc4b210bbeb3",
"bankSlug":"guaranty-trust-bank",
"record":"613f7c8c37a198uhbv4efce9",
"recordId":"6190ok7627a1679413eefce9",
"callback_url":"https://api.okra.ng/v2/callback?record=613f7c8c37a198uhbv4efce9&method=PAYMENT",
"login_type":"mobile",
"customerId":"608b0098yt5fg42a4989c70c",
"identityType":"bvn",
"customerEmail":[
"[email protected]"
],
"country":"NG",
"extras":{
},
"garnishment":{
"amount_collected":10000
},
"schedule":{
"current_amount":0,
"paymentId":"613f7e0a7a7b6917bee79ef5"
},
"paymentId":"613f7c8c37a198uhbv4efce9",
"link":null,
"payment":{
"_id":"613f7c8c37a198uhbv4efce9",
"record":"613f7c8c37a198uhbv4efce9",
"amount":10000,
"available_balance":null,
"bank":"5d6fe57a4099cc4b210bbeb3",
"bank_response":{
"CODE":"1000",
"MESSAGE":"TRANSACTION SUCCESSFUL",
"SESSIONID":"0000132186543073850000325621364",
"ERROR":null,
"STATUSCODE":null,
"STATUSMESSAGE":null,
"NIBSSRESPONSECODE":" 00",
"BANKDOWNTIMEMESSAGE":"",
"DestAccName":"OKRA WALLET"
},
"created_at":"2021-09-13T16:36:26.652Z",
"credit_account":"5eaaff7741318jh464b964d3",
"currency":"NGN",
"current_project":"6050d01a9307g087a64462cf",
"debit_account":"609aa830dd48gf72604a518f",
"email":null,
"env":"production",
"error":null,
"error_response":null,
"fee":26.88,
"last_updated":"2021-09-13T16:38:58.809Z",
"link":null,
"meta":{
},
"meta_responses":null,
"owner":"5d9288ea182d38v00cb7c486",
"ref":"Okra, Inc via OKR PAY Ref _XbpOiwNX",
"schedule":null,
"source":"link",
"status":"success",
"customer":"608b03b09doj2d2a4989c70c"
},
"current_project":"6050d00o9306f087a64462cf",
"owner":"5d9288ea182d3dho0cb7c486"
}
{
"method": "PAYMENT",
"callback_type": "PAYMENT",
"callback_code": "PAYMENT_CANCELLED",
"type": "CALLBACK",
"code": "PAYMENT_CANCELLED",
"env": "production",
"status": "is_cancelled",
"started_at": "2023-09-08T08:49:12.425Z",
"ended_at": "2023-09-08T08:50:07.741Z",
"message": "payment cancelled",
"error": "",
"accountId": "1498d3f7697aaf7019a4db6a",
"options": {},
"meta": {},
"bankName": "Access Bank",
"bankType": "1d6fe57a4099cc4b210bbec0",
"bankId": "1d6fe57a4099cc4b210bbec0",
"bankSlug": "access-bank",
"record": "14fae008080a7e004576cb2d",
"recordId": "14fae008080a7e004576cb2d",
"callback_url": "https://api.okra.ng/v2/callback?record=14fae008080a7e004576cb2d&method=PAYMENT",
"login_type": "app",
"country": "NG",
"extras": {},
"garnishment": {
"amount_collected": 0
},
"schedule": {
"current_amount": 0,
"paymentId": "14fae02860fb365271bdd18d"
},
"paymentId": "14fae02860fb365271bdd18d",
"payment": {
"amount": 10500,
"fee": 26.88,
"projects": [],
"type": "transfer",
"_id": "14fae02860fb365271bdd18d",
"record": "14fae008080a7e004576cb2d",
"__v": 0,
"available_balance": null,
"bank": "1d6fe57a4099cc4b210bbec0",
"bank_response": null,
"created_at": "2023-09-08T08:49:44.730Z",
"credit_account": "10a3bc792ba83b658736cd46",
"currency": "NGN",
"current_project": "10507f16da47873727a94610",
"debit_account": "1498d3f7697aaf7019a4db6a",
"email": null,
"env": null,
"error": null,
"error_response": null,
"last_updated": "2023-09-08T08:50:04.756Z",
"link": null,
"meta_responses": null,
"owner": "1d9288ea182d3d000cb7c486",
"ref": "OKRA, INC via OKR PAY Ref 4Hf-1Ig",
"refund": null,
"schedule": null,
"source": "integration",
"status": "cancelled",
"receipt": "14fae02e080a7e004576cb6f",
"customer": "14247efe8e3711362e9ef0ab"
},
"isRefund": false,
"callbackURL": "https://webhook.site/1b363e2a-d006-425d-8491-4b2d57039598"
}
Best practices
Follow these best practices to ensure that your webhook implementation runs smoothly.
Monitoring webhooks
- During integration, Okra recommends that you test and monitor that your app can successfully receive event notifications. You can use services like Webhooks.site or Pipedream for testing and monitoring.
Setting up webhook URLs
- If you are using
.htaccess
, make sure that you add the trailing/
to the URL you set. - Test your webhook URL with a
POST
request to ensure that it is able to receive the request body. - Make sure that your webhook URL is publicly available.
localhost
URLs cannot receive events.
Whitelisting webhook IPs
Okra delivers webhooks from these IP addresses:
13.39.179.188
13.38.152.18
35.180.165.18
Responding to event notifications
Okra recommends that you respond with a 200 OK
status message when you receive an event notification. You do not need to provide a request body or any other parameters, only the status code. The Okra API considers this as a confirmation that your app has received the notification.
If your app returns any status other than 2xx
, the API considers the notification as "not received". Based on Okra's retry policy, the API continues to send the notification every hour for the next 72 hours.
If your app starts a longer process in response to an event notifiction without sending a 200 OK
status message, the Okra API might time out in waiting for a response. The API considers this timeout the same as a notification that is "not received" and falls back to the retry policy. Okra recommends that you avoid duplicte notifications by sending a 200 OK
status message immediately when you receive an event notification.
Matching keys
All webhook requests are sent with an Okra-Auth header for verification. Okra recommends that you verify and match the webhook secret key you passed when creating this webhook.
Sample code on how to verify incoming webhook requests in Node JS
// Javascript Implementation
const secret = process.env.OKRA_WEBHOOK_KEY;
function verifyWebhook(req, res, next) {
//isVerified is a function that verifies the token
if (!isVerified(req.headers['Okra-Auth'])) {
return res.status(401).json({
message: "Unauthorized request."
});
}
next();
}
router.post('/create', verifyWebhook, (req, res) => {
const webhook = req.body;
switch(webhook.event) {
case "okra.event":
// do something with webhook.data.account;
break;
}
return res.sendStatus(200);
});
Trigger webhooks
Okra enables you to trigger webhooks for specific user records, to any URL that you set up. Triggering webhooks can be useful in these scenarios:
- You want to trigger webhooks to an alternative webhook URL for certain users
- You want to check the status of a webhook
- Your app did not receive webhook events due to technical issues and you want to retrigger failed event notifications
You can trigger webhooks by sending a POST
request to the /callback/trigger
endpoint:
curl -X POST 'https://api.okra.ng/v2/callback/trigger' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {your secret_API_key}' \
--data '{
"records": ["60b7be20ca7ce542d906e029", "60b7bc9aca7ce542d906e026"] //an array of record Ids
"url": "https://yourcompany.com/webhooks/okra" //the callback_url (optional), defaults to your saved callback_url
}'
{
"status": "success",
"message": "webhook trigger successfully initiated",
"data": {}
}
- Use your secret API key for bearer authentication
- Use these body parameters to specify your request:
Body parameter | Required | Description |
---|---|---|
records | true | An array of record ID for users. This array accepts a maximum of 100 record IDs. |
url | false | Specifies a URL where the Okra API sends triggered webhooks. If you do not specify url , the value defaults to the default webhook URL you set up. |
Webhooks for async data processing
Some of Okra's products, like Balance and Transactions require asynchronous data processing.
For these products, the Okra API provides a URL instead of immediately returning a response. You can periodically ping this URL to see if data processing is ready or not.
{
"transactions":{
"callback_url":"https://api.okra.ng/v2/callback?record=14ad5be8d14dd70039585b0c&method=TRANSACTIONS"
}
}
Example request:
curl -X GET https://api.okra.ng/v2/callback?record=14ad5be8d14dd70039585b0c&method=TRANSACTIONS"
-H 'Content-Type: application/json'
-H 'Authorization: Bearer {your_secret_API_key}'
- Send a
GET
request to the/callback
endpoint - Use the
record
andmethod
values that you received in the webhook as query parameters - Use your secret API key for bearer authentication