Identivia-API is an Express-based bridge between third-party onboarding experiences and the Identivia identity verification backend. It authenticates against PocketBase, creates or reuses applicant profiles, exposes status updates, and accepts document uploads that enrich each record.
- Token-based partner access with configurable API keys
- PocketBase integration for profile storage and status history
- Idempotent profile creation that reuses existing records by document fingerprint
- Multipart upload pipeline for document images, photos, and facial videos
- Hardened CORS configuration covering the Identivia web clients
- Express server (
app.js) - Hosts HTTP endpoints, validates payloads, and brokers data to PocketBase. - PocketBase SaaS - Serves as the system of record for profiles and their status history.
- Multer - Processes multipart/form-data uploads in memory before streaming them to PocketBase.
- dotenv - Loads environment variables so secrets never live in source code.
- Node.js 18+ (for built-in
fetch,FormData, andFileglobals used by the PocketBase SDK) - npm (bundled with Node)
- A PocketBase service account with access to the
profilesandstatus_historycollections
- Install dependencies:
npm install
- Create or update
.env(do not commit it) and populate the values described below. - Start the server locally:
node app.js
- The API listens on port
3000. Point your frontend or API client athttp://localhost:3000during development.
All runtime configuration is provided through environment variables (typically declared in .env).
| Variable | Purpose | Default |
|---|
| PB_USER_EMAIL | PocketBase service account email | test@example.com |
| PB_USER_PASSWORD | PocketBase service account password | 1234567890 |
| IDENTIVIA_FRONTEND_URL | Base URL of the hosted Identivia flow | https://identivia.com |
Restart the server whenever these values change. Avoid committing real credentials to source control. The PocketBase instance URL is currently hard-coded to https://pocketbase.likweitan.eu.org inside app.js; update it if you host PocketBase elsewhere.
Provide the service account credentials. Missing credentials will now cause the server to fail authentication early instead of returning a 403 later on Vercel/other serverless runtimes.
Partner endpoints require a static API key. Provide it via the x-api-key header on every authenticated request. If a client cannot set custom headers, POST /api/profiles/create also checks the apiKey property in the JSON body. Requests missing a valid key receive 401 { "error": "Invalid or missing API key" }.
- Method:
POST - Path:
/api/profiles/create - Auth:
x-api-key(required) - Body: JSON
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Applicant full name |
document_type |
string | yes | e.g. passport, national_id, driver_license |
document_number |
string | yes | Document identifier |
nationality |
string | yes | ISO country code or plain-text country name |
The backend searches PocketBase for an existing record with the same document type, number, and country. If found, it returns that record instead of creating a duplicate.
New record (201):
{
"success": true,
"url": "https://identivia.com/RECORD_ID",
"id": "RECORD_ID"
}Existing record (200):
{
"success": true,
"url": "https://identivia.com/RECORD_ID",
"id": "RECORD_ID",
"message": "Existing record found"
}- Method:
GET - Path:
/api/profiles/:id - Auth: None (public status lookup)
Returns the profile from PocketBase and augments it with the latest status history entry (if present).
{
"success": true,
"data": {
"name": "Jane Doe",
"document_type": "passport",
"document_number": "A1234567",
"nationality": "SG",
"verification_status": "unverified",
"status": "pending_review",
"createdAt": "2025-10-23T12:34:56.789Z"
}
}If the record cannot be found, the service responds with 404 { "error": "Identivia record not found", "message": "Invalid or expired ID" }.
A second handler (
GET /api/profiles/:idwith API key middleware) exists for backwards compatibility, but the public handler responds first and is the documented interface.
- Method:
PATCH - Path:
/api/profiles/:id - Auth:
x-api-key(required) - Body:
multipart/form-data
Use this endpoint to upload verification artifacts and update profile metadata. Accepted fields:
| Field | Type | Notes |
|---|---|---|
verification_status |
text | Must be one of unverified, pending, verified, rejected |
document_type |
text | Optional override |
document_number |
text | Optional override |
document_name |
text | Display name for the document |
country |
text | Country associated with the document |
document_front |
file | Front image upload |
document_back |
file | Back image upload |
facial_photo |
file | Applicant photo |
facial_video |
file | Liveness or facial video |
Example request (PowerShell escaping omitted):
curl -X PATCH "http://localhost:3000/api/profiles/RECORD_ID" \
-H "x-api-key: your-secret-api-key-1" \
-F "verification_status=verified" \
-F "document_front=@front.jpg" \
-F "facial_photo=@selfie.png"Successful responses include the updated PocketBase fields and file references.
- Method:
POST - Path:
/api/status_history/:id - Auth:
x-api-key(required) - Body: JSON
| Field | Type | Required | Description |
|---|---|---|---|
previous_status |
string | yes | Status before the change |
new_status |
string | yes | Updated status value |
notes |
string | yes | Free-form notes describing the change |
liveness_session_id |
string | no | Face Liveness session identifier associated with the update |
liveness_confidence |
number | no | Confidence score reported by AWS Face Liveness |
liveness_status |
string | no | Normalized liveness decision (for example live, not_live) |
The route verifies the profile exists, then stores a record in the status_history collection attributed to the authenticated PocketBase user.
When available, include the liveness fields to correlate manual review activity with the corresponding AWS Face Liveness session that generated the confidence score.
- Method:
GET - Path:
/ - Response:
{
"status": "OK",
"service": "Identivia-API",
"recordsStored": 0
}Use this endpoint for uptime probes or quick smoke tests.
Only the following origins are allowed by default:
https://demo.identivia.comhttps://app.identivia.comhttp://localhost:3000
Requests from other origins are rejected with a CORS error. Update the allowedOrigins array in app.js if you deploy additional web clients.
- Replace the in-memory
identiviaDataStorefallback with a persistent store if you ever rely on it. - Terminate TLS and expose the API over HTTPS.
- Store environment variables in a secure secrets manager and rotate API keys regularly.
- Add rate limiting and request logging middleware before going live.
- Consider background jobs or webhooks if you need to notify clients about status changes proactively.