Migrating from Persona
A field-tested mapping from Persona Inquiry templates and webhooks to VEREID verification sessions and events.
Last updated 2026-05-20
Persona's API is one of the cleanest in the KYC space. Migrating to VEREID is mostly a one-to-one renaming exercise, with the exception of a few honest-tier wording fixes you will need to make in your own UI and downstream systems.
Object mapping
| Persona | VEREID |
|---|---|
| Inquiry | Verification Session (/v1/verify/sessions) |
| Inquiry template | Session template (tiers array) |
| Verification | Per-check signal in signals[] |
| Report | Bundled in the session response |
| Account | User (users row, owned by your tenant) |
| Document submission | documents.uploaded event |
| Selfie submission | verification.selfie_captured event |
Inquiry status: started, pending, completed, failed, expired | pending, in_progress, completed, declined, expired |
| Webhook | Webhook (HMAC-SHA256 — same algorithm, different header) |
Template mapping
Persona templates are configured per inquiry type. VEREID expresses the same intent via the tiers array on session creation:
| Persona template | VEREID tiers |
|---|---|
| Government ID + Selfie | ["T1", "T2"] |
| Government ID + Selfie + Database | ["T1", "T2", "T3"] |
| Government ID + Database + Sanctions | ["T1", "T3"] |
| Business verification | ["T4"] |
| Government ID + Selfie + ePassport NFC | ["T1", "T2", "T5"] (requires mobile SDK) |
// before (Persona)
const inquiry = await persona.inquiries.create({
template_id: "itmpl_xxx",
reference_id: "user_42",
});
// after (VEREID)
const session = await vereid.verify.sessions.create({
tiers: ["T1", "T2"],
reference: "user_42",
redirect_url: "https://yourapp.com/done",
});session = client.verify.sessions.create(
tiers=["T1", "T2"],
reference="user_42",
redirect_url="https://yourapp.com/done",
)Webhook envelope mapping
Persona ships data + included[]; VEREID ships a flat data block plus a signals[] array for verification events. Both are HMAC-SHA256 signed with a 5-minute replay window — the algorithm is identical; only the header name differs.
// before
const expected = crypto
.createHmac("sha256", PERSONA_SECRET)
.update(req.body)
.digest("hex");
const ok = expected === req.header("persona-signature");
// after
import { verifyWebhook } from "@vereid/js/webhooks";
const ok = verifyWebhook(
req.body,
req.header("vereid-signature"),
VEREID_SECRET,
);Event-type mapping
| Persona event | VEREID event |
|---|---|
inquiry.created | verification.session.created |
inquiry.started | verification.in_progress |
inquiry.completed | verification.completed |
inquiry.expired | verification.expired |
inquiry.failed | verification.failed |
report.run.completed | (part of verification.completed.signals[]) |
case.opened | verification.review.opened |
case.resolved | verification.review.resolved |
Status field mapping
const STATUS_MAP = {
created: "pending",
pending: "pending",
started: "in_progress",
completed: "completed",
failed: "declined",
expired: "expired",
approved: "completed",
declined: "declined",
needs_review: "in_progress",
};Honest-tier rewording
Most Persona integrations have UI copy that reads roughly "Government-verified" or "ID verified by government" when an inquiry completes. Do not carry that copy over. Use the verification tiers page as the source of truth. A T1+T2 result is "Photo + liveness verified", not "Government verified". A T5 result is "Document is genuine per ICAO 9303 Passive Authentication — does NOT verify the holder against any government database" — that exact sentence.
Customers who carry over inflated copy face the same regulatory exposure they had with Persona; we will not let our marketing channels say what theirs did.
Backfill — porting historical inquiries
If you want to mirror existing inquiries into VEREID for a unified history (recommended, since downstream analytics depend on a single source of truth), use vereid persona import:
vereid persona import \
--persona-api-key=$PERSONA_KEY \
--since=2024-01-01 \
--map='reference_id=reference,fields.name_first=first_name,fields.name_last=last_name'This streams every Persona inquiry into /v1/verify/sessions/imported, preserving created_at, reference, and the decision. Imported sessions are flagged with source=persona_import and do not bill — they are evidence-only.
Decommissioning
Run both vendors in parallel for one billing cycle. Once verification.completed deliveries are flowing into your downstream systems and tickets are quiet, disable the Persona webhook delivery, then revoke their API keys.
We have a one-page comparison brief at vereid.com/persona-vs-vereid that is helpful for getting buy-in from non-engineering stakeholders.