Start a process and get the Human Token and the person's intelligence.
POST /v1/processes
Starts a process with one of the flows and answers with id, state and the result in data: the Human Token and the person's intelligence, data.ndocs.
Before you call
- Human Plugin is running and
GET /health/readyanswers200. - Your access key is enabled for the flow you use.
- If you send a document, its
typeis in the attribute catalog.
Flows
The flow field chooses what the process does. Human Plugin runs these flows, in two integration models:
- API Only: your back-end sends the selfie in
imageBase64, and the create answers with the result. - Human Token Journey: the person takes the selfie in the capture journey and returns to your
callbackUri. The create answers with atokenand alink, and you read the result with Get a process.
| Flow | Description | Possible result | Integration components required | Example |
|---|---|---|---|---|
api+humantoken | Receives a selfie via your back-end and generates the Human Token, a unique face identifier. The answer is final: no capture, no second call. | PROCESS_STATE_FINISHEDPROCESS_STATE_FAILED | API | |
humantoken | Captures a selfie in the capture journey, with a liveness check, and generates the Human Token. The create returns the `token` and the `link`; read the result when the capture ends. | PROCESS_STATE_CREATEDPROCESS_STATE_FINISHEDPROCESS_STATE_FAILED | APIWeb | |
humantoken+revalidation | Captures a selfie and compares the face with the Human Token you expect. Returns whether it is the same person or not, for example before a sensitive action. | PROCESS_STATE_CREATEDPROCESS_STATE_FINISHEDPROCESS_STATE_FAILED | APIWeb |
clientId, correlationId and credential are the same in every flow.
Request
{
"flow": "api+humantoken",
"clientId": "client-a",
"correlationId": "onboarding-001",
"credential": { "type": "DUI_TYPE_NG_BVN", "value": "<document-number>" },
"imageBase64": "<base64 selfie>"
}
Common fields
| Field | Required | Limit (bytes) | Notes |
|---|---|---|---|
flow | Yes | 64 | One of the flows |
clientId | Yes | 128 | Your id for the client. The intelligence counts distinct values |
correlationId | Yes | 128 | Your reference for this process. Unique: one that another process already has, whatever its state, is refused with 409 |
credential | Yes, but may be empty | The key must be present. See below | |
credential.type | With a document | A code of the attribute catalog, exact and case-sensitive | |
credential.value | With a document | 64 | The document number |
flow, clientId and correlationId must be strings, without control characters and without leading or trailing whitespace. Invalid values are rejected, never rewritten.
The credential field
- With a document: an object with exactly
typeandvalue, both strings, sent together. - Without a document:
nullor{}. The process still counts as a transaction and as a client in the intelligence. - Omitted, or an object with empty strings: rejected with
400 MISSING_CREDENTIAL_TYPE. This catches a misspelled key before anything is processed. - Any other key inside
credentialis rejected.
Flow fields
What each flow adds to the common fields:
| Field | Flow | Required | Value |
|---|---|---|---|
imageBase64 | api+humantoken | Yes | The selfie in base64. PNG, JPEG or WebP, up to 800 KB |
callbackUri | humantoken, humantoken+revalidation | Yes | Where the person returns when the capture ends: a page of yours, or your app's URL scheme |
references | humantoken+revalidation | Yes | One item with the Human Token you expect, as in the example above |
Human Plugin does not store these fields, and a misspelled optional field may be ignored without an error.
Use a frontal, well-lit selfie of one face with api+humantoken. A value that is not an image is refused, and the process is stored as failed: see Flow refusals.
With humantoken+revalidation, the result has humanTokenMatch instead of humanToken:
"true": it is the same person. The process counts for that person, andndocsdescribes them.- Anything else, or a capture that is not live: it is not confirmed. The process counts for no one, and there is no
ndocs.
PROCESS_STATE_FINISHED is answered in both cases: read humanTokenMatch. See Get a process.
A few names are reserved by Human Plugin and refused with 400 INVALID_REQUEST, such as clientReference. So is another spelling of Human Plugin's own fields, such as client_id, correlation_id or Flow: only flow, clientId, correlationId and credential are read, spelled exactly like that.
Body rules
- One JSON object, at most 2 MiB (about enough for a selfie in base64). A larger body is refused with
400 REQUEST_TOO_LARGE. - Nothing may follow the JSON object.
Response
201 Created, with Location: /v1/processes/<id>.
{
"id": "b063041c-7529-4e70-a2b4-c71c00f19801",
"state": "PROCESS_STATE_FINISHED",
"data": {
"humanToken": { "value": "6d3d71…", "status": "validated" },
"ndocs": {
"distinctClientsCount": 2,
"transactionsCount": 3,
"firstSeen": "2026-09-08",
"lastSeen": "2026-11-03",
"credentials": [
{ "type": "DUI_TYPE_NG_BVN", "countryCode": "NGA", "distinctCredentialCount": 1 }
]
}
}
}
idis Human Plugin's UUID. Each accepted request creates a new one.stateis the local status. See lifecycle.humantokenandhumantoken+revalidationanswerPROCESS_STATE_CREATEDwith atokenand alink. These are returned once and are never stored: keep them. See Human Token Journey and the capture guide for your platform.data.ndocsis the person's intelligence. It can be absent: see Intelligence.
The result in data
A finished process has these fields in data. The Journey flows return them when you read the process after the capture.
| Field | When | Value |
|---|---|---|
humanToken | api+humantoken, humantoken | Who the person is: value is the Human Token, and status is validated when it was generated |
humanTokenMatch | humantoken+revalidation | "true" when it is the same person as the Human Token in references |
liveness | Flows that check liveness, such as the Journey flows | value is live when the capture came from a live person, or not_live when it did not; status is validated when the check ran |
ndocs | When there is intelligence for the person | The person's intelligence |
A Journey result looks like this:
{
"id": "b063041c-7529-4e70-a2b4-c71c00f19801",
"state": "PROCESS_STATE_FINISHED",
"data": {
"humanToken": { "value": "6d3d71…", "status": "validated" },
"liveness": { "value": "live", "status": "validated" },
"ndocs": { "distinctClientsCount": 1, "transactionsCount": 1, "firstSeen": "2026-11-05", "lastSeen": "2026-11-05", "credentials": [] }
}
}
Check liveness before you trust the result: with not_live, treat the capture as failed and ask the person to try again. A process with not_live does not count toward anyone's intelligence.
Errors
| Status | message | Meaning |
|---|---|---|
| 400 | INVALID_REQUEST, REQUEST_TOO_LARGE | Not one JSON object, a reserved field, a wrong type, or a body over 2 MiB |
| 400 | MISSING_<FIELD>, INVALID_<FIELD> | A required field is missing or malformed, such as MISSING_CLIENT_ID |
| 401 | Empty ("") | Unico refused your access key: it is missing, wrong or no longer valid. The process is stored as failed. Check HUMAN_API_ACCESS_KEY |
| 409 | CORRELATION_ID_ALREADY_USED | Another process already has the correlationId. Nothing is stored or sent |
| 422 | ATTRIBUTE_TYPE_NOT_SUPPORTED | credential.type is not in the catalog. Nothing is stored or sent |
| 4xx | The flow's message | The flow refused the request, for example an invalid image. See Flow refusals |
| 502 | UPSTREAM_UNAVAILABLE | The process could not be confirmed in time |
| 503 | DATABASE_UNAVAILABLE | The database failed. Nothing was processed |
| 500 | INTERNAL | Unexpected error |
Flow refusals
When a flow refuses the request, the create answers 4xx with the reason in message, in the usual envelope. The most common:
message | Cause |
|---|---|
invalid flow | flow is not a flow enabled for your account |
INVALID_IMAGE (400) | api+humantoken without imageBase64 |
INVALID_REQUEST (400) | imageBase64 is not an image in base64 |
IMAGE_TOO_LARGE | The image is over 800 KB |
UNSUPPORTED_IMAGE_FORMAT | The image is not PNG, JPEG or WebP |
PERMISSION_DENIED (403) | Your access key is not enabled for this flow |
A refused process is stored as failed. Correct the request and create a new process with a new correlationId.
Read Errors and retries before adding retry logic: a new attempt needs a new correlationId.