Submit Tier 1 verification
curl --request POST \
--url https://api.daya.co/v1/customers/{id}/tier1-verification \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <x-api-key>' \
--data '
{
"bvn": "<string>",
"phone_number": "<string>",
"image_url": "<string>",
"bank_account": {
"account_number": "<string>",
"bank_code": "<string>"
}
}
'import requests
url = "https://api.daya.co/v1/customers/{id}/tier1-verification"
payload = {
"bvn": "<string>",
"phone_number": "<string>",
"image_url": "<string>",
"bank_account": {
"account_number": "<string>",
"bank_code": "<string>"
}
}
headers = {
"X-Api-Key": "<x-api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Api-Key': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
bvn: '<string>',
phone_number: '<string>',
image_url: '<string>',
bank_account: {account_number: '<string>', bank_code: '<string>'}
})
};
fetch('https://api.daya.co/v1/customers/{id}/tier1-verification', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.daya.co/v1/customers/{id}/tier1-verification",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'bvn' => '<string>',
'phone_number' => '<string>',
'image_url' => '<string>',
'bank_account' => [
'account_number' => '<string>',
'bank_code' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Api-Key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.daya.co/v1/customers/{id}/tier1-verification"
payload := strings.NewReader("{\n \"bvn\": \"<string>\",\n \"phone_number\": \"<string>\",\n \"image_url\": \"<string>\",\n \"bank_account\": {\n \"account_number\": \"<string>\",\n \"bank_code\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Api-Key", "<x-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.daya.co/v1/customers/{id}/tier1-verification")
.header("X-Api-Key", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"bvn\": \"<string>\",\n \"phone_number\": \"<string>\",\n \"image_url\": \"<string>\",\n \"bank_account\": {\n \"account_number\": \"<string>\",\n \"bank_code\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.daya.co/v1/customers/{id}/tier1-verification")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Api-Key"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"bvn\": \"<string>\",\n \"phone_number\": \"<string>\",\n \"image_url\": \"<string>\",\n \"bank_account\": {\n \"account_number\": \"<string>\",\n \"bank_code\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "650e8400-e29b-41d4-a716-446655440000",
"email": "customer@example.com",
"first_name": "John",
"last_name": "Doe",
"is_verified": false,
"tier_1_kyc_complete": true,
"tier_2_kyc_complete": false,
"capabilities": [
{ "name": "base", "status": "approved" }
],
"paystack_funding_account_readiness": {
"status": "READY",
"bank_code": "058",
"account_number_last4": "6789",
"missing_fields": [],
"updated_at": "2026-01-06T12:00:00Z"
},
"rejection_reasons": [],
"created_at": "2026-01-05T15:04:05Z",
"updated_at": "2026-01-06T12:00:00Z"
}
Customers
Submit Tier 1 verification
Submit identity verification for a customer
POST
/
v1
/
customers
/
{id}
/
tier1-verification
Submit Tier 1 verification
curl --request POST \
--url https://api.daya.co/v1/customers/{id}/tier1-verification \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <x-api-key>' \
--data '
{
"bvn": "<string>",
"phone_number": "<string>",
"image_url": "<string>",
"bank_account": {
"account_number": "<string>",
"bank_code": "<string>"
}
}
'import requests
url = "https://api.daya.co/v1/customers/{id}/tier1-verification"
payload = {
"bvn": "<string>",
"phone_number": "<string>",
"image_url": "<string>",
"bank_account": {
"account_number": "<string>",
"bank_code": "<string>"
}
}
headers = {
"X-Api-Key": "<x-api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Api-Key': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
bvn: '<string>',
phone_number: '<string>',
image_url: '<string>',
bank_account: {account_number: '<string>', bank_code: '<string>'}
})
};
fetch('https://api.daya.co/v1/customers/{id}/tier1-verification', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.daya.co/v1/customers/{id}/tier1-verification",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'bvn' => '<string>',
'phone_number' => '<string>',
'image_url' => '<string>',
'bank_account' => [
'account_number' => '<string>',
'bank_code' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Api-Key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.daya.co/v1/customers/{id}/tier1-verification"
payload := strings.NewReader("{\n \"bvn\": \"<string>\",\n \"phone_number\": \"<string>\",\n \"image_url\": \"<string>\",\n \"bank_account\": {\n \"account_number\": \"<string>\",\n \"bank_code\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Api-Key", "<x-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.daya.co/v1/customers/{id}/tier1-verification")
.header("X-Api-Key", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"bvn\": \"<string>\",\n \"phone_number\": \"<string>\",\n \"image_url\": \"<string>\",\n \"bank_account\": {\n \"account_number\": \"<string>\",\n \"bank_code\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.daya.co/v1/customers/{id}/tier1-verification")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Api-Key"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"bvn\": \"<string>\",\n \"phone_number\": \"<string>\",\n \"image_url\": \"<string>\",\n \"bank_account\": {\n \"account_number\": \"<string>\",\n \"bank_code\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "650e8400-e29b-41d4-a716-446655440000",
"email": "customer@example.com",
"first_name": "John",
"last_name": "Doe",
"is_verified": false,
"tier_1_kyc_complete": true,
"tier_2_kyc_complete": false,
"capabilities": [
{ "name": "base", "status": "approved" }
],
"paystack_funding_account_readiness": {
"status": "READY",
"bank_code": "058",
"account_number_last4": "6789",
"missing_fields": [],
"updated_at": "2026-01-06T12:00:00Z"
},
"rejection_reasons": [],
"created_at": "2026-01-05T15:04:05Z",
"updated_at": "2026-01-06T12:00:00Z"
}
Overview
Submit Tier 1 identity verification (BVN + selfie) for a customer. This is required before creating permanent NGN funding accounts. Include a verified customer bank account only if you want a Paystack funding-account instruction. When you includebank_account, you must also include phone_number Flutterwave does not require either field. Tier 1 KYC is complete once the BVN check succeeds.
Authentication
string
required
Your merchant API key
Path Parameters
string
required
Customer ID (UUID)Example:
650e8400-e29b-41d4-a716-446655440000Request Body
string
required
11-digit Bank Verification NumberExample:
22345678901Must be exactly 11 digits. The BVN is validated against the national identity database.
string
Customer’s phone number. Required when
bank_account is included; otherwise optional. Send the 11-digit national form or the +234 international form.Example: +2348012345678string
required
Face image for identity matching. Accepts an HTTPS URL to a jpg/png image, or base64-encoded image data up to 1 MiB decoded.Example:
https://example.com/selfie.jpgFor base64, include the data URI prefix:
data:image/jpeg;base64,/9j/4AAQ.... The decoded payload must not exceed 1 MiB.object
Optional NGN bank account belonging to the customer. This is not the funding account the customer will receive.
Show bank_account properties
Show bank_account properties
string
required
The customer’s 10-digit NGN bank account number.
string
required
The bank code returned by
GET /v1/banks.bank_account, get the supported bank_code from GET /v1/banks and verify the account with POST /v1/banks/resolve. Then send the verified account_number and bank_code together.
If the bank details are rejected after the BVN check succeeds, the customer remains Tier 1 verified. Correct the bank details with the Update Tier 1 bank account endpoint.
Request Examples
{
"bvn": "22345678901",
"phone_number": "+2348012345678",
"image_url": "https://example.com/selfie.jpg",
"bank_account": {
"account_number": "0123456789",
"bank_code": "058"
}
}
{
"bvn": "22345678901",
"image_url": "data:image/jpeg;base64,/9j/4AAQSkZJRg..."
}
curl --request POST \
--url https://api.daya.co/v1/customers/650e8400-e29b-41d4-a716-446655440000/tier1-verification \
--header 'X-Api-Key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"bvn": "22345678901",
"phone_number": "+2348012345678",
"image_url": "https://example.com/selfie.jpg",
"bank_account": {
"account_number": "0123456789",
"bank_code": "058"
}
}'
const response = await fetch(
'https://api.daya.co/v1/customers/650e8400-e29b-41d4-a716-446655440000/tier1-verification',
{
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
bvn: '22345678901',
phone_number: '+2348012345678',
image_url: 'https://example.com/selfie.jpg',
bank_account: {
account_number: '0123456789',
bank_code: '058'
}
})
}
);
const result = await response.json();
console.log(result);
Response
Returns the updated customer object. See Get customer for the full field list. On success,tier_1_kyc_complete flips to true.
Success Response
{
"id": "650e8400-e29b-41d4-a716-446655440000",
"email": "customer@example.com",
"first_name": "John",
"last_name": "Doe",
"is_verified": false,
"tier_1_kyc_complete": true,
"tier_2_kyc_complete": false,
"capabilities": [
{ "name": "base", "status": "approved" }
],
"paystack_funding_account_readiness": {
"status": "READY",
"bank_code": "058",
"account_number_last4": "6789",
"missing_fields": [],
"updated_at": "2026-01-06T12:00:00Z"
},
"rejection_reasons": [],
"created_at": "2026-01-05T15:04:05Z",
"updated_at": "2026-01-06T12:00:00Z"
}
Bank Account Verification Result
The result webhook includescustomer_id, provider, status, and identity_version. Failed results also include failure_code and failure_message so you can tell the customer what needs to be corrected.
See Bank Account Verification Events for complete payloads and retry-safe handling.
Error Responses
{
"error": {
"code": "VALIDATION_FAILED",
"message": "Validation failed",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"validation": "bvn must be exactly 11 digits"
}
}
{
"error": {
"code": "BVN_VERIFICATION_FAILED",
"message": "BVN verification failed",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}
{
"error": {
"code": "FACE_MISMATCH",
"message": "Face verification failed: selfie does not match BVN record",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}
{
"error": {
"code": "NOT_FOUND",
"message": "Customer not found",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}
{
"error": {
"code": "INTEGRATION_FAILED",
"message": "Verification provider unavailable, please try again",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}
Next Steps
Create Funding Account
Create a permanent funding account for the verified customer
Update Tier 1 Bank Account
Add bank details for an already verified customer
Get Customer
Check the customer’s current verification status
Webhook Events
Handle Paystack bank account verification results