Quick Start
Get API Key
Find it in your Business Dashboard under Settings โ API
Submit Verification
POST to /api/business/verify with address + type
Poll for Results
GET /findings every 30 s until status is COMPLETED
Authentication
Every request must include your business API key as a header. You can find and rotate your key in the Business Dashboard โ Settings โ API Keys.
x-api-key: lv_biz_xxxxxxxxxxxxxxxxxxxxxxxxVerification Types
The API supports two types of verification, controlled by the type field. Each type has its own quota tracked separately on your account.
Basic Verification
type: "basic"Address + government record cross-check. Ideal for quick title confirmation, pre-deal screening, or high-volume workflows.
findings objectFull Verification
type: "full"Everything in Basic, plus forensic AI document analysis. Required for mortgage due diligence, legal conveyancing, and compliance workflows.
findings + documentIntegrityFile Upload (Full Verification)
Files must be sent as Base64 data URIs or public HTTPS URLs. Accepted document types: title deeds, survey plans, receipts, and any property document in PNG, JPG, JPEG, or PDF format.
Converting files to Base64
function fileToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result); // "data:image/png;base64,..."
reader.onerror = reject;
});
}
// Convert multiple files before submitting full verification
const prepareFiles = async (fileList) => {
return Promise.all(Array.from(fileList).map(fileToBase64));
};1 - Submit a Verification
Submits a new verification request against your business quota. On success you receive a verificationId -keep it to poll for results.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Always | "basic" or "full" |
address | string | Always | Full property address to verify |
files | string[] | Full only | Base64 data URIs or public URLs of property documents |
state | string | Optional | State name (e.g. Lagos) |
lga | string | Optional | Local Government Area |
landsize | string | Optional | Size string e.g. "500sqm" |
latitude | number | Optional | GPS latitude |
longitude | number | Optional | GPS longitude |
Basic verification - minimal request
curl -X POST "https://app.landverify.ng/api/business/verify" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_BUSINESS_API_KEY" \
-d '{
"type": "basic",
"address": "14 Adeola Odeku Street, Victoria Island, Lagos"
}'Basic verification - with optional fields
curl -X POST "https://app.landverify.ng/api/business/verify" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_BUSINESS_API_KEY" \
-d '{
"type": "basic",
"address": "14 Adeola Odeku Street, Victoria Island, Lagos",
"state": "Lagos",
"lga": "Eti-Osa",
"landsize": "600sqm",
"latitude": 6.4281,
"longitude": 3.4219
}'Full verification - with documents
curl -X POST "https://app.landverify.ng/api/business/verify" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_BUSINESS_API_KEY" \
-d '{
"type": "full",
"address": "14 Adeola Odeku Street, Victoria Island, Lagos",
"files": [
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...",
"data:application/pdf;base64,JVBERi0xLjQK..."
],
"state": "Lagos",
"lga": "Eti-Osa",
"landsize": "600sqm",
"latitude": 6.4281,
"longitude": 3.4219
}'Success response (201)
{
"success": true,
"verificationId": "a7f3c891-12bd-4e67-9053-cde72b1a3e88",
"type": "basic",
"status": "SUBMITTED",
"quota": {
"used": 4,
"limit": 20,
"remaining": 16
},
"submittedAt": "2025-10-05T09:15:00.000Z",
"message": "Verification submitted successfully. Poll the findings endpoint for results."
}Response fields
verificationId-UUID to poll for resultstype-basic or fullstatus-Always SUBMITTED on creationquota.used-Verifications used this periodquota.limit-Your plan's quota for this typequota.remaining-How many you have left2 - Get Verification Findings
Poll this endpoint with the verificationId from Step 1 to check for results. Verification typically completes within a few hours.
Example request
curl "https://app.landverify.ng/api/business/verify/a7f3c891-12bd-4e67-9053-cde72b1a3e88/findings" \
-H "x-api-key: YOUR_BUSINESS_API_KEY"Response - in progress
{
"verificationId": "a7f3c891-12bd-4e67-9053-cde72b1a3e88",
"type": "basic",
"status": "IN_PROGRESS",
"findings": null,
"documentIntegrity": null,
"updatedAt": "2025-10-05T09:20:00.000Z"
}Response - basic verification complete
When complete, findings is populated. For basic verifications, documentIntegrity is always null.
{
"verificationId": "a7f3c891-12bd-4e67-9053-cde72b1a3e88",
"type": "basic",
"status": "COMPLETED",
"findings": {
"comments": "Property is verified. Clean title with no encumbrances detected. Suitable for residential development pending standard zoning approvals.",
"isRegisteredTitledVerified": true,
"isPropertyFreeOfAcquisition": true,
"DoesAddressMatchSurvey": true,
"erosionOrFloodRisk": false,
"locatedInMixedArea": true,
"suitableTopography": true
},
"documentIntegrity": null,
"updatedAt": "2025-10-05T11:45:00.000Z"
}Response - full verification complete
Full verifications additionally return a documentIntegrity object with the AI forensic analysis of your submitted documents.
{
"verificationId": "b9d2e712-44ca-4f81-a017-8fa913c2d501",
"type": "full",
"status": "COMPLETED",
"findings": {
"comments": "Property verified with full document review. Title is valid and unencumbered.",
"isRegisteredTitledVerified": true,
"isPropertyFreeOfAcquisition": true,
"DoesAddressMatchSurvey": true,
"erosionOrFloodRisk": false,
"locatedInMixedArea": true,
"suitableTopography": true
},
"documentIntegrity": {
"overallScore": 94,
"verdict": "AUTHENTIC",
"documentsAnalysed": 2,
"issues": [],
"checks": {
"stampDutyPresent": true,
"signatureConsistency": true,
"dateSequenceValid": true,
"surveyNumberMatchesTitle": true,
"ownerNameConsistency": true,
"documentAgeConsistent": true
},
"riskFlags": []
},
"updatedAt": "2025-10-05T12:00:00.000Z"
}documentIntegrity fields explained
overallScorenumber0โ100 authenticity score across all submitted documentsverdictstringAUTHENTIC | SUSPICIOUS | FRAUDULENTdocumentsAnalysednumberCount of documents processedissuesstring[]Human-readable descriptions of detected problemschecksobjectBoolean results for each forensic check (see example above)riskFlagsstring[]High-severity flags requiring immediate attentionPolling best practices
Complete JavaScript Example
A production-ready helper that submits a verification and polls until complete:
// JavaScript -submit a basic verification
const verifyProperty = async (address) => {
const response = await fetch(
"https://app.landverify.ng/api/business/verify",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": process.env.LANDVERIFY_API_KEY,
},
body: JSON.stringify({ type: "basic", address }),
}
);
if (!response.ok) {
const err = await response.json();
throw new Error(err.message);
}
const { verificationId } = await response.json();
return verificationId;
};
// Poll until complete (max 30 min)
const waitForFindings = async (verificationId) => {
const POLL_INTERVAL = 30_000; // 30 seconds
const TIMEOUT = 30 * 60 * 1000; // 30 minutes
const start = Date.now();
while (Date.now() - start < TIMEOUT) {
await new Promise(r => setTimeout(r, POLL_INTERVAL));
const res = await fetch(
`https://app.landverify.ng/api/business/verify/${verificationId}/findings`,
{ headers: { "x-api-key": process.env.LANDVERIFY_API_KEY } }
);
const data = await res.json();
if (data.status === "COMPLETED" && data.findings) {
return data; // { findings, documentIntegrity, status }
}
}
throw new Error("Verification timed out after 30 minutes.");
};
// Usage
const id = await verifyProperty("14 Adeola Odeku St, VI, Lagos");
const result = await waitForFindings(id);
console.log(result.findings.comments);Error Reference
All errors follow a consistent shape with a machine-readable error code and a human-readable message you can display directly to users.
Client errors (4xx)
400VALIDATION_ERRORMissing/invalid field401UNAUTHORIZEDBad or missing API key403QUOTA_EXCEEDEDPlan quota exhausted404NOT_FOUNDUnknown verificationId429RATE_LIMITEDToo many requestsServer errors (5xx)
500INTERNAL_ERRORUnexpected server error503SERVICE_UNAVAILABLETemporary outage// 400 - Missing required field
{
"success": false,
"error": "VALIDATION_ERROR",
"message": "address is required for all verification types.",
"field": "address"
}
// 400 -Files missing for full verification
{
"success": false,
"error": "VALIDATION_ERROR",
"message": "files are required for full verification. Please provide at least one document (title deed, survey plan, etc.).",
"field": "files"
}
// 400 - Invalid verification type
{
"success": false,
"error": "VALIDATION_ERROR",
"message": "type must be either 'basic' or 'full'.",
"field": "type"
}
// 401 - Bad API key
{
"success": false,
"error": "UNAUTHORIZED",
"message": "Invalid or inactive API key. Check your key in the Business Dashboard."
}
// 403 - Quota exhausted
{
"success": false,
"error": "QUOTA_EXCEEDED",
"message": "Your basic verification quota is exhausted (20/20 used). Contact support to top up.",
"quota": { "used": 20, "limit": 20, "remaining": 0 }
}
// 404 - Verification not found
{
"success": false,
"error": "NOT_FOUND",
"message": "Verification 'xyz' not found or does not belong to your account."
}
// 429 - Rate limited
{
"success": false,
"error": "RATE_LIMITED",
"message": "Too many requests. Please wait before retrying.",
"retryAfterSeconds": 30
}Ready to integrate?
Your API key is in your Business Dashboard. Stuck on something? Our team responds within 2 business hours.
