Document Verification
curl --request POST \
--url https://adhere-api.smartcomply.com/api/onboarding/document_verification \
--header 'Content-Type: multipart/form-data' \
--header 'x-access-token: <api-key>' \
--form document_type=passport \
--form country=nigeria \
--form document_front='@example-file' \
--form document_back='@example-file'import requests
url = "https://adhere-api.smartcomply.com/api/onboarding/document_verification"
files = {
"document_front": ("example-file", open("example-file", "rb")),
"document_back": ("example-file", open("example-file", "rb"))
}
payload = {
"document_type": "passport",
"country": "nigeria"
}
headers = {"x-access-token": "<api-key>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('document_type', 'passport');
form.append('country', 'nigeria');
form.append('document_front', '<string>');
form.append('document_back', '<string>');
const options = {method: 'POST', headers: {'x-access-token': '<api-key>'}};
options.body = form;
fetch('https://adhere-api.smartcomply.com/api/onboarding/document_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://adhere-api.smartcomply.com/api/onboarding/document_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 => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_type\"\r\n\r\npassport\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"country\"\r\n\r\nnigeria\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_front\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_back\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Content-Type: multipart/form-data",
"x-access-token: <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://adhere-api.smartcomply.com/api/onboarding/document_verification"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_type\"\r\n\r\npassport\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"country\"\r\n\r\nnigeria\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_front\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_back\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-access-token", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://adhere-api.smartcomply.com/api/onboarding/document_verification")
.header("x-access-token", "<api-key>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_type\"\r\n\r\npassport\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"country\"\r\n\r\nnigeria\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_front\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_back\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://adhere-api.smartcomply.com/api/onboarding/document_verification")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-access-token"] = '<api-key>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_type\"\r\n\r\npassport\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"country\"\r\n\r\nnigeria\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_front\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_back\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"status": "failed",
"data": [
"<unknown>"
],
"message": "<string>"
}{
"status": "failed",
"message": "Authentication credentials were not provided."
}Document Verification
Document Verification
Extract identity details from a photo of a document using OCR — no face match, no liveness.
POST
/
api
/
onboarding
/
document_verification
Document Verification
curl --request POST \
--url https://adhere-api.smartcomply.com/api/onboarding/document_verification \
--header 'Content-Type: multipart/form-data' \
--header 'x-access-token: <api-key>' \
--form document_type=passport \
--form country=nigeria \
--form document_front='@example-file' \
--form document_back='@example-file'import requests
url = "https://adhere-api.smartcomply.com/api/onboarding/document_verification"
files = {
"document_front": ("example-file", open("example-file", "rb")),
"document_back": ("example-file", open("example-file", "rb"))
}
payload = {
"document_type": "passport",
"country": "nigeria"
}
headers = {"x-access-token": "<api-key>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('document_type', 'passport');
form.append('country', 'nigeria');
form.append('document_front', '<string>');
form.append('document_back', '<string>');
const options = {method: 'POST', headers: {'x-access-token': '<api-key>'}};
options.body = form;
fetch('https://adhere-api.smartcomply.com/api/onboarding/document_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://adhere-api.smartcomply.com/api/onboarding/document_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 => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_type\"\r\n\r\npassport\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"country\"\r\n\r\nnigeria\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_front\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_back\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Content-Type: multipart/form-data",
"x-access-token: <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://adhere-api.smartcomply.com/api/onboarding/document_verification"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_type\"\r\n\r\npassport\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"country\"\r\n\r\nnigeria\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_front\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_back\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-access-token", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://adhere-api.smartcomply.com/api/onboarding/document_verification")
.header("x-access-token", "<api-key>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_type\"\r\n\r\npassport\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"country\"\r\n\r\nnigeria\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_front\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_back\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://adhere-api.smartcomply.com/api/onboarding/document_verification")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-access-token"] = '<api-key>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_type\"\r\n\r\npassport\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"country\"\r\n\r\nnigeria\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_front\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document_back\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"status": "failed",
"data": [
"<unknown>"
],
"message": "<string>"
}{
"status": "failed",
"message": "Authentication credentials were not provided."
}The Document Verification endpoint extracts identity details from a photo of a document using OCR. Unlike the checks under Data Verification, which look up an ID number against a government database, this endpoint reads the details directly off an uploaded image — useful as a fallback when a number-lookup check is unavailable, or when your flow already collects a document photo.
No face match, no liveness check — this endpoint only performs OCR extraction.
Supported Documents
Whichdocument_type values are valid depends on the document’s country.
| Country | Supported document_type values |
|---|---|
| Nigeria | national_id, passport, drivers_license, voters_card, cac_certificate, utility_bill |
| Kenya | kenya_id, passport |
| Ghana | passport |
| Canada | passport |
| USA | passport |
| Côte d’Ivoire | passport |
passport is the only type valid across every supported country. All other types are specific to the country listed. Kenya’s national ID uses its own value, kenya_id — it is not interchangeable with national_id, which is Nigeria’s NIN slip/card.
document_front and document_back are optional per document type — recommended for two-sided documents (national_id, kenya_id, drivers_license), where extraction may be less complete with only the front supplied.Endpoint
POST /api/onboarding/document_verification
Request
Headers
| Header | Value | Required |
|---|---|---|
x-access-token | Your API secret key | Yes |
Content-Type | multipart/form-data | Yes |
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
document_type | string | Yes | The kind of document being submitted — see Supported Documents above |
country | string | Yes | Country the document was issued in — see Supported Documents above |
document_front | file | Yes | Front of the document. JPG or PNG, max 5MB |
document_back | file | No | Back of the document. JPG or PNG, max 5MB |
Example
curl -X POST "https://adhere-api.smartcomply.com/api/onboarding/document_verification" \
-H "x-access-token: YOUR_SECRET_KEY" \
-F "document_type=passport" \
-F "country=nigeria" \
-F "document_front=@/path/to/passport.jpg"
const formData = new FormData();
formData.append("document_type", "passport");
formData.append("country", "nigeria");
formData.append("document_front", fs.createReadStream("/path/to/passport.jpg"));
const response = await fetch(
"https://adhere-api.smartcomply.com/api/onboarding/document_verification",
{
method: "POST",
headers: { "x-access-token": "YOUR_SECRET_KEY" },
body: formData,
}
);
const data = await response.json();
import requests
response = requests.post(
"https://adhere-api.smartcomply.com/api/onboarding/document_verification",
headers={"x-access-token": "YOUR_SECRET_KEY"},
data={"document_type": "passport", "country": "nigeria"},
files={"document_front": open("/path/to/passport.jpg", "rb")},
)
data = response.json()
Response
200 OK
| Field | Type | Description |
|---|---|---|
status | string | "success" on a successful extraction |
data.full_name | string | Extracted full name |
data.first_name | string | Extracted first name |
data.last_name | string | Extracted last name |
data.date_of_birth | string | Date of birth in YYYY-MM-DD format |
data.gender | string | Extracted gender, where present on the document |
data.id_number | string | The document’s own number (passport number, NIN, license number, etc.) |
data.document_type | string | Echoes the document_type that was submitted |
data.expiry_date | string | Document expiry date, where the document carries one |
data.is_expired | boolean | Whether expiry_date has already passed |
data.photo | string | Base64-encoded face photo extracted from the document. null for cac_certificate and utility_bill, which don’t carry a face |
message | string | Human-readable result summary |
{
"status": "success",
"data": {
"valid": true,
"first_name": "TUNDE",
"last_name": "AYODELE",
"full_name": "AYODELE TUNDE",
"date_of_birth": "2002-02-16",
"id_number": "A12345678",
"id_type": "passport",
"document_type": "passport",
"expiry_date": "2030-01-01",
"is_expired": false,
"photo": "/9j/4AAQSkZJRgABAQAAAQABAAD..."
},
"message": "Document details retrieved successfully"
}
Not every field is present on every document type —
cac_certificate and utility_bill never populate photo, and fields that genuinely aren’t visible or present on the document (e.g. gender on some documents) come back absent rather than guessed.400 Bad Request
Returned for invalid input (unsupporteddocument_type/country, wrong file type, file too large) or when the document itself fails OCR’s own quality checks (blurry, wrong document type, glare, etc.) — message carries the specific reason in either case.
{
"status": "failed",
"data": [],
"message": "ID photo is too blurry — please retake in good lighting with a steady hand"
}
401 Unauthorized
Returned when thex-access-token header is missing or invalid.
{
"status": "failed",
"message": "Authentication credentials were not provided."
}
For a full list of error codes, see the Error Codes reference.
Authorizations
Your Adhere API secret key
Body
multipart/form-data
The kind of document being submitted. Which values are valid depends on country — passport works for every supported country; the rest are country-specific.
Available options:
national_id, passport, drivers_license, voters_card, kenya_id, cac_certificate, utility_bill Example:
"passport"
Country the document was issued in.
Available options:
nigeria, kenya, ghana, canada, usa, cote d'ivoire Example:
"nigeria"
Front of the document. JPG or PNG, max 5MB.
Back of the document. Optional for every type, but recommended for two-sided documents (national_id, kenya_id, drivers_license) — extraction may be less complete without it.
Response
Document details extracted successfully
⌘I

