{"activeVersionTag":"latest","latestAvailableVersionTag":"latest","collection":{"info":{"_postman_id":"bc6887b7-b4bc-4790-8051-48635f1238b9","name":"Vulte - Documentation","description":"# Banking as a Service\n\nOur vision is to collaboratively provide the underlying banking services infrastructure to fintechs and innovators in order to deliver best in class user experiences and target the next generation bank customers.\n\nThis suite of APIs provides access to an array of payment-related, enquiry & KYC lookup services. Vulte wraps around them an abstraction layer with one major goal: To provide a consistent interface to integrators regardless of underlying service provider. That way, you can switch between providers at any time, based on quality of service, business justification, etc. without starting a new integration project or changing your systems in any way.\n\n# Want to try it quickly?\n\nTo get started, sign up for Vulte by visiting [https://openbanking.vulte.ng](https://openbanking.vulte.ng). Once your account has been approved, you will receive an invite email to set your password.\n\n1. Set up your password\n2. Login with newly set password\n3. Generate your **API key** and **secret**\n    \n\n# Index of services\n\nHere's the list of services available at the moment. It's a list that will grow with time as we complete more integrations.\n\n## Lookup BVN Min\n\nWith this service, the calling apps can KYC a customer's bank verification number. This service will only return a True/False match of the supplied customer details if it matches what is saved against their BVN correctly.\n\n## Lookup BVN Mid\n\nWith this service, the calling apps can do KYC with the customer's bvn. This service will return slightly above minimal KYC information.\n\n## Lookup BVN Max\n\nWith this service, the calling apps can do KYC with the customer's bvn. This service will return maximum KYC information.\n\n## Lookup Account Min\n\nWith this service, the calling apps can KYC a customer's account numbe. This service will only return minimal KYC information.\n\n## Lookup Account Mid\n\nWith this service, the calling apps can do KYC with the customer's account number. This service will return slightly above minimal KYC information.\n\n## Lookup Account Max\n\nWith this service, the calling apps can do KYC with the customer's account number. This service will return maximum KYC information.\n\n## Get Statement\n\nWith this service, the calling apps can get statements of accounts. Apps will forward the customer reference account number they will like to obtain information on and forward to Vulte.\n\n## Get Balance\n\nWith this service, the calling apps can get available balance for a given source.\n\n## Collect\n\nWith this service, the calling app can request or initiate payment from a customer. Provide a customer’s bank account number, Vulte forwards to selected provider, provider debits the linked account and credits beneficiary account tied to the app. The underlying provider may prompt for OTP, therefore you’d supply the OTP via a follow-on call.\n\n## Transfer Funds\n\nWith this service, the calling apps can do a transfer to a destination account number from a given source. Authorisation details (for source of funds) will always be required by the Vulte, apps will have to provide this.\n\n## Disburse\n\nWith this service, the calling apps can do a transfer to a destination account number from a pre-configured account of the app. If authorisation details are required by a provider, apps will have to provide this.\n\n## Lookup NUBAN\n\nWith this service, the calling apps can check corresponding banks matched to a customer's account number. In effect, take an account number and try to determine which bank it’s from.\n\n## Get Accounts Min\n\nWith this service, the calling apps can take customer ref and return a masked list of accounts linked to it. Apps will collect the customer ref they will like to obtain information on and forward to Vulte.\n\n## Get Accounts Mid\n\nWith this service, the calling apps can take customer ref and return an unmasked list of accounts linked to it. Apps will collect the customer ref they will like to obtain information on and forward to Vulte.\n\n## Get Banks\n\nWith this service, the calling apps can get list of financial institutions with their corresponding codes.\n\n## List Branches\n\nList branches of Polaris Bank\n\n# Getting access to the APIs\n\nTo get started, sign up for Vulte by visiting [https://openbanking.vulte.ng](https://openbanking.vulte.ng). Once your account has been approved, you will receive an invite email to set your password.\n\n1. Set up your password\n2. Login with newly set password\n3. Generate your **API key** and **secret**\n    \n\n# General API information\n\nThe APIs are fairly RESTFUL and organized around the main services you would be interacting with. You can simply import this collection from the top right of the page into your **Postman**.\n\nThe base url currently sits at:\n\n```\nhttps://api.openbanking.vulte.ng\n\n ```\n\n# Authentication headers\n\nAuthenticate your API calls by including your API key in the Authorization header of every request you make. You can manage your API keys from your dashboard.\n\n_**Sample Authorization Header:**_\n\n```\nAuthorization: Bearer {api_key}\n\n ```\n\nAlso, every request requires you to provide a unique `request-ref` per call. Then You'd need to add a custom header called `Signature` that's an MD5 hash of that `request-ref` and your `api-secret` separated by a semi-colon. `;`.\n\n_**Sample Signature Header:**_\n\n```\nSignature:MD5Hash(request_ref;client_secret)\n\n ```\n\nYour complete header for evey single call will look like:\n\n```\nContent-Type:application/json\nAuthorization:Bearer {{api_key}}\nSignature:{{MD5Hash(request_ref;client_secret)}}\n\n ```\n\n# What requests would look like\n\nFor all requests, you'd put a JSON object in the body of your API call. All payloads have the following high level construct:\n\n``` json\n    {\n      \"request_ref\":\"0000000001\",\n      \"request_type\":\"lookup_bvn_max | get_statement |etc\",\n      \"auth\": {\n        \"type\": \"bvn | bank.account\", \n        \"secure\": \"YKBOxtdD8kZHqG7JO0C9TZ\",\n        \"auth_provider\": \"Polaris\"\n      },\n      \"transaction\": {\n        \"amount\": 10000,\n        \"transaction_ref\": \"000001\",\n        \"transaction_desc\": \"A random transaction\",\n        \"transaction_ref-parent\": \"000001\",\n        \"customer\":{\n            \"customer_ref\": \"000001\",\n            \"firstname\": \"Kola\",\n              \"surname\": \"Eboe\",\n            \"email\": \"kolaebue@gmail.com\",\n            \"mobile_no\": \"2348009871412\"\n        },\n        \"meta\":{\n            \"a_key\":\"a_meta_value_1\",\n            \"b_key\":\"a_meta_value_2\"\n        },\n        \"details\": {\n            \"key\": 'value'\n        }\n      }\n    }\n\n ```\n\n# What responses would look like\n\nFor all responses, you'd get a JSON object in the body of the response you receive. All payloads have the following high level construct:\n\n``` json\n    {\n        \"status\": \"Processing | WaitingForOTP | ProcessingOTP | Successful | Failed | OfflineValidating | OfflineValidated | OfflineNotifying | OfflineNotified\",\n        \"message\": \"The transaction has been processed successully\",\n        \"data\": {\n            \"provider_responde_code\":\"00\",\n            \"provider\": \"Polaris\",\n            \"errors\": [],\n            \"error\": null,\n            \"charge_token\": \"Kz5Dev7BenV9HmLNB\",\n            \"paymentoptions\": []\n        }\n    }\n\n ```\n\n- **status**: Indicates the state of the request, whether successful, failed or anything in between\n- **message**: Provides a text description of the state of the request and at times a message for the customer\n- **data**: Will contain much more details of the outcome of the request. The values within this could vary by request type or endpoint called but some standard elements would be in almost all calls\n- **provider_response_code**: The actual response code receieved from the underlyig provider, e.g. `00` for Quickteller\n- **provider**: The provider that was used to process the request\n- **errors**: In case of a failed transaction, this contains the lists of errors that occurred while processing the transaction\n- **error**: This contain the most important error that hinders the successful completion of the transaction.  \n    We highly recommend that developers use the Errors field to determine the result of an API call. As an empty Errors node indicate a successful transaction.\n    \n\n**NOTE**: Some API calls may have response elements that are only applicable to those API calls. You will see examples in the provided postman collection and across the documentation.\n\n# Vulte standard status codes\n\n- **Successful**: For all requests that were successfully processed\n- **Failed**: If a request fails. Read the errors object(s)\n- **WaitingForOTP**: If a request requires OTP validation for completion.\n- **PendingValidation**: If a request requires other information to be supplied for completion.\n- **Processing**: If a transaction request is still in a processing state and needs to be subsequently queried.\n- **OptionsDelivered**: Applicable only for services that support some form of options processing.\n- **InvalidID**: If an ID being looked up by service is not valid.\n- **Fraud**: If a request is flagged as suspicious.\n- **Duplicate**: If a similar request has been made earlier within a stipulated time frame of 5 minutes.\n- **\\[Anything else\\]**: This would vary per endpoint called. Applicable values would be in the documentation for that endpoint.\n    \n\n# HTTP Status Codes\n\n- **200**: A successful request occurred, do note that the description field on the response can contain further steps to be carried on this transaction\n- **400**: Data validation error occurred due to inconsistent data supplied by the client\n- **401**: Invalid request authorization, which might be due to invalid API key or the client is not registered for the service being accessed.\n- **500**: An internal server error at our End, this should be reported if it persists.\n    \n\n# Encryption of Secure element\n\n**NOTE** Please note that the underlying encryption behind the core Vulte communication is based on the AES algorithm. This section only shows encryption details for some parameters on the merchant request payload.\n\nFor encryption of values for the `auth.secure` field, do use Triple DES Encryption Algorithm with your application secret key as the encryption key\n\nE.g.\n\n```\nTripleDES.encrypt(\"{bvn}\",secretKey)\nTripleDES.encrypt(\"{bank_account;bank_code}\",secretKey)\nTripleDES.encrypt(\"{otp}\",secretKey)\nTripleDES.encrypt(\"card.Pan;card.Cvv;card.Expdate;card.Pin\",secretKey)\n\n ```\n\n**NOTE For DCIR:**\n\nCVV is not required for Card-Present transactions, the cvv position should be left empty.\n\n```\nTripleDES.encrypt(\"card.Pan;card.Cvv;card.Expdate;card.Pin\",secretKey) => Card-Not-Present\nTripleDES.encrypt(\"card.Pan;;card.Expdate;card.Pinblock\",secretKey) => Card-Present\n\n ```\n\n**NOTE** Expiry date is YYMM\n\n## Sample encryption in Java\n\n```\nMessageDigest md = MessageDigest.getInstance(\"md5\");\nbyte[] digestOfPassword = md.digest(key.getBytes(\"UTF-16LE\"));\nbyte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);\nfor (int j = 0, k = 16; j < 8;) {\n    keyBytes[k++] = keyBytes[j++];\n}\nSecretKey secretKey = new SecretKeySpec(keyBytes, 0, 24, \"DESede\");\nIvParameterSpec iv = new IvParameterSpec(new byte[8]);\nCipher cipher = Cipher.getInstance(\"DESede/CBC/PKCS5Padding\");\ncipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);\nbyte[] plainTextBytes = toBeEncrypted.getBytes(\"UTF-16LE\");\nbyte[] cipherText = cipher.doFinal(plainTextBytes);\nString output = new String(Base64.encodeBase64(cipherText));\nreturn output;\n\n ```\n\n## Sample encryption in C-Sharp\n\n```\nstring encryptedText = \"\";\nMD5 md5 = new MD5CryptoServiceProvider();\nTripleDES des = new TripleDESCryptoServiceProvider();\ndes.KeySize = 128;\ndes.Mode = CipherMode.CBC;\ndes.Padding = PaddingMode.PKCS7;\nbyte[] md5Bytes = md5.ComputeHash(Encoding.Unicode.GetBytes(key));\nbyte[] ivBytes = new byte[8];\ndes.Key = md5Bytes;\ndes.IV = ivBytes;\nbyte[] clearBytes = Encoding.Unicode.GetBytes(TextToEncrypt);\nICryptoTransform ct = des.CreateEncryptor();\nusing (MemoryStream ms = new MemoryStream())\n{\n    using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))\n    {\n        cs.Write(clearBytes, 0, clearBytes.Length);\n        cs.Close();\n    }\n    encryptedText = Convert.ToBase64String(ms.ToArray());\n}\nreturn encryptedText;\n\n ```\n\n## Sample encryption in PHP\n\n```\nfunction EncryptV2($encryption_key,$data)\n{\n    $source = mb_convert_encoding($encryption_key, 'UTF-16LE', 'UTF-8');\n    $key = md5($source, true);\n    $key .= substr($key, 0, 8);\n     // a 128 bit (16 byte) key\n     // append the first 8 bytes onto the end\n    //Pad for PKCS7\n    $block = mcrypt_get_block_size('tripledes', 'cbc');\n    $len = strlen($data);\n    $padding = $block - ($len % $block);\n    $data .= str_repeat(chr($padding),$padding);\n    $iv =  \"\\0\\0\\0\\0\\0\\0\\0\\0\";\n    $encData = mcrypt_encrypt('tripledes', $key, $data, 'cbc',$iv);\n    echo base64_encode($encData);\n}\n\n ```\n\n## Sample encryption in Node.js\n\n```\nconst crypto = require('crypto');\nfunction encrypt(sharedKey, plainText) {\n    const bufferedKey = Buffer.from(sharedKey, 'utf16le');\n    const key = crypto.createHash('md5').update(bufferedKey).digest();\n    const newKey = Buffer.concat([key, key.slice(0, 8)]);\n    const IV = Buffer.alloc(8, '\\0');\n    const cipher = crypto.createCipheriv('des-ede3-cbc', newKey, IV).setAutoPadding(true);\n    return cipher.update(plainText, 'utf8', 'base64') + cipher.final('base64');\n}\n\n ```\n\n# Switching providers for a service\n\nAll services subscribed to in your application are attached to providers that will end up fulfilling such service(s) on request. You can switch providers as you wish by managing the application from your dashboard and editing the service details. Also, for some endpoints, you can explicitly set the provider you would like to be used in the request payload. You would see examples in the documentation for the endpoints that support this.\n\n# Bank CBN Codes\n\nAnywhere bank codes are required in the API specification (bank_code), this refers to the CBN bank codes. Details of all bank codes can be found [here](https://bank.codes/api-nigeria-nuban/).\n\nNow let's dive deeper into specific API calls.","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","isPublicCollection":true,"owner":"6358444","team":242895,"collectionId":"bc6887b7-b4bc-4790-8051-48635f1238b9","publishedId":"SzS4R7Jv","public":true,"publicUrl":"https://docs.openbanking.vulte.ng","privateUrl":"https://go.postman.co/documentation/6358444-bc6887b7-b4bc-4790-8051-48635f1238b9","customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"EF5B25"},"documentationLayout":"classic-double-column","customisation":null,"version":"8.10.1","publishDate":"2021-05-14T11:10:29.000Z","activeVersionTag":"latest","documentationTheme":"light","metaTags":{},"logos":{}},"statusCode":200},"environments":[],"user":{"authenticated":false,"permissions":{"publish":false}},"run":{"button":{"js":"https://run.pstmn.io/button.js","css":"https://run.pstmn.io/button.css"}},"web":"https://www.getpostman.com/","team":{"logo":"https://res.cloudinary.com/postman/image/upload/t_team_logo_pubdoc/v1/team/a27a425324c006dd1f53f07becf2d5c16478567dd1dde25001728b716c749aa8","favicon":"https://res.cloudinary.com/postman/image/upload/v1547191824/team/zjhn0lwn04wuxbe90rhq.ico"},"isEnvFetchError":false,"languages":"[{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"HttpClient\"},{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"RestSharp\"},{\"key\":\"curl\",\"label\":\"cURL\",\"variant\":\"cURL\"},{\"key\":\"dart\",\"label\":\"Dart\",\"variant\":\"http\"},{\"key\":\"go\",\"label\":\"Go\",\"variant\":\"Native\"},{\"key\":\"http\",\"label\":\"HTTP\",\"variant\":\"HTTP\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"OkHttp\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"Unirest\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"Fetch\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"jQuery\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"XHR\"},{\"key\":\"c\",\"label\":\"C\",\"variant\":\"libcurl\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Axios\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Native\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Request\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Unirest\"},{\"key\":\"objective-c\",\"label\":\"Objective-C\",\"variant\":\"NSURLSession\"},{\"key\":\"ocaml\",\"label\":\"OCaml\",\"variant\":\"Cohttp\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"cURL\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"Guzzle\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"HTTP_Request2\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"pecl_http\"},{\"key\":\"powershell\",\"label\":\"PowerShell\",\"variant\":\"RestMethod\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"http.client\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"Requests\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"httr\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"RCurl\"},{\"key\":\"ruby\",\"label\":\"Ruby\",\"variant\":\"Net::HTTP\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"Httpie\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"wget\"},{\"key\":\"swift\",\"label\":\"Swift\",\"variant\":\"URLSession\"}]","languageSettings":[{"key":"csharp","label":"C#","variant":"HttpClient"},{"key":"csharp","label":"C#","variant":"RestSharp"},{"key":"curl","label":"cURL","variant":"cURL"},{"key":"dart","label":"Dart","variant":"http"},{"key":"go","label":"Go","variant":"Native"},{"key":"http","label":"HTTP","variant":"HTTP"},{"key":"java","label":"Java","variant":"OkHttp"},{"key":"java","label":"Java","variant":"Unirest"},{"key":"javascript","label":"JavaScript","variant":"Fetch"},{"key":"javascript","label":"JavaScript","variant":"jQuery"},{"key":"javascript","label":"JavaScript","variant":"XHR"},{"key":"c","label":"C","variant":"libcurl"},{"key":"nodejs","label":"NodeJs","variant":"Axios"},{"key":"nodejs","label":"NodeJs","variant":"Native"},{"key":"nodejs","label":"NodeJs","variant":"Request"},{"key":"nodejs","label":"NodeJs","variant":"Unirest"},{"key":"objective-c","label":"Objective-C","variant":"NSURLSession"},{"key":"ocaml","label":"OCaml","variant":"Cohttp"},{"key":"php","label":"PHP","variant":"cURL"},{"key":"php","label":"PHP","variant":"Guzzle"},{"key":"php","label":"PHP","variant":"HTTP_Request2"},{"key":"php","label":"PHP","variant":"pecl_http"},{"key":"powershell","label":"PowerShell","variant":"RestMethod"},{"key":"python","label":"Python","variant":"http.client"},{"key":"python","label":"Python","variant":"Requests"},{"key":"r","label":"R","variant":"httr"},{"key":"r","label":"R","variant":"RCurl"},{"key":"ruby","label":"Ruby","variant":"Net::HTTP"},{"key":"shell","label":"Shell","variant":"Httpie"},{"key":"shell","label":"Shell","variant":"wget"},{"key":"swift","label":"Swift","variant":"URLSession"}],"languageOptions":[{"label":"C# - HttpClient","value":"csharp - HttpClient - C#"},{"label":"C# - RestSharp","value":"csharp - RestSharp - C#"},{"label":"cURL - cURL","value":"curl - cURL - cURL"},{"label":"Dart - http","value":"dart - http - Dart"},{"label":"Go - Native","value":"go - Native - Go"},{"label":"HTTP - HTTP","value":"http - HTTP - HTTP"},{"label":"Java - OkHttp","value":"java - OkHttp - Java"},{"label":"Java - Unirest","value":"java - Unirest - Java"},{"label":"JavaScript - Fetch","value":"javascript - Fetch - JavaScript"},{"label":"JavaScript - jQuery","value":"javascript - jQuery - JavaScript"},{"label":"JavaScript - XHR","value":"javascript - XHR - JavaScript"},{"label":"C - libcurl","value":"c - libcurl - C"},{"label":"NodeJs - Axios","value":"nodejs - Axios - NodeJs"},{"label":"NodeJs - Native","value":"nodejs - Native - NodeJs"},{"label":"NodeJs - Request","value":"nodejs - Request - NodeJs"},{"label":"NodeJs - Unirest","value":"nodejs - Unirest - NodeJs"},{"label":"Objective-C - NSURLSession","value":"objective-c - NSURLSession - Objective-C"},{"label":"OCaml - Cohttp","value":"ocaml - Cohttp - OCaml"},{"label":"PHP - cURL","value":"php - cURL - PHP"},{"label":"PHP - Guzzle","value":"php - Guzzle - PHP"},{"label":"PHP - HTTP_Request2","value":"php - HTTP_Request2 - PHP"},{"label":"PHP - pecl_http","value":"php - pecl_http - PHP"},{"label":"PowerShell - RestMethod","value":"powershell - RestMethod - PowerShell"},{"label":"Python - http.client","value":"python - http.client - Python"},{"label":"Python - Requests","value":"python - Requests - Python"},{"label":"R - httr","value":"r - httr - R"},{"label":"R - RCurl","value":"r - RCurl - R"},{"label":"Ruby - Net::HTTP","value":"ruby - Net::HTTP - Ruby"},{"label":"Shell - Httpie","value":"shell - Httpie - Shell"},{"label":"Shell - wget","value":"shell - wget - Shell"},{"label":"Swift - URLSession","value":"swift - URLSession - Swift"}],"layoutOptions":[{"value":"classic-single-column","label":"Single Column"},{"value":"classic-double-column","label":"Double Column"}],"versionOptions":[],"environmentOptions":[{"value":"0","label":"No Environment"}],"canonicalUrl":"https://docs.openbanking.vulte.ng/view/metadata/SzS4R7Jv"}