Optimus

Overview

Carbon Optimus provides you APIs for performing common transactions such as Transfers, Airtime Purchases and Bill Payments. The Optimus API is organized around REST. The APIs generally accept JSON-encoded request bodies and returns JSON-encoded responses, while using standard HTTP response codes and Verbs.

You can use our Test environment for test/integration purposes. Optimus has different URLs for Test and Live environments.

Authentication

Carbon Optimus uses Merchant ID and API Keys to authenticate requests. You can view your Merchant ID and API Key from your Carbon Optimus Dashboard -> Profile -> ApiKeys. Please be sure to keep your keys secure! Do not share your secret API keys in publicly accessible areas such as Git Providers, client-side code, etc.

The API Authenticates using HMAC. Provide your Merchant ID as the username and your API key as a key for HMAC-SHA256 encryption of the HMAC Signing String. You can find sample implementations below for creating a HMAC Authorization Header for our APIs.

                  
          // Or any other http client library
          const axios = require('axios');
          const moment = require('moment');
          const cryptojs = require('crypto-js');
          
          const baseUrl = `https://optimus-staging.getcarbon.co`;
          const merchantId = 'YOUR_MERCHANT_ID';
          const apiKey = 'YOUR_API_KEY';
          

          async function makeOptimusTransferApiRequest (requestObject) {

            // If Request doesnt require a body e.g GET Requests
            // then requestRawBody = "";

            const requestRawBody = JSON.stringify(requestObject);
            // Format Sun, 25 Mar 2019 10:21:49 GMT
            let dateHeaderValue = moment().utcOffset('+0000')
                .format('ddd, DD MMM YYYY HH:mm:ss G\\MT');

            let bodyDigest = cryptojs.SHA256(requestRawBody)
                .toString(cryptojs.enc.Base64);
            let digestHeaderValue = `SHA-256=${bodyDigest}`

            // `${REQUEST_METHOD} ${REQUEST_PATH} HTTP/1.1`
            let requestLine = `POST /api/v2/transfers/sendmoney HTTP/1.1`;

            let signingString = [
                `date: ${dateHeaderValue}`,
                `digest: ${digestHeaderValue}`,
                `host: ${url.parse(baseUrl).hostname}`,
                requestLine
              ].join('\n');

            let signature = cryptojs.HmacSHA256(signingString, apiKey)
                .toString(cryptojs.enc.Base64);

            let hMACAuth = `hmac ${merchantId}:${signature}`;

            const headers = {
              'Accept': 'application/json',
              'Content-Type': 'application/json',
              'Date': dateHeaderValue,
              'Digest': digestHeaderValue,
              'Authorization': hMACAuth
            };

            const transferUrl = baseUrl + "/api/v2/transfers/sendmoney";
            return axios.post(transferUrl, requestObject, { headers });
          }
                  
                
              
      class OptimusClient {

        private $merchantId;
        private $apiKey;
        private $baseUrl;
        private $guzzleClient;
    
        public function __construct($merchantId, $apiKey, $baseUrl)
        {
            $this->merchantId = $merchantId; // YOUR_MERCHANT_ID
            $this->apiKey = $apiKey; // YOUR_API_KEY

            // https://optimus-staging.getcarbon.co
            $this->baseUrl = $baseUrl;

            // OR ANY OTHER HTTP CLIENT
            $this->guzzleClient = new GuzzleHttp\Client();
        }
    
    
        public function makeOptimusTransferApiRequest ($requestObject = []) {
            try {
                /**
                  * If Request doesnt require a body e.g GET Request then requestRawBody = "";
                  */
                $requestRawBody = json_encode($requestObject);
                $dateObject = new DateTime("now", new DateTimeZone('UTC'));
    
                // Format Sun, 25 Mar 2019 10:21:49 GMT
                $dateHeaderValue = date_format($dateObject,'D, d M Y H:i:s \G\M\T');
    
                $bodyDigest = hash("sha256", $requestRawBody);
                $digestHeaderValue = 'SHA-256='.$bodyDigest;
    
                // `${REQUEST_METHOD} ${REQUEST_PATH} HTTP/1.1`
                $requestLine = "POST /api/v2/transfers/sendmoney HTTP/1.1";
                          
                $signingString = join("/n", [
                    "date: $dateHeaderValue",
                    "digest: $digestHeaderValue",
                    "host: $this->baseUrl",
                    $requestLine
                ]);
    
                $signature = hash_hmac("sha256", $signingString, $this->apiKey);
                $hMACAuth = 'hmac '.$this->merchantId.':'.$signature;
    
                $response = $this->guzzleClient->post($this->baseUrl.'/api/v2/transfers/sendmoney', [
                    'headers' => [
                        'Date' =>  $dateHeaderValue,
                        'Digest' => $digestHeaderValue,
                        'Authorization'=> $hMACAuth
                    ],
                    'json' => $requestObject
                ]);
                return $response->getBody();
    
            } catch (\Exception $e) {
                /**
                  * Handle Exception
                  */
            }
        }
      }
              
            
                
        package co.getcarbon.optimus.internal.client;
        // Imports skipped for Brevity

        public class OptimusApiGateway {

          private String merchantId;
      
          private String apiKey;
      
          private String hostName;
      
          public OptimusApiGateway(String merchantId, String apiKey) {
              this.merchantId = merchantId;
              this.apiKey = apiKey;
              hostName = "https://optimus-staging.getcarbon.co";
          }
      
          public Object doSingleTransfer (Object transferRequest) throws Exception{
      
              try {
                  Gson gson = new Gson();
      
                  /**
                    * Convert Object to JSON String
                    * For requests do not require a body e.g GET requests, rawRequestBody should be "" (empty string)
                    */
                  String rawRequestBody = gson.toJson(transferRequest);
      
                  DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("E, dd MMM yyyy HH:mm:ss");
                  ZoneOffset zoneOffSet = ZoneOffset.of("+00:00");
                  String dateHeaderValue = dateTimeFormatter.format(LocalDateTime.now(zoneOffSet)) + " GMT";

                  String bodyDigest = Base64.getEncoder().encodeToString(DigestUtils.sha256(rawRequestBody));
                  String digestHeaderValue = "SHA-256=" + bodyDigest;
      
                  /**
                    * `${REQUEST_METHOD} ${REQUEST_PATH} HTTP/1.1`;
                    */
                  String transferEndpoint = "/api/v2/transfers/sendmoney";
                  String requestLine = String.format("POST %s HTTP/1.1", transferEndpoint);
                  String signingString = String.join(
                          "\n",
                          Arrays.asList(
                              "date: " + dateHeaderValue,
                              "digest: " + digestHeaderValue,
                              "host: optimus-staging.getcarbon.co",
                              requestLine
                          )
                  );
      
                  /**
                    * Do HMAC Encoding
                    */
                  Mac sha256 = Mac.getInstance("HmacSHA256");
                  SecretKeySpec secretKeySpec = new SecretKeySpec(apiKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
                  sha256.init(secretKeySpec);
      
                  String signature = Base64.getEncoder().encodeToString(sha256.doFinal(signingString.getBytes(StandardCharsets.UTF_8)));
      
                  /**
                    * Generate HMAC Authorization String
                    */
                  String hMACAuth = String.format("hmac %s:%s", merchantId, signature);

                  RestTemplate restTemplate = new RestTemplate();
      
                  HttpHeaders httpHeaders = new HttpHeaders();
                  httpHeaders.set("Accept", "application/json");
                  httpHeaders.set("Content-Type", "application/json");
                  httpHeaders.set("Date", dateHeaderValue);
                  httpHeaders.set("Digest", digestHeaderValue);
                  httpHeaders.set("Authorization", hMACAuth);
      
                  HttpEntity<Object> httpEntity = new HttpEntity<>(transferRequest, httpHeaders);
                  ResponseEntity<String> responseJson = restTemplate.exchange(hostName + transferEndpoint, HttpMethod.POST, httpEntity, String.class);
                  return gson.fromJson(responseJson.getBody(), Object.class);
              } catch (Exception e){
                  // Handle Exception
                  throw new Exception("Unknown Error");
              }
          }
      }
                
              

Errors

Standard HTTP response codes are used to indicate the success or failure of an API request. Codes in the 2xx range indicate success. Codes in the 4xx range indicate an error that failed with a descriptive message (e.g. A required parameter was missing, authentication errors, etc.). Codes in the 5xx range indicate an error with the Optimus's servers.

HTTP Code Summary
200 - OK Everything worked as expected
400 - Bad Request The request was not accepted due to missing required parameters or malformed requests
401 - Unauthorized Invalid key provided or malformed authorization header
403 - Forbidden No permission to perform request
404 - Not found Requested resource was not found
500 - Service Error Something went wrong on Optimus end

Banks Lookup

Returns a list of Nigerian Banks with their sort codes. The sort codes are important for specifying destination bank when making a request on the single transfer API

Endpoint GET https://optimus.getcarbon.co/api/v2/transfers/banks

Returns: An array of Bank objects

The Bank Object
name
string
The name of the Bank
sortCode
string
Designated CBN Sort Code
            
    [
        {
            "sortCode": "044",
            "name": "Access Bank"
        },
        ...
    ]
                
          

Account Lookup

Attempts to do an Account Name Enquiry on an Account number of a selected bank.

Endpoint POST https://optimus.getcarbon.co/api/v2/transfers/lookup

Request:

Lookup Request Object
bankcode
string
Sort code of Bank used for lookup (retrieved from Bank lookup)
accountnumber
string
10 digit NUBAN
              
    // Sample Request
    {
        "bankcode":"058",
        "accountnumber":"0123456789"
    }
              
            

Returns: Lookup object

The Lookup Object
bank_code
string
Sort code of Bank used for lookup
account_number
string
Account Number used for lookup
account_name
string
Account Name retrieved from operation
bank_name
string
Name of Bank with specified sort code
                  
    // Sample Response
    {
        "bank_code": "058",
        "account_number": "0127909008",
        "account_name": "AREGBESOLA, SUNDAY CIROMA",
        "bank_name": "GT Bank",
        "display_name": "AREGBESOLA, SUNDAY CIROMA (0127909008)"
    }
                    
                

Single Transfer

Transfer funds to a Bank Account.

Endpoint POST https://optimus.getcarbon.co/api/v2/transfers/sendmoney

Request

Make Transfer Request
transaction_amount
number
Amount to transfer in Minor currency (kobo)
beneficiary_account_number
string
Account number to transfer to
beneficiary_bank_code
string
Bank code of destination bank
custom_fields
object Optional
Additional fields to be attached to the transfer.
customer_reference
string Optional
Reference generated by merchant
transaction_narration
string Optional
Optional Description of Transfer
                      
      // Sample Request
      {
        "transaction_amount":10000,
        "beneficiary_account_number":"0127909008",
        "beneficiary_bank_code":"058",
        "custom_fields":{
          "invoice":"2332211223",
          "description": "Payment for 3 API Shoes"
        },
        "customer_reference":"32334",
        "transaction_narration": "Transfers for 3 API Shoes"
      }
                      
                    

Returns: Transfer object

The Transfer Object
status
string
Status of the transaction. Can be SUCCESS, FAILED or PROCESSING
statusMessage
string
Descriptive text of transfer status
reference
string
Optimus reference for the transfer
beneficiary
object
Details of Transfer Beneficiary
transaction
object
Details of Transfer
customer_reference
string | null Optional
Reference generated by merchant
custom_fields
object | null Optional
Additional fields to attached to the transfer.
                          
    // Sample Response
    {
      "status": "SUCCESS",
      "statusMessage": "Successful Transaction",
      "reference": "OPT9467221697521458",
      "customerReference": "32334",
      "beneficiary": {
          "accountNumber": "0127909008",
          "accountName": "AREGBESOLA, SUNDAY JAMES",
          "bankCode": "058",
          "bankName": "GT Bank"
      },
      "transaction": {
          "amount": 10000,
          "serviceFee": 2000,
          "totalAmount": 12000,
          "currency": "NGN",
          "narration": "Carbon For Agents"
      },
      "custom_fields": {
        "invoice":"2332211223",
        "description": "Payment for 3 API Shoes"
      },
      "date": "2019-08-26T09:23:03.189Z"
    }
                          
                        

Requery Transfer

Query an existing transfer record by reference.

Endpoint GET https://optimus.getcarbon.co/api/v2/transfers/:reference/query

Arguments: reference - string

Returns: Transfer object - (Same as above)

Airtime Topup

Endpoint POST https://optimus.getcarbon.co/api/v2/airtime/topup

Request

Make Transfer Request
topup_amount
number
Amount to topup in minor currency (kobo)
topup_phone_number
string
Phone number to Topup
topup_network_id
string
Network ID of phone number
                      
      // Sample Request
      {
        "topup_amount":50000,
        "topup_phone_number":"07060931569",
        "topup_network_id":"mtn"
      }
                      
                    

Returns: Topup object

The Transfer Object
status
string
Status of the topup. Can be SUCCESS, FAILED or PROCESSING
statusMessage
string
Descriptive text of transfer status
reference
string
Optimus reference for the transfer
transaction
object
Transactions Details of Airtime Topup
                        
        //Sample Response
        {
          "status": "SUCCESS",
          "statusMessage": "Successful Transaction",
          "reference": "OPT1608063549936751",
          "transaction": {
              "amount": 50000,
              "serviceFee": 0,
              "totalAmount": 50000,
              "currency": "NGN"
          }
        }
                        
                      

Fetch Wallet

Returns your Carbon Wallet information

Endpoint GET https://optimus.getcarbon.co/api/v2/wallet

Returns: Wallet object

The Wallet Object
walletId
string
Your unique Carbon Wallet ID
balance
number
Wallet Balance minor currency (kobo)
businessName
string
Registered name of Merchant's Business
                  
  // Sample Response
  {
    "walletId": "4414621088",
    "balance": 984601640,
    "businessName": "Carbon For Agents"
  }
                  
                

Identity Verification

Overview

With the CarbonIVS APIs, you can automate your identity verification flow, verify your KYC backlog to meet compliance obligations and plug identity verification right into your onboarding flow.

With the API, you can verify the identity of an individual from the following sources.

  • BVN
  • Intl Passport
  • Voters ID
  • Drivers License
  • National ID
  • NIMC Slip and
  • Tax Identification Number
  • Corporate Affairs Commission Reg No
  • Credit Reports (FREE)

All verification via the API is reported on your dashboard in real time. All requests to the API should be AES encrypted using your API key.

Get your API keys

Verify

All verification requests are made to the CarbonIVS API url below

Endpoint POST https://carbonivs.co/api/verify

Content Type: application/json

Returns: Responses containing encrypted data key

Verification Payload
identification_type
string
Type of verification. Can be bvn, driverlicence, passport, voterid, nationalid
, nimcslip, cac, tin

If you are verifying bvn, tin or cac
then only the identification_number is required.

identification_number
string
ID Number of selected type
identification_name
string
Full Name on Identity Card
identification_dob
string
Date of birth on Identity Card (format YYYY-MM-DD)
Verification Request Object
key
string
Your Merchant ID
data
string
Encrypted Verification Payload

The payload is AES encrypted using your API key from the dashboard.
                    
        // Sample Payload to encrypt
        {
            "identification_type": "type",
            "identification_number": "A12345678",
            "identification_name": "Lekan David",
            "identification_dob": "1960-09-01"
        }
                    
                  

                    
        // Sample Final request to API
        {
            "key": "b8778-908475-99482-gr8e7w",
            "data": "U2FsdGVkX1+LiseL2jnSLu2msLpAZJISqn4DhiH906woLeu
                    cFqffL8Bq1PsovSZtb6LNoxsLFlRG2t3Rpdrqn+Zid0ZG/ZQ
                    XLXtggNmTLpC+0qK18WMPPhHCfmSxZUbbNNYjhUwxcvF07h7
                    +/Dt44/sbrJCdmd9iYfQAj6kuzSKQhjVKXYeg8Ib5t/M3kvC
                    TWaR2Uz8Wt7RkNYS0+YIb3nklDj9UMYcnUGWpsnKtjcSHa2S
                    RALeqduvFpymCVluMmydPnhsKn/wmF7YuT62PdqU7GwPLhy5
                    DW0azq4RuM3Q="
        }
                    
                
Verification Response
data
string
Encrypted Verification result to be AES decrypted using your API key from the dashboard.

Credit Reports

Get latest credit reports history from various credit bureaus

Credit Report Verification Payload
identification_type
string
Type of verification.Must be set to credit
identification_first_name
string
First name of applicant
identification_last_name
string
Last name of applicant
identification_middle_name
string Optional
Middle name of applicant
identification_bvn
string
11 digit BVN of applicant
identification_dob
string
Date of birth on Identity Card (format YYYY-MM-DD)
identification_phone_numbers
string[]
Phone numbers of applicant, at least one must be provided
Verification Response
data
string
Encrypted Verification result to be AES decrypted using your API key from the dashboard.
                        
        // Sample Payload to encrypt
        {
            "identification_type": "credit"
            "identification_first_name": "Lekan",
            "identification_last_name": "David",
            "identification_middle_name": "",
            "identification_bvn": "12345678901",
            "identification_dob": "1956-04-08",
            "identification_phone_numbers": ["0803xxxxxxx", "0908xxxxxxx"]
        }
                        
                      

                        
        // Sample Final request to API
        {
            "key": "b8778-908475-99482-gr8e7w",
            "data": "U2FsdGVkX1+LiseL2jnSLu2msLpAZJISqn4DhiH906woLeu
                    cFqffL8Bq1PsovSZtb6LNoxsLFlRG2t3Rpdrqn+Zid0ZG/ZQ
                    XLXtggNmTLpC+0qK18WMPPhHCfmSxZUbbNNYjhUwxcvF07h7
                    +/Dt44/sbrJCdmd9iYfQAj6kuzSKQhjVKXYeg8Ib5t/M3kvC
                    TWaR2Uz8Wt7RkNYS0+YIb3nklDj9UMYcnUGWpsnKtjcSHa2S
                    RALeqduvFpymCVluMmydPnhsKn/wmF7YuT62PdqU7GwPLhy5
                    DW0azq4RuM3Q="
        }
                        
                    

Bank Statements

Overview

Our Bank Statements lets you request and retrieve Bank Statements of an individual. THe statements are retrieved from the banks and eliminate the need for requesting the indivudual to downloand, print and send to you. Coming soon...


Business Loans

Overview

Coming soon


Online Payments

Overview

Coming Soon