Webhooks

Learn how to listen to events whenever certain actions occur on your integration.

What are webhooks?

We trigger events that your application can listen to whenever certain actions occur on your Okra integration. Here's where webhooks come in handy. We deliver payloads for such events to a webhook URL on your server. If you use webhooks, for example, we'll send a balance.success event to your server as soon as a balance is retrieved. 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.

You can specify your webhook URL on your dashboard where we would send POST requests whenever an event occurs.

Here are some things to note when setting up a webhook URL:

  1. If using .htaccess, remember to add the trailing / to the URL you set.
  2. Do a test post to your URL and ensure the script gets the post body.
  3. Ensure your webhook URL is publicly available (localhost URLs cannot receive events)

Webhooks Configuration

To set up a new webhook:

  1. From the Environment Switcher in your Okra dashboard, select the environment you want to create a new webhook.
  2. Select the Developer tab and click Webhooks.
  3. Select the Configuration tab and input your webhook URL and bearer token.
  • URL: The URL receives the data of an event that occurs in your Okra integrations.
  • Token: It's a text string used to authenticate API requests.
    Click Save Changes.
    ✳️ 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 route 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);
});
<?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 greater
?>

Best practices for setting up webhooks

1. Responding to an event

A 200 OK should be used to respond to an event. This is considered an acknowledgment by 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.

Okra 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.

2. Correctly matched keys

All webhook requests are sent with an Okra-Auth header for verification.
It is recommended that you verify and match the webhook secret key you passed when creating this webhook.

Here’s an example of 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);
});

Example incoming webhook

If you're using callbacks with any product, you'll receive a callback when Okra finishes processing the product's data for the Record. Once you receive this callback, you can make an API call to retrieve the product's data.

Below you will see an example of an incoming webhook from Okra's servers. The below example is for AUTH but you will receive webhooks for all products.

Webhook response

If you've set up webhook notifications for your account, we will also send you a response in the format below:

{
  method: 'IDENTITY',
  callback_type: 'IDENTITY',
  callback_code: 'PRODUCT_IS_READY',
  type: 'CALLBACK',
  code: 'PRODUCT_IS_READY',
  callbackURL: 'https://e2c550b71c3f.ngrok.io/v2/data/login/',
  env: 'production-sandbox',
  status: 'is_success',
  started_at: '2021-04-23T07:39:10.133Z',
  ended_at: '2021-04-23T07:39:35.376Z',
  message: 'Record callback started!',
  options: { },
  bankName: 'Access Bank',
  bankType: 'ind',
  bankId: '5d6fe57a4099cc4b210bbec0',
  bankSlug: 'access-bank',
  record: '6082799e5ad7d31243eb6d43',
  login_type: 'bank',
  customerId: '602d7a668299304ef0df55v2',
  extras: {},
  owner: '5d9288ea182d3d000cb7c481'
}
{
    "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"
   },
   "serverResponse":{
      "success":false,
      "error":{
         "message":"The POST method is not supported for this route. Supported methods: GET, HEAD.",
         "id":null
      }
   }
}
{
    "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"
   },
   "serverResponse":{
      "status":"error",
      "message":"Record does not match this user, please use your correct Bearer Token or record does not exist!",
      "data":null
   }

Checking a webhook status

curl -X GET https://api.okra.ng/v2/callback?record={RECORD}&method=METHOD
-H 'Content-Type: application/json' 
-H 'Authorization: Bearer <secretKey>'

Product callbacks/webhooks

The following are the current events that we have for you. As we hook into more actions in the future, we'll add to this list.

ProductMethodsEndpoint
authAUTHGET /v2/callback?record={RECORD ID HERE}&method=AUTH
identityIDENTITYGET /v2/callback?record={RECORD ID HERE}&method=IDENTITY
balanceBALANCE
PERIODIC_BALANCE
GET /v2/callback?record={RECORD ID HERE}&method=BALANCE
incomeINCOMEGET /v2/callback?record={RECORD ID HERE}&method=INCOME
transactionsTRANSACTIONS
PERIODIC_TRANSACTIONS
GET /v2/callback?record={RECORD ID HERE}&method=TRANSACTIONS
paymentPAYMENT
PAYMENT_RECURRING
GET /v2/callback?record={RECORD ID HERE}&method=PAYMENT

Other webhooks

{
"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/>
  }
}

WebHook trigger

Overview

The webhook trigger can come in very handy if you need to get the webhooks associated with a particular record id(s), in scenarios where the server goes down unexpectedly or you want to send webhooks to a different server.

You can use the webhook trigger to check the status of a webhook by supplying their record id(s) as the payload to the webhook trigger endpoint.

The way this works is by, calling this endpoint <https://api.okra.ng/v2/callback/trigger>, and passing the record id or an array of record id(s), or maybe a valid URL you'd like to redirect the webhooks to.

payload = {
     records: ["60b7be20ca7ce542d906e029", "60b7bc9aca7ce542d906e026"] //array of recordIds
     url: "https://yourcompany/webhooks/okra"//callback_url (optional), it default to your saved callback_url
}
{
"status": "success",
"messgae": "webhook trigger successfully initiated",
"data": {}
}

:notebook:   Note that the records array accepts a maximum of 100 record ID's


How to setup Okra JS with webhooks


Webhook logs

The webhook logs on your dashboard, and help track activities on your webhooks, such as successful and failed sessions on what users do on a widget, its search functionality allows you to query customer ID, record ID as well as filter based on date ranges and status.


Search

To monitor the activities on your webhooks, you can use the search feature to query specific keywords, such as code, status, record ID, and customer ID.

Sample webhook responseSample webhook response

Sample webhook response

Date
You can filter your search based on a certain date range on the calendar or choose from the default options, such as Today, Yesterday, Last 7 days, Last 14 days, Last 30 days, This month and Last month.

Date RangeDate Range

Date Range

Status

You can streamline your search to output logs based on failed and successful status.

Select webhook statusSelect webhook status

Select webhook status

Export

For ease of analysis outside of the Okra dashboard, you can export the logs by selecting some or all of the logs, the format of the export(in JSON), and click the "send to mail" button to download it directly from your mail.