VVEREID Docs
guides

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

PersonaVEREID
InquiryVerification Session (/v1/verify/sessions)
Inquiry templateSession template (tiers array)
VerificationPer-check signal in signals[]
ReportBundled in the session response
AccountUser (users row, owned by your tenant)
Document submissiondocuments.uploaded event
Selfie submissionverification.selfie_captured event
Inquiry status: started, pending, completed, failed, expiredpending, in_progress, completed, declined, expired
WebhookWebhook (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 templateVEREID 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 eventVEREID event
inquiry.createdverification.session.created
inquiry.startedverification.in_progress
inquiry.completedverification.completed
inquiry.expiredverification.expired
inquiry.failedverification.failed
report.run.completed(part of verification.completed.signals[])
case.openedverification.review.opened
case.resolvedverification.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.