Developers
API documentation
A small REST API to create identity verifications, collect documents through a hosted flow, and receive the result via polling or signed webhooks.
The base URL is https://avalkyc.com/api/v1. All requests and responses are JSON. Every object is created in either live or test mode, determined by the API key you use.
Authentication
Authenticate with an API key in the Authorization header. Create and manage keys under Settings → API keys. A key is shown only once at creation. Keys starting with sk_test_ operate on isolated test data.
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxCreate a verification
POST /verifications creates a session and returns a hosted_url you redirect the applicant to. Body fields are optional.
curl -X POST https://avalkyc.com/api/v1/verifications \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"document_type": "passport",
"applicant": { "name": "Alex Morgan", "country": "USA" }
}'201 Response
{
"id": "cmq1...",
"reference": "VER-A37548CB",
"status": "pending",
"mode": "live",
"document_type": "passport",
"applicant": { "name": "Alex Morgan", "email": null, "dob": null, "country": "USA" },
"hosted_url": "https://avalkyc.com/verify/cmq1...",
"created_at": "2026-06-05T20:03:47.018Z",
"updated_at": "2026-06-05T20:03:47.018Z",
"result": null
}The hosted flow
Redirect the applicant to hosted_url. They capture their document and a selfie; AvalKYC runs OCR + MRZ checks, biometric face match, liveness, and AML screening, then produces a decision. When it completes, the verification's status and result update and a webhook fires.
Web SDK (embed)
Prefer not to redirect? Drop in the Web SDK and the hosted flow opens in a modal over your page, returning the outcome to a callback. Create the session server-side (so your API key never touches the browser), then pass its hosted_url to AvalKYC.open.
<script src="https://avalkyc.com/sdk/avalkyc.js"></script>
<button id="verify">Verify my identity</button>
<script>
document.getElementById("verify").onclick = function () {
AvalKYC.open({
// hosted_url returned by POST /api/v1/verifications
url: "https://avalkyc.com/verify/<session>",
onComplete: function (r) {
// r = { status, reference } — no PII crosses the boundary
console.log("Verification", r.reference, "→", r.status);
},
onClose: function () { /* user dismissed the modal */ },
});
};
</script>The widget requests camera access, validates the message origin, and supports desktop→phone QR handoff inside the modal. It posts only status and reference — the full result stays server-side, retrievable via the API or webhook.
Retrieve & list
Poll for the result, or list recent verifications (scoped to your key's mode).
curl https://avalkyc.com/api/v1/verifications/{id} \
-H "Authorization: Bearer sk_live_..."
curl https://avalkyc.com/api/v1/verifications \
-H "Authorization: Bearer sk_live_..."Instant re-verification
Every approved verification with a face match auto-issues a reusable identity token (rid_…, in the dashboard). A returning applicant can then re-verify in one call with just a selfie — we run a live face match against their stored biometric, liveness, and a fresh AML screen. No document re-capture.
curl -X POST https://avalkyc.com/api/v1/reverify \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"token": "rid_9f8a7b6c...",
"selfie": "data:image/jpeg;base64,/9j/4AAQ..."
}'Returns a new verification (status approved on a match) with reused_from set to the original. Revoke a token any time from the dashboard.
Business verification (KYB)
Verify a companyinstead of a person. We resolve it in the global LEI register (GLEIF), screen the entity, its owners, and officers against sanctions & PEP lists, and return a risk decision — synchronously, in one call.
curl -X POST https://avalkyc.com/api/v1/business \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"legal_name": "Apple Inc",
"jurisdiction": "US-CA",
"officers": [
{ "name": "Jane Smith", "role": "ubo" }
]
}'The response includes the registry record (LEI, status, registration, addresses), the ownership graph, every screening hit, and a risk_level / status. Retrieve or list with the same key:
curl https://avalkyc.com/api/v1/business/{id} \
-H "Authorization: Bearer sk_live_..."
curl https://avalkyc.com/api/v1/business \
-H "Authorization: Bearer sk_live_..."Proof of address
Verify a residential address from a document. Upload a utility bill, bank statement, or government letter (base64 or data URL); we OCR it, extract the address and date, check it's recent, and match the declared name.
curl -X POST https://avalkyc.com/api/v1/address-checks \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"image": "data:image/jpeg;base64,/9j/4AAQ...",
"declared_name": "Alex Morgan Taylor",
"declared_address": "42 Baker Street, London NW1 6XE"
}'The response includes extracted_address, document_date, name_match, is_recent, and a risk decision. Retrieve or list with the same key:
curl https://avalkyc.com/api/v1/address-checks/{id} \
-H "Authorization: Bearer sk_live_..."
curl https://avalkyc.com/api/v1/address-checks \
-H "Authorization: Bearer sk_live_..."NFC ePassport (Passive Authentication)
The gold-standard document check: verify the passport chip's cryptographic signature chain (ICAO 9303). Because reading the chip needs NFC hardware, a native mobile SDK (iOS CoreNFC / Android NFC) reads it and posts the SOD + data groups here, which runs Passive Authentication: data-group hashes, SOD signature, and issuer (DSC → CSCA) trust.
curl -X POST https://avalkyc.com/api/v1/nfc-verify \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"sod": "<base64 SOD from the chip>",
"data_groups": { "1": "<base64 DG1>", "2": "<base64 DG2>" }
}'Returns chip_authentic plus the three passive_auth checks and the MRZ read from the chip. Each scan is recorded — list them with GET /nfc-verify or in the dashboard under NFC ePassport, where you can also try it live (no passport needed).
Statuses
pending— created, awaiting document captureprocessing— running the pipelineapproved— passed all checksneeds_review— flagged for a human reviewerrejected— failed (e.g. sanctions hit, failed liveness)
Webhooks
Register endpoints in Settings → Webhooks. On completion we POST a verification.completed event (and a fraud.duplicateevent if the applicant's face or document matches a prior enrollment) signed with your endpoint secret:
X-AvalKYC-Event: verification.completed
X-AvalKYC-Signature: t=1717612345,v1=9f86d08...Verify the signature by recomputing the HMAC over `${t}.${rawBody}` with your secret:
import crypto from "crypto";
function verifySignature(secret, header, rawBody) {
const parts = Object.fromEntries(
header.split(",").map((kv) => kv.split("=")),
);
const expected = crypto
.createHmac("sha256", secret)
.update(`${parts.t}.${rawBody}`)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(parts.v1),
Buffer.from(expected),
);
}MCP server
AvalKYC ships a Model Context Protocol server so AI agents can run verifications directly. It speaks JSON-RPC 2.0 over Streamable HTTP at https://avalkyc.com/api/mcp, authenticated with the same API key. Point any MCP client at it:
{
"mcpServers": {
"avalkyc": {
"url": "https://avalkyc.com/api/mcp",
"headers": { "Authorization": "Bearer sk_live_..." }
}
}
}Tools: create_verification, get_verification, list_verifications, screen_transaction, verify_business, verify_email, and verify_phone. Or call it directly:
curl -X POST https://avalkyc.com/api/mcp \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Errors & rate limits
Errors use standard HTTP status codes with a JSON body. The API is rate-limited to 120 requests/minute per key.
{ "error": { "message": "Invalid or missing API key." } }401— invalid or missing API key404— verification not found (or belongs to another key/mode)429— rate limit exceeded
The full machine-readable spec lives at /api/openapi.json — import it into Postman or generate a client.