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_fieldsobject Optional |
Additional fields to be attached to the transfer. |
customer_referencestring Optional |
Reference generated by merchant |
transaction_narrationstring 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_referencestring | null Optional |
Reference generated by merchant |
custom_fieldsobject | 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.
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 |
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