Error Handling

The Portal APIs use HTTP response status codes to indicate success or failure. When a request to our API is successful, the API returns an HTTP response code in the 2XX range. And when a request fails, the API returns an HTTP response code in the 4XX or 5XX range.

In summary:

  • Codes in the 2XX range mean that the request was processed successfully
  • Codes in the 4XX range mean that something was wrong with the data that you sent. For example, you might have missed some required parameters, or you might be using the wrong API token.
  • Codes in the 5XX range mean that something went wrong within Onafriq's servers.

In all cases, the response will include an appropriate status code and content-type. The body of the response will include any additional details regarding the nature of the error.

Most error responses will include a “detail” key in the body of the response, but some may include additional information, for example, they may include information about missing fields.

The examples to the right show some of the errors that might occur, including the status code and content-type in the response header, and the json-formatted details in the response body.

// 401 unauthorized error response due to a wrong token

HTTP/1.1 401 Unauthorized
Content-Type: application/json
Content-Length: 27

{"detail":"Invalid token."}
// 400 Bad Request error response due to missing parameters in the request. Note that the fields are included as keys, and the error messages for each field are included as a list after each key.

HTTP/1.1 400 Bad Request
Content-Type: application/json
Content-Length: 94

{"amount": ["A valid integer is required."], "description": ["This field may not be blank."]}

Common error codes

Error CodeMeaning
400Bad Request – Your request is malformed or is missing some required parameters.
401Unauthorized – You are using an invalid API token.
403Forbidden – You are attempting to access a resource that doesn’t belong to you. Check that you are using the correct API token for the user who owns the resource.
404Not Found – You are attempting to access a resource that doesn’t exit. Check the url for your request.
405Method Not Allowed – You are attempting to use an invalid method. For example, you might be trying to POST to a readonly endpoint.
406Not Acceptable – You requested a format that isn’t supported. Check the “Accept” header of your request, and try to ensure that you are using JSON format for your requests.
409Conflict – You sent a duplicate request. Check your Duplicate-Check-Key
415Unsupported Media Type – Check the content-type of the data you are sending.
429Throttled – You are sending too many requests in a short period of time. Slow down!
500Internal Server Error – We had a problem with our server. Try again later.
503Service Unavailable – We’re temporarily offline for maintenance. Please try again later.

📘

Note

Always check the response body for details about the error.

Handling errors

Your code should handle errors gracefully.

The API libraries will raise an exception when an error occurs. So you should add exception handling to your requests as shown in the examples below.

<?php
require_once('./lib/Beyonic.php');
Beyonic::setApiKey("ab594c14986612f6167a975e1c369e71edab6901");

try {
  $collection_requests = Beyonic_Collection_Request::getAll();
} catch (Beyonic_Exception $e) {
  echo $e->getMessage();
  print_r(json_decode($e->responseBody));
}
?>
import beyonic
beyonic.api_key = 'ab594c14986612f6167a975e1c369e71edab6901'

try:
  collection_request = beyonic.CollectionRequest.get(23)
except beyonic.errors.ResponseError as e:
  print e
else:
  # No error, proceed with processing
  pass
require 'beyonic'
Beyonic.api_key = 'ab594c14986612f6167a975e1c369e71edab6901'

begin
  collection_request = Beyonic::CollectionRequest.get(23)
rescue RestClient::ExceptionWithResponse => e   # You probably want to use more specific RestClient codes like RestClient::Unauthorized, RestClient::ResourceNotFound, etc
  p e  # Print out the error
end

Duplicate Requests

The API provides a way for you to make sure that duplicate requests do not result in multiple transactions. This allows you to safely retry a request if you’re not sure that it worked the first time.

You do this by adding a “Duplicate-Check-Key” header to your request. The value of this header can be any string value of your choosing. If the API finds a previous request with the same Duplicate-Check-Key, we will reject the new request with a 409 Conflict error.

The response body will include “Duplicate Request Detected!” as part of the error detail message.

Duplicate Check Keys expire after 24 hours, after which a new request is generated if the same key is used.

curl https://api.mfsafrica.com/api -H "Duplicate-Check-Key: ab594c14986612f6167a975e1c369e71edab6900"
package com.beyonic.examples.payments;
import com.beyonic.models.Payment;

// Payments with duplicate key check
HashMap<String, Object> paymentCreate = new HashMap<>();
paymentCreate.put("phonenumber", "+80000000001");
paymentCreate.put("first_name", "Kennedy");
paymentCreate.put("last_name", "Amani");
paymentCreate.put("currency", "BXC");
paymentCreate.put("amount", "30");
paymentCreate.put("description", "Per diem payment");
paymentCreate.put("payment_type", "money");

// Pass unique duplicate key as the third parameter, unique per payment
response = new Payment().create(paymentCreate, null, "duplicate.check.key");
System.out.println(response);
<?php
require_once('./lib/Beyonic.php');
Beyonic::setApiKey("ab594c14986612f6167a975e1c369e71edab6900");

$payment = Beyonic_Payment::create(array(
  "phonenumber" => "+80000000001",
  "first_name" => "Kennedy",
  "last_name" => "Kennedy",
  "amount" => "100.2",
  "currency" => "BXC",
  "description" => "Per diem payment",
  "payment_type" => "money",
  "callback_url" => "https://my.website/payments/callback",
  "metadata" => array("id"=>"1234", "name"=>"Lucy")
), array("Duplicate-Check-Key": "ab594c14986612f6167a"));

print_r($payment);  // Examine the returned object
?>
import beyonic
beyonic.api_key = 'ab594c14986612f6167a975e1c369e71edab6900'

payment = beyonic.Payment.create(phonenumber='+80000000001',
                       first_name='Kennedy',
                       last_name='Amani',
                       amount='1200',
                       currency='BXC',
                       description='Per diem',
                       callback_url='https://my.website/payments/callback',
                       metadata={'id': '1234', 'name': 'Lucy'},
                       duplicate_check_key="ab594c14986612f6167a"
                       )

print payment  # Examine the returned object
require 'beyonic'
Beyonic.api_key = 'ab594c14986612f6167a975e1c369e71edab6900'

payment = Beyonic::Payment.create({
    phonenumber: "+80000000001",
    first_name: "Kennedy",
    last_name: "Amani",
    amount: "100.2",
    currency: "BXC",
    description: "Per diem payment",
    payment_type: "money",
    callback_url: "https://my.website/payments/callback",
    metadata: {id: "1234", name: "Lucy"}
}, {"Duplicate-Check-Key"=>"ab594c14986612f6167a"})

Throttling

Requests to the Portal APIs are throttled. If you send too many requests too fast, you will receive a throttling error resulting in a response with the HTTP status code “429 Too Many Requests”.

API READ requests are limited to 30/minute.

API WRITE requests are limited to 3000/minute.