Skip to content
Lira APILira API

Identity/KYC Verification in Ghana

Ghana Card Facial Verification

Verify that a person physically present is the genuine holder of a Ghana Card by matching a live selfie against the cardholder's record. This runs a liveness check on the photo and a 1:1 face match, then returns the holder's identity details when the face matches.

Use this when you need to prove "this person is who they claim to be", not just that the card number exists. For a plain document lookup without a photo, use Ghana Card, Voter ID & Passport instead.

Prerequisites

You'll need an API key. See Quickstart or Authentication if you don't have one yet.

Note

Verification endpoints use an API key in the X-API-Key header, not a Bearer token. Verification POST requests also accept an optional Idempotency-Key header.


Prepare the selfie

The endpoint expects a live face photo of the person being verified, not a scan of the card. Encode the image as base64 and send it inline, either as a raw base64 string or a data URI (data:image/jpeg;base64,...).

Terminal
SELFIE="data:image/jpeg;base64,$(base64 -i ./selfie.jpg)"
RequirementDetail
ContentA single, clear, front-facing live photo of the person's face.
FormatJPEG or PNG, base64-encoded (data URI or raw base64).
SizeUp to ~7 MB decoded. Smaller, well-lit photos verify faster and more reliably.
FacesExactly one face in frame. Multiple faces are rejected.

Make the verification request

Set country to GH and idType to ghana_card, and supply the selfie under images.selfie.

Terminal
curl -X POST https://api.lira.com/api/v1/verify/identity/facial \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Idempotency-Key: YOUR_IDEMPOTENCY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "country": "GH",
    "idType": "ghana_card",
    "idNumber": "GHA-123456789-0",
    "images": {
      "selfie": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/..."
    }
  }'

Request body fields

FieldTypeRequiredDescription
countrystringYesAlways GH. Facial verification is currently supported for Ghana only.
idTypestringYesAlways ghana_card.
idNumberstringYesThe Ghana Card number, 6–20 alphanumeric characters and dashes (e.g. GHA-123456789-0).
images.selfiestringYesBase64-encoded live face photo (data URI or raw base64).
modestringNosync (default). Facial verification is synchronous only.
validationobjectNoOptional fields to cross-check against the matched record. See below.

Info

Sandbox: Use a sandbox API key to exercise the flow without incurring charges. See Environments.


Optional validation (cross-check)

You can include a validation object to check whether specific caller-provided fields match the matched cardholder record. The response includes a validation object with per-field results, and the verification status becomes inconclusive if any submitted field does not match, even when the face matched.

Terminal
curl -X POST https://api.lira.com/api/v1/verify/identity/facial \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "country": "GH",
    "idType": "ghana_card",
    "idNumber": "GHA-123456789-0",
    "images": { "selfie": "data:image/jpeg;base64,/9j/4AAQ..." },
    "validation": {
      "firstName": "Daniel",
      "lastName": "Mensah",
      "dateOfBirth": "1990-01-15"
    }
  }'
Validation fieldTypeMatch rule
firstNamestringCase-insensitive, trimmed.
lastNamestringCase-insensitive, trimmed.
dateOfBirthstringExact match. Format YYYY-MM-DD.

Note

The selfie is never stored and never logged. It is used only for the live match and then discarded. Cross-check fields are never persisted either; only the boolean match result is stored.


Read the result

Successful verification (face matched)

JSON
{
  "id": "c3d4e5f6-...-...-...-...",
  "status": "success",
  "verificationType": "GHANA_CARD_FACIAL",
  "idType": "ghana_card",
  "country": "GH",
  "identifier": "GHA-123456789-0",
  "verifiedAt": "2026-06-05T10:00:00.000Z",
  "origin": "api",
  "verified": true,
  "facialMatch": true,
  "firstName": "Daniel",
  "lastName": "Mensah",
  "dateOfBirth": "1990-01-15",
  "gender": "MALE",
  "placeOfBirth": "Greater Accra",
  "validation": null
}

Inconclusive verification (cross-check mismatch)

The face matched, but a submitted validation field did not match the record.

JSON
{
  "id": "c3d4e5f6-...-...-...-...",
  "status": "inconclusive",
  "verificationType": "GHANA_CARD_FACIAL",
  "idType": "ghana_card",
  "country": "GH",
  "identifier": "GHA-123456789-0",
  "verifiedAt": "2026-06-05T10:00:00.000Z",
  "origin": "api",
  "verified": false,
  "facialMatch": true,
  "firstName": "Daniel",
  "lastName": "Mensah",
  "dateOfBirth": "1990-01-15",
  "gender": "MALE",
  "placeOfBirth": "Greater Accra",
  "validation": {
    "firstName": { "value": "Danielle", "match": false },
    "lastName":  { "value": "Mensah",   "match": true },
    "dateOfBirth": { "value": "1990-01-15", "match": true }
  }
}

Failed verification (no match or unusable photo)

JSON
{
  "id": "c3d4e5f6-...-...-...-...",
  "status": "failed",
  "verificationType": "GHANA_CARD_FACIAL",
  "idType": "ghana_card",
  "country": "GH",
  "identifier": "GHA-123456789-0",
  "verifiedAt": "2026-06-05T10:00:00.000Z",
  "origin": "api",
  "facialMatch": false,
  "error": {
    "code": "FACE_MATCH_FAILED",
    "message": "Facial verification did not match"
  }
}

Response fields

FieldTypeDescription
idstringUnique verification ID.
statusstringsuccess, inconclusive, failed, or error.
verificationTypestringAlways GHANA_CARD_FACIAL.
idTypestringThe idType you submitted (ghana_card).
countrystringAlways GH.
identifierstringThe Ghana Card number you submitted.
verifiedAtstringISO 8601 timestamp.
originstringapi (API-key requests) or dashboard (logged-in dashboard requests).
verifiedbooleantrue only when status is success.
facialMatchbooleantrue when the selfie matched the cardholder (liveness + face match passed); false on a failed check.
firstNamestringFirst name as recorded by the registry. May be null.
lastNamestringLast name as recorded by the registry. May be null.
dateOfBirthstringDate of birth, YYYY-MM-DD. May be null.
genderstringGender as recorded by the registry. May be null.
placeOfBirthstringRegion/place of birth as recorded by the registry. May be null.
validationobjectPresent only when validation was included in the request. Contains per-field match results.
errorobjectPresent when status is failed or error.
error.codestringMachine-readable failure code. See error handling table below.
error.messagestringHuman-readable description.

Error handling

Facial failures return a stable error.code your client can branch on. Several are retake-able: show the user the message and let them capture a new photo.

error.codeCauseAction
FACE_MATCH_FAILEDThe face did not match the cardholder recordGenuine non-match; do not retry blindly; route to your fraud/manual review flow
FACIAL_LIVENESS_FAILEDLiveness check failed (e.g. a photo of a photo)Ask the user to retake a live selfie
FACE_NOT_DETECTEDNo face found in the imageAsk the user to retake with their face clearly in frame
FACE_QUALITY_LOWFace too small, too close, partially covered, or image too low-resolutionAsk the user to retake in good lighting, framing their whole face
MULTIPLE_FACES_DETECTEDMore than one face in the imageAsk the user to retake with only their face in frame
IDENTIFIER_NOT_FOUNDGhana Card number not foundAsk the user to check the card number
FACIAL_VERIFICATION_FAILEDThe check could not be completedAsk the user to retake; retry once before failing the flow
PROVIDER_RATE_LIMITEDToo many requests in a short windowBack off and retry
PROVIDER_UNAVAILABLEVerification temporarily unavailableRetry with exponential backoff

A malformed request (missing images.selfie, a bad card number, or unsupported country/idType) returns HTTP 422 with a validation error before any verification runs.

For the full error code reference, see Errors.

Warning

Do not surface raw error.code values directly to end users. Map them to friendly, actionable messages (e.g. FACE_QUALITY_LOW → "We couldn't read your photo clearly. Please retake it in good lighting.").


Next steps