API Reference
All endpoints require the X-IdentifyOrg-Key header. Base URL: https://api.identifyorg.com. This reference is generated from our OpenAPI 3.0 specification — the same source of truth our SDKs are built from.
Send a phone verification code
/v1/phone/verify/startGenerates a code, sends it by SMS to your user's phone, and returns an id to check it against later. Works with local Nigerian numbers or E.164 — a local 0803… is normalised to +234803… for you. NGN 6.00 per send on an API key (NGN 8.00 from the dashboard), charged when the message goes out and refunded in full if delivery fails. Pass your own `template` to control the wording; it must contain {code}. Test keys return this exact shape without sending anything, so no real phone is messaged while you build.
{
"phone": "08031234567",
"template": "Your {site} code is {code}. Expires in {minutes} minutes.", // optional
"reference": "signup-8842" // optional, your own id, echoed back
}{
"id": "phv_01hxyz...",
"phone": "+2348031234567",
"status": "pending",
"expires_at": "2026-09-08T10:35:00Z",
"reference": "signup-8842",
"cost": 6.0,
"is_test": false
}Stuck integrating Send a phone verification code?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Check a phone verification code
/v1/phone/verify/checkConfirms the code your user typed. Free — the charge already happened when the code was sent, and billing again to find out whether six digits were typed correctly would be charging twice for one delivery. Codes expire, and repeated wrong attempts stop the id being usable, so a code cannot be brute-forced.
{
"id": "phv_01hxyz...",
"code": "418209"
}{
"id": "phv_01hxyz...",
"phone": "+2348031234567",
"status": "verified",
"verified": true,
"reference": "signup-8842"
}Stuck integrating Check a phone verification code?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Generate app store assets
/v1/tools/store-assetsUpload one image and get back a zip containing every icon and screenshot size Google Play and the App Store require — including the 7-inch and 10-inch tablet screenshots most people have no device to produce. NGN 10 per run, or free on the tools monthly pass. Pass `platform` as play, ios or both.
multipart/form-data
file = your logo or screenshot (PNG/JPG)
kind = icon | screenshot | splash
platform = play | ios | bothA zip file, with each asset named by the size
and folder the store expects.Stuck integrating Generate app store assets?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Verify a BVN
/v1/verify/bvnVerify an 11-digit Bank Verification Number. phone_number is required on live keys (the upstream provider rejects requests without it) — test keys ignore it. Optionally pass first_name, last_name and date_of_birth for cross-match scoring against what's on file. Synchronous — responds in under 3 seconds.
{
"bvn": "12345678901",
"phone_number": "08012345678", // required on live keys
"first_name": "Adaeze", // optional, for cross-match
"last_name": "Okafor", // optional, for cross-match
"date_of_birth": "1992-04-15" // optional, for cross-match
}{
"id": "ver_01hxyz...",
"type": "bvn",
"status": "success",
"match": true,
"confidence_score": 98,
"data": {
"bvn": "12345678901",
"date_of_birth": "1992-04-15",
"phone_number": "+2348012345678",
"gender": "female"
}
}Stuck integrating Verify a BVN?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Verify a NIN
/v1/verify/ninVerify an 11-digit National Identification Number issued by NIMC. Optionally pass first_name and last_name to cross-match against what's on file (the upstream lookup itself doesn't do matching, so we do it for you). Synchronous — responds in under 4 seconds.
{
"nin": "12345678901",
"first_name": "Adaeze", // optional, for cross-match
"last_name": "Okafor" // optional, for cross-match
}{
"id": "ver_01hxyz...",
"type": "nin",
"status": "success",
"match": true,
"data": {
"nin": "12345678901",
"first_name": "Adaeze",
"last_name": "Okafor",
"date_of_birth": "1992-04-15",
"phone_number": "+2348012345678",
"gender": "female"
}
}Stuck integrating Verify a NIN?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Verify a driver's licence
/v1/verify/frscVerify a Nigerian driver's licence via licensed FRSC data partners. Returns licence status, class, expiry date and state of issue.
{
"licence_number": "ABC12345DE67",
"first_name": "Adaeze", // optional
"last_name": "Okafor" // optional
}{
"id": "ver_01hxyz...",
"type": "frsc",
"status": "success",
"data": {
"licence_status": "valid",
"expiry_date": "2028-11-30",
"licence_class": "B",
"state_of_issue": "Lagos"
}
}Stuck integrating Verify a driver's licence?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Verify a bank account
/v1/verify/bank-accountLook up the registered name on a Nigerian bank account from the account number and the bank's CBN code. Use it to confirm a payout or refund goes to the right person before you send money. Returns not_found when the number and bank do not match.
{
"account_number": "0123456789",
"bank_code": "058"
}{
"id": "ver_01hxyz...",
"type": "bank_account",
"status": "success",
"data": {
"account_number": "0123456789",
"account_name": "ADAEZE NGOZI OKAFOR",
"bank_code": "058"
}
}Stuck integrating Verify a bank account?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Match a BVN to a bank account
/v1/verify/bvn-account-matchCheck that a BVN belongs to the holder of a bank account. Returns a match status (FULL_MATCH, PARTIAL_MATCH or NO_MATCH), a match percentage, and `match: true` when the owner is the same person. Useful for onboarding, loan payouts and fraud checks.
{
"account_number": "0123456789",
"bank_code": "058",
"bvn": "22212345678"
}{
"id": "ver_01hxyz...",
"type": "bvn_account_match",
"status": "success",
"match": true,
"confidence_score": 100,
"data": {
"account_number": "0123456789",
"account_name": "ADAEZE NGOZI OKAFOR",
"match_status": "FULL_MATCH",
"match_percentage": 100
}
}Stuck integrating Match a BVN to a bank account?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Verify an address
/v1/verify/addressLook the address up on the map and start a check. Send the returned `confirm_url` to the person: when they open it on their phone at the address and share their location, we compare the two. Add a utility bill or bank statement with `/v1/verify/address/{id}/document`, or post the phone's coordinates yourself with `/v1/verify/address/{id}/location` from a mobile app. Each signal adds to `confidence_score` (address found up to 40, person at the address up to 40, document up to 20). `status` is `verified` at 70 or more, `review` from 40, otherwise `failed`, and `pending` until the person or a document has been checked. Results are also sent as `verification.completed` webhooks.
{
"address": "12 Adeola Odeku Street, Victoria Island, Lagos",
"full_name": "Ada Obi",
"country": "NG",
"radius_m": 150,
"reference": "loan-4821"
}{
"id": "ver_01hxyz...",
"type": "address",
"status": "pending",
"match": false,
"confidence_score": 40,
"address": {
"submitted": "12 Adeola Odeku Street, Victoria Island, Lagos",
"formatted": "12 Adeola Odeku St, Victoria Island, Lagos, Nigeria",
"latitude": 6.4281,
"longitude": 3.4219,
"precision": "ROOFTOP"
},
"checks": {
"address_exists": { "status": "pass", "points": 40 },
"location": { "status": "not_provided", "points": 0 },
"document": { "status": "not_provided", "points": 0 }
},
"signals": [],
"confirm_url": "https://identifyorg.com/verify-address/...",
"expires_at": "2026-10-15T10:24:00Z",
"cost": 150.0,
"currency": "NGN",
"is_test": false
}Stuck integrating Verify an address?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Submit a phone location for an address check
/v1/verify/address/{id}/locationFor mobile apps: send the coordinates your app read from the person's phone while they are at the address. `accuracy_m` is the phone's reported accuracy. Returns the updated result. No extra charge.
{
"latitude": 6.4283,
"longitude": 3.4221,
"accuracy_m": 12
}{
"id": "ver_01hxyz...",
"type": "address",
"status": "verified",
"match": true,
"confidence_score": 80,
"checks": {
"address_exists": { "status": "pass", "points": 40 },
"location": { "status": "pass", "points": 40, "distance_m": 31, "accuracy_m": 12 },
"document": { "status": "not_provided", "points": 0 }
}
}Stuck integrating Submit a phone location for an address check?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Add a utility bill or statement to an address check
/v1/verify/address/{id}/documentUpload a photo or scan (multipart/form-data, field `file`) of a utility bill or bank statement. We read it on our own servers, compare the address and the name, and discard the image. No extra charge.
curl -X POST https://api.identifyorg.com/v1/verify/address/ver_01hxyz.../document \
-H "X-IdentifyOrg-Key: io_live_xxxx" \
-F "file=@bill.jpg"{
"id": "ver_01hxyz...",
"type": "address",
"status": "verified",
"confidence_score": 100,
"checks": {
"document": { "status": "pass", "points": 20, "address_match": 100, "name_match": true }
}
}Stuck integrating Add a utility bill or statement to an address check?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Verify a document
/v1/verify/documentUpload an ID document photo (multipart/form-data, field `file`) for OCR extraction and validity checks. Synchronous — responds directly, no polling.
curl -X POST https://api.identifyorg.com/v1/verify/document \
-H "X-IdentifyOrg-Key: io_live_xxxx" \
-F "file=@passport.jpg"{
"id": "ver_01hxyz...",
"type": "document",
"status": "success",
"match": null,
"confidence_score": 91,
"data": {
"full_name": "OKAFOR ADAEZE N",
"document_number": "A12345678",
"expiry_date": "2030-05-01"
},
"cost": 30.0,
"currency": "NGN",
"is_test": false,
"created_at": "2026-07-02T10:24:00Z"
}Stuck integrating Verify a document?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Check liveness
/v1/verify/livenessUpload a selfie photo (multipart/form-data, field `file`) for passive anti-spoofing analysis. Synchronous. `confidence_score` of 75+ is considered live.
curl -X POST https://api.identifyorg.com/v1/verify/liveness \
-H "X-IdentifyOrg-Key: io_live_xxxx" \
-F "file=@selfie.jpg"{
"id": "ver_01hxyz...",
"type": "liveness",
"status": "success",
"match": null,
"confidence_score": 91,
"data": null,
"cost": 25.0,
"currency": "NGN",
"is_test": false,
"created_at": "2026-07-02T10:24:00Z"
}Stuck integrating Check liveness?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Compare two faces
/v1/verify/face-matchUpload two images (multipart/form-data, fields `selfie` and `id_photo`) to biometrically compare them. Synchronous.
curl -X POST https://api.identifyorg.com/v1/verify/face-match \
-H "X-IdentifyOrg-Key: io_live_xxxx" \
-F "selfie=@selfie.jpg" \
-F "id_photo=@id_card_photo.jpg"{
"id": "ver_01hxyz...",
"type": "face_match",
"status": "success",
"match": true,
"confidence_score": 94,
"data": null,
"cost": 35.0,
"currency": "NGN",
"is_test": false,
"created_at": "2026-07-02T10:24:00Z"
}Stuck integrating Compare two faces?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Issue a video/voice/stream token
/v1/streaming/{session_type}/tokenMint a short-lived LiveKit token for a participant. `session_type` in the path is one of `video`, `voice` or `stream`. Omit `room_name` to start a new room. Room creation is implicit — the first token issued for a room name creates it. Billed per participant-minute; see the pricing page for rates by session type.
{
"room_name": "kyc-session-4821", // optional, omit to create a new room
"identity": "user-8821",
"display_name": "Adaeze Okafor", // optional
"role": "publisher" // publisher (send+receive) or viewer
}{
"session_id": "cs_01hxyz...",
"room_name": "kyc-session-4821",
"token": "eyJhbGciOi...",
"url": "wss://livekit.identifyorg.com",
"type": "video",
"expires_in_minutes": 180,
"price_per_minute": 2.5,
"currency": "NGN",
"is_test": false
}Stuck integrating Issue a video/voice/stream token?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
List call/stream sessions
/v1/streaming/sessionsReturns your most recent call/streaming sessions and their billed cost.
[
{
"id": "cs_01hxyz...",
"type": "video",
"room_name": "kyc-session-4821",
"status": "completed",
"duration_seconds": 342,
"cost": 14.25,
"currency": "NGN",
"created_at": "2026-07-02T10:24:00Z"
}
]Stuck integrating List call/stream sessions?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Balance & usage
/v1/balanceGET /v1/balance returns your current credit balance and free-tier calls remaining this month. GET /v1/usage returns usage history with date filters (?from=2026-06-01&to=2026-06-30). GET /v1/pricing returns current per-verification-type pricing.
{
"balance": 48250.00,
"currency": "NGN",
"low_balance": false,
"free_tier_remaining": 2
}Stuck integrating Balance & usage?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
PDF to DOCX
/v1/tools/pdf-to-docxConvert a PDF into an editable Word document. multipart/form-data upload, field name `file`. Returns the .docx binary directly (Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document). Max file size 20MB.
curl -X POST https://api.identifyorg.com/v1/tools/pdf-to-docx \
-H "X-IdentifyOrg-Key: io_live_xxxx" \
-F "file=@document.pdf" \
-o converted.docxStuck integrating PDF to DOCX?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
DOCX to PDF
/v1/tools/docx-to-pdfConvert a Word document to PDF. multipart/form-data upload, field name `file`. Returns the .pdf binary directly. Max file size 20MB.
curl -X POST https://api.identifyorg.com/v1/tools/docx-to-pdf \
-H "X-IdentifyOrg-Key: io_live_xxxx" \
-F "file=@document.docx" \
-o converted.pdfStuck integrating DOCX to PDF?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Audio format conversion
/v1/tools/audio-convertConvert audio between mp3, wav, aac, flac, ogg and m4a. multipart/form-data upload with fields `file` and `target_format`. Returns the converted audio binary. Max file size 50MB.
curl -X POST https://api.identifyorg.com/v1/tools/audio-convert \
-H "X-IdentifyOrg-Key: io_live_xxxx" \
-F "file=@voice-note.wav" \
-F "target_format=mp3" \
-o converted.mp3Stuck integrating Audio format conversion?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Background remover
/v1/tools/remove-backgroundRemove the background from an image, returning a transparent PNG. multipart/form-data upload, field name `file`. Max file size 15MB.
curl -X POST https://api.identifyorg.com/v1/tools/remove-background \
-H "X-IdentifyOrg-Key: io_live_xxxx" \
-F "file=@photo.jpg" \
-o no-background.pngStuck integrating Background remover?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Website Audit
/v1/auditsRun a self-hosted security, performance, and AI-generation-detection scan against any URL — security headers, TLS, exposed paths, CORS misconfiguration, Lighthouse performance/accessibility/SEO scoring, and more. Synchronous — takes 15-70 seconds since a real Lighthouse run is the long pole. First audit is free per account, then billed at the API rate (separate from the website's own rate). Note: the free anonymous/claim flow used on the homepage is web-only, not part of this API.
{
"url": "https://example.com"
}{
"id": "aud_01hxyz...",
"url": "https://example.com/",
"status": "ready",
"score": 78,
"grade": "C",
"findings": [
{
"category": "headers",
"severity": "warning",
"title": "Content-Security-Policy header is missing",
"detail": "",
"fix": "Add a Content-Security-Policy response header to reduce this class of attack surface."
}
],
"lighthouse": {
"performance": { "score": 92, "title": "Performance" },
"accessibility": { "score": 96, "title": "Accessibility" },
"best_practices": { "score": 96, "title": "Best Practices" },
"seo": { "score": 100, "title": "SEO" }
},
"ai_signals": { "signals": [], "count": 0 },
"cost": 300.0,
"created_at": "2026-07-02T10:24:00Z"
}Stuck integrating Website Audit?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
List your website audits
/v1/auditsReturns your audit history, most recent first.
[
{
"id": "aud_01hxyz...",
"url": "https://example.com/",
"status": "ready",
"score": 78,
"grade": "C",
"cost": 300.0,
"created_at": "2026-07-02T10:24:00Z"
}
]Stuck integrating List your website audits?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Run a Deep Audit
/v1/auditsPass tier="deep" for the expanded audit — multi-page crawl, responsiveness, data-exposure checks, AI-generated-design-pattern detection, an optional GitHub code review, and (only for domains you've verified via /v1/domains) ownership-gated active security tests (login-throttling probe, CSRF header verification). Runs in the background — this call returns immediately with status="pending"; poll GET /v1/audits/{id} until status is "ready" or "failed", or just wait for the completion email. Always billed, no free trial.
{
"url": "https://example.com",
"tier": "deep",
"github_repo_url": "https://github.com/owner/repo"
}{
"id": "aud_01hxyz...",
"url": "https://example.com/",
"status": "pending",
"score": null,
"grade": null,
"tier": "deep",
"active_tests_run": false,
"cost": 5000.0,
"created_at": "2026-07-02T10:24:00Z"
}Stuck integrating Run a Deep Audit?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Start domain ownership verification
/v1/domains/verify/startProves you control a domain, to unlock the deep audit tier's active security tests for it. Returns both verification options — add either the DNS TXT record or the .well-known file, then call the check endpoint below. Free; dashboard-only (JWT auth).
{
"domain": "example.com"
}{
"id": "dom_01hxyz...",
"domain": "example.com",
"token": "3a810d5fe095e8f16555177ab14b8c29",
"dns_txt": {
"record": "_identifyorg-verify.example.com",
"type": "TXT",
"value": "3a810d5fe095e8f16555177ab14b8c29"
},
"well_known_file": {
"path": "/.well-known/identifyorg-verify.txt",
"url": "https://example.com/.well-known/identifyorg-verify.txt",
"content": "3a810d5fe095e8f16555177ab14b8c29"
}
}Stuck integrating Start domain ownership verification?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Check domain verification status
/v1/domains/verify/{domain_id}/checkRe-checks whether the DNS TXT record or well-known file is now in place. Retry-able — no error if not found yet.
{
"verified": true,
"method": "dns_txt"
}Stuck integrating Check domain verification status?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Check an image for AI generation / doctoring
/v1/media-scan/imageSelf-hosted detection — metadata/provenance, JPEG forensics, frequency/noise analysis, face-splice signals, plus a local ONNX classifier. multipart/form-data upload, field name `file`. Reports which signals fired, not a manufactured confidence percentage. First image check is free per account, then billed at the API rate (separate from the website's own rate). Note: the free anonymous/claim flow used on the homepage is web-only, not part of this API.
curl -X POST https://api.identifyorg.com/v1/media-scan/image \
-H "X-IdentifyOrg-Key: io_live_xxxx" \
-F "file=@photo.jpg"{
"id": "scn_01hxyz...",
"media_type": "image",
"status": "ready",
"verdict": "likely_authentic",
"signals": [
{
"category": "provenance",
"severity": "weak",
"title": "No camera metadata present",
"detail": "No Make/Model/DateTimeOriginal EXIF fields.",
"measured": null
}
],
"signal_count": 1,
"classifier_model": "ateeqq-ai-vs-human-siglip@1",
"cost": 200.0,
"is_test": false,
"created_at": "2026-07-02T10:24:00Z"
}Stuck integrating Check an image for AI generation / doctoring?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Check text for AI generation
/v1/media-scan/textSelf-hosted detection — stylometric heuristics (sentence/paragraph uniformity, vocabulary diversity, repeated phrasing, AI-phrasing lexicon) plus perplexity/burstiness scoring from a local language model. Requires at least 800 characters (shorter text is statistically meaningless for these checks). First text check is free per account, then billed at the API rate.
{
"text": "Paste at least 800 characters of text to check..."
}{
"id": "scn_01hxyz...",
"media_type": "text",
"status": "ready",
"verdict": "likely_ai",
"signals": [
{
"category": "language_model",
"severity": "moderate",
"title": "Text is unusually predictable to a language model",
"detail": "Mean perplexity (20.2) is low.",
"measured": { "mean_perplexity": 20.25 }
}
],
"signal_count": 1,
"classifier_model": "gpt2-base@1",
"text_char_count": 942,
"cost": 150.0,
"is_test": false,
"created_at": "2026-07-02T10:24:00Z"
}Stuck integrating Check text for AI generation?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Check a video for AI generation / doctoring
/v1/media-scan/videoffprobe container/metadata analysis plus ffmpeg frame-sampling through the same image-detection pipeline, aggregated across frames. multipart/form-data upload, field name `file`, optional `frames` query param (4-30, default 12). Always billed — there is no free tier and no anonymous trial for video, since a scan is real, multi-frame compute cost. Max file size 200MB, max duration 5 minutes.
curl -X POST "https://api.identifyorg.com/v1/media-scan/video?frames=12" \
-H "X-IdentifyOrg-Key: io_live_xxxx" \
-F "file=@clip.mp4"{
"id": "scn_01hxyz...",
"media_type": "video",
"status": "ready",
"verdict": "inconclusive",
"signals": [
{
"category": "container",
"severity": "weak",
"title": "No audio stream present",
"detail": "",
"measured": null
}
],
"signal_count": 1,
"duration_seconds": 8.4,
"frames_sampled": 12,
"cost": 800.0,
"is_test": false,
"created_at": "2026-07-02T10:24:00Z"
}Stuck integrating Check a video for AI generation / doctoring?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
List your media checks
/v1/media-scanReturns your image/video/text check history, most recent first. Optional `?media_type=image|video|text` filter.
[
{
"id": "scn_01hxyz...",
"media_type": "image",
"status": "ready",
"verdict": "likely_authentic",
"signal_count": 1,
"cost": 200.0,
"created_at": "2026-07-02T10:24:00Z"
}
]Stuck integrating List your media checks?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Logo generator
/v1/tools/generate-logoGenerate a procedural SVG logo — monogram, badge, abstract mark, or wordmark — from a company name and two brand colors. Instant, no queue.
{
"company_name": "Acme Fintech",
"style": "monogram", // monogram | badge | abstract | wordmark
"primary_color": "#10b981",
"secondary_color": "#0a0f1a",
"size": 256
}<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256">
<rect width="256" height="256" rx="56" fill="#10b981" />
<text ...>AF</text>
</svg>Stuck integrating Logo generator?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
WhatsApp: list your numbers (get your channel id)
/v1/wa/channelsStart here to use WhatsApp from your own app. First link a number once in your dashboard (WhatsApp > Add a number > Show QR, then scan it in WhatsApp under Linked devices). This call returns each number you have linked with its id. Use that id as {channel_id} in every WhatsApp call below. You can also create a number with POST /v1/wa/channels { label } and start linking with POST /v1/wa/channels/{channel_id}/connect. Your secret API key goes in the X-IdentifyOrg-Key header. Full guide: /docs/whatsapp.
[
{ "id": "8cabd11b-1293-432f-b429-9d222ce3e452", "label": "My shop", "phone": "2348012345678", "status": "connected" }
]Stuck integrating WhatsApp: list your numbers (get your channel id)?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
WhatsApp: reply to a customer
/v1/wa/channels/{channel_id}/sendSend a text, image or document from your linked number to a customer. Customer numbers can only reply to people who messaged them in the last 24 to 72 hours (depending on your plan). Use digits with the country code, like 2348012345678. Images and documents need a Business plan or above. To send a code or verification question to someone who has not messaged you, use the OTP and identity endpoints below.
{
"to": "2348012345678",
"text": "Order #1042 is out for delivery."
}{ "sent": 1, "session_active": false }Stuck integrating WhatsApp: reply to a customer?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
WhatsApp: send a one-time code (OTP)
/v1/wa/channels/{channel_id}/otpGenerates a code and delivers it from your linked WhatsApp number, worded as your brand. Works for any number, even if the person has never messaged you. Growth plan and above. Limits: 3 per person per hour, 8 per person per day, plus a daily cap for your plan. Codes expire after ttl_minutes (default 10) and lock after 5 wrong tries.
{
"to": "2348012345678",
"brand": "Acme Pay", // optional, shown in the message
"length": 6, // optional, 4 to 8
"ttl_minutes": 10, // optional, 1 to 30
"reference": "signin-8842" // optional, your own id
}{
"id": "5b0e...",
"kind": "otp",
"to": "2348012345678",
"status": "pending",
"expires_at": "2026-10-11T10:35:00Z"
}Stuck integrating WhatsApp: send a one-time code (OTP)?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
WhatsApp: check the code the person typed
/v1/wa/channels/{channel_id}/otp/verifyCall this when your user types the code into your app. Returns valid true or false and, if false, the reason: wrong_code, expired, too_many_attempts or no_pending_code. A code can be used once.
{
"to": "2348012345678",
"code": "483920"
}{ "valid": true, "reason": null, "reference": "signin-8842" }Stuck integrating WhatsApp: check the code the person typed?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
WhatsApp: verify identity with a question
/v1/wa/channels/{channel_id}/verify-identitySends a question to the person on WhatsApp. They reply with their answer, and we compare it to the expected answer you give (ignoring capital letters, spaces and punctuation). The expected answer is stored only as a one-way hash. If your website is connected to the number, it also receives a signed event of type verification when the check ends. Growth plan and above.
{
"to": "2348012345678",
"question": "What is your date of birth? (DD/MM/YYYY)",
"expected": "12/03/1990",
"reference": "customer_8841", // optional
"ttl_minutes": 30, // optional
"max_attempts": 3 // optional, 1 to 5
}{
"id": "c41f...",
"kind": "identity",
"to": "2348012345678",
"status": "pending",
"attempts": 0,
"expires_at": "2026-10-11T10:55:00Z"
}Stuck integrating WhatsApp: verify identity with a question?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
WhatsApp: get the result of an identity check
/v1/wa/channels/{channel_id}/verify-identity/{verification_id}Status is pending until the person answers, then verified, failed (out of tries) or expired. Poll this, or wait for the signed verification event on your website.
{
"id": "c41f...",
"kind": "identity",
"status": "verified",
"attempts": 1,
"resolved_at": "2026-10-11T10:41:12Z"
}Stuck integrating WhatsApp: get the result of an identity check?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Business payments: your limit, balance and fees
/v1/business/overviewUse IdentifyOrg to take payments for your own business, even before you have a bank-grade setup. Create account numbers for your customers, take card payments, and see everything received. You can receive up to your limit (NGN 5,000,000 to start) before we ask for your business registration certificate. Payments past the limit are held safely and released as soon as the certificate is verified. Our fee per payment: NGN 50 flat on payments under NGN 5,000, then 1% from NGN 5,000. `remaining` is how much you can still receive before verification (null once verified).
{
"status": "active",
"business_verified": false,
"limit": 5000000.0,
"received": 1250000.0,
"remaining": 3750000.0,
"balance": 1237500.0,
"held": 0.0,
"fees_charged": 12500.0,
"fees": { "flat": 50.0, "percent_from": 5000.0, "percent": 1.0 },
"live": true
}Stuck integrating Business payments: your limit, balance and fees?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Business payments: create an account number for a customer
/v1/business/virtual-accountsGives one of your customers their own bank account number to pay into. Everything they send is recorded against that customer. In test mode you get a test account number (no real money moves), and you can simulate payments to it. The banks require the customer's BVN or NIN (`bvn` or `nin`, 11 digits) to open a permanent account number on live accounts. We use it once to open the account and do not keep it. `reference` is optional and must be unique: use your own customer id. We send a `virtual_account.created` webhook.
{
"customer_name": "Ada Obi",
"customer_email": "ada@example.com",
"reference": "cust-1042", // optional
"bvn": "22212345678" // or "nin". Required on live accounts. Used once, never stored.
}{
"id": "5d1c...",
"reference": "cust-1042",
"account_number": "9950269842",
"bank_name": "Wema Bank",
"account_name": "Ada Obi",
"customer_name": "Ada Obi",
"customer_email": "ada@example.com",
"test": false,
"active": true,
"created_at": "2026-10-12T09:00:00Z"
}Stuck integrating Business payments: create an account number for a customer?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Business payments: list your customers' accounts
/v1/business/virtual-accountsEvery account number you created, with how many payments each received and the total.
{
"accounts": [
{ "id": "5d1c...", "reference": "cust-1042", "account_number": "9950269842", "bank_name": "Wema Bank",
"customer_name": "Ada Obi", "payments": 3, "total_received": 45000.0, "test": false }
]
}Stuck integrating Business payments: list your customers' accounts?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Business payments: take a card payment
/v1/business/chargesCreates a checkout link for a card payment. Send the link to your customer. When they pay, we send a `payment.received` webhook and the money (minus our fee) is added to your balance. Amounts are in naira, from 100 to 5,000,000.
{
"amount": 15000,
"customer_name": "Ada Obi",
"customer_email": "ada@example.com",
"description": "Order 8842"
}{
"reference": "mp_3f9a...",
"checkout_url": "https://checkout.example/pay/mp_3f9a...",
"payment": { "status": "pending", "amount": 15000.0 }
}Stuck integrating Business payments: take a card payment?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Business payments: list payments received
/v1/business/paymentsEverything received. Filter with `virtual_account_id` to see one customer's payments, or `status` (success, held, failed). `held` means the payment is waiting for your business certificate to be verified. Each payment shows our `fee` and what you received (`net`).
{
"payments": [
{ "id": "a7b2...", "method": "transfer", "status": "success", "amount": 15000.0, "fee": 150.0, "net": 14850.0,
"payer_name": "Ada Obi", "virtual_account_id": "5d1c...", "test": false, "paid_at": "2026-10-12T09:30:00Z" }
]
}Stuck integrating Business payments: list payments received?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Business payments: simulate a payment (test mode)
/v1/business/test/simulate-paymentIn test mode, pretend a customer paid into one of your test account numbers, to try your webhook, the limit and the fee without real money. Does nothing on live accounts.
{
"virtual_account_id": "5d1c...",
"amount": 20000
}{ "status": "success", "payment_id": "a7b2..." }Stuck integrating Business payments: simulate a payment (test mode)?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Business payments: set your business name
/v1/business/profileRequired before you can create account numbers or take payments. Send it with PUT. `business_type` is `registered` or `individual`.
{
"business_name": "Ada Stores",
"business_type": "individual",
"contact_phone": "08030000000"
}{ "business_name": "Ada Stores", "business_type": "individual", "contact_phone": "08030000000" }Stuck integrating Business payments: set your business name?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Business payments: withdraw your money
/v1/business/payoutsWithdraw to your saved bank account (set it with PUT /v1/business/payout-account using `bank_code` and `account_number`; we check the account name with the bank). Money received is pending for 24 hours before it can be withdrawn, and we may hold a payment we are checking: the overview shows `available` and `pending`. Withdrawals are approved by us and sent to your bank. You get `payout.requested`, then `payout.paid` or `payout.failed` webhooks. A failed or declined withdrawal goes back into your balance.
{ "amount": 50000 }{
"id": "e3f1...",
"reference": "po_8c1e...",
"status": "requested",
"amount": 50000.0,
"fee": 0.0,
"you_receive": 50000.0,
"bank_name": "Guaranty Trust Bank",
"account_number": "0123456789"
}Stuck integrating Business payments: withdraw your money?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Business payments: refund a customer
/v1/business/refundsAsk to send a payment (or part of it) back to the customer who paid. Leave `amount` out to refund all of it. Card refunds go back to the card through the payment provider. We approve it and tell you with `refund.processed`, or `refund.rejected` / `refund.failed` if it does not go through. The refunded amount comes off your balance, and our fee on that part is returned to you. If we find a problem with a transaction we send `payment.issue` and hold it until it is `payment.issue_resolved`.
{
"payment_id": "a7b2...",
"amount": 5000,
"reason": "Customer cancelled the order"
}{ "id": "b91c...", "reference": "rf_41d0...", "status": "requested", "amount": 5000.0, "reason": "Customer cancelled the order" }Stuck integrating Business payments: refund a customer?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.
Business payments: activity and issues
/v1/business/eventsA plain record of what has happened on your account: issues with a payment, refunds, withdrawals and when money became available. The same things are sent to your webhooks: payment.settled, payment.failed, payment.issue, payment.issue_resolved, refund.requested, refund.processed, refund.rejected, refund.failed, payout.requested, payout.paid, payout.failed, payout.rejected.
{
"events": [
{ "kind": "refund.processed", "message": "₦5,000.00 refunded to Ada Obi", "created_at": "2026-10-12T11:00:00Z" }
]
}Stuck integrating Business payments: activity and issues?
Open a ticket and our technical team will help you get it working. We reply by email. Or WhatsApp or call +234 913 995 7618.

