Persona's Inquiries API → the Naive verification primitive
POST /api/v1/inquiries, hand the subject a verification link, and read the result (ID scan,
selfie, database checks) back as an inquiry status or webhook. It does that job well, and the API
is mature. But it is also a separate vendor account:
- KYC lives behind its own API key, its own templates and themes, and its own dashboard — disconnected from wherever the verified person’s company, cards, phone, and secrets live.
- An inquiry’s
reference-idis a string tag back to a row in your user table. Persona knows the person passed KYC; it does not know that same person is the responsible party who then incorporates the company and owns its virtual card. - “This founder cleared KYC — now what is allowed to happen on their behalf?” is answered in Persona for verification, and in unrelated systems for formation, banking, and cards. The cleared identity has no shared accountability with the rest of the company’s footprint.
verification primitive gives the same capability —
hosted KYC for one or more company founders, with real-time status — but the person you verify is a
governed identity, not a tagged inquiry:
- The tenant user whose founders you KYC is the same identity that then forms the LLC, and owns its cards, phone number, email inboxes, and vault secrets.
- Verified PII (SSN, DOB, address) is pulled from the encrypted identity vault at formation time — it never lands in your database.
- When every member passes,
ready_for_formationflips totrue— KYC is structurally a step toward incorporation, not an isolated pass/fail you have to wire to a formation vendor yourself.
Persona is a trademark of its owner, used here for identification only. No endorsement or affiliation is implied.
Tested against: the Persona REST API (base
https://api.withpersona.com/api/v1, header
Persona-Version: 2025-10-27 — 2025-12-08 also valid — hosted flow at
https://inquiry.withpersona.com, docs snapshot June 2026), and the Naive Node SDK
@usenaive-sdk/server against the Naive API (base https://api.usenaive.ai/v1,
docs snapshot June 2026).Version notes:- Persona’s officially featured SDKs are client-side (persona-react / persona-web / mobile); the server-side integration is REST, which is what the “before” code below uses. There is no first-party server SDK to swap out.
- Persona verifies one subject per inquiry against a template you author (
itmpl_…). Naive verifies a set of company members in oneverification.startcall, and requiresownership_percentageto sum to 100, exactly onerole: "primary", and exactly oneis_responsible_party: true. This is formation-shaped — see gaps. - Persona is webhook-first (
inquiry.completed/inquiry.approved/inquiry.declined). Naive’s public webhook surface advertises onlyemail.received,sms.received, andapproval.resolvedtoday, so KYC status comes from the validation-tokencompleteendpoint (instant for the primary) + pollingGET /v1/verification/:id. TreatGET /v1/webhooks/event-typesas the source of truth before depending on any KYC event.
Concept map
Before / after: the core path
The path that matters for founder KYC is start verification for the people who own the company, hand them a hosted link, then know when they’ve passed. Here it is on both platforms.- One subject vs. a set of members. Persona’s inquiry is one person tagged with a
reference-id. Naive’sstarttakes the founding members withownership_percentage(must sum to 100), oneprimary, and oneis_responsible_party. That structure is the formation contract — not an arbitrary KYC subject. - The link comes back inline. Persona is create inquiry → generate link → email it yourself.
Naive returns
primary_linkfromstartand emails secondary members automatically. - Status: poll + validation token, not a webhook. Persona steers you to
inquiry.completedwebhooks. Naive’s public webhook surface does not advertise a KYC event today — use the validation-tokencomplete(instant for the primary) and pollverification.getfor the rest. - The id is your identity, not a tag. In Persona,
reference-idpoints back to your DB. In Naive,forUser(id)is the identity that owns the founders’ KYC and the company they’re about to form, its cards, phone, and vault.
Knowing when a founder passed
- Persona’s recommended path is a webhook workflow: subscribe to
inquiry.completed, then approve in a post-inquiry workflow and act oninquiry.approved. - Naive’s reliable public path today is validation token + polling:
- Member statuses map roughly as: Persona
completed/approved→ Naivepass;declined/failed→fail;needs_review→pending_review;pending/created→in_progress/link_sent. See the full status list.
Minimal viable migration
The smallest swap that keeps a working founder-KYC flow running is just start + hand over the link + read status.1
Install the SDK and set your key
NAIVE_API_KEY (a server-side key from the dashboard).2
Swap inquiry creation for verification.start
Replace
POST /api/v1/inquiries (one subject + template) with
client.verification.start({ members: [...] }). Provide each founder’s name + email,
ownership_percentage (summing to 100), exactly one role: "primary", and exactly one
is_responsible_party: true. Drop the inquiry-template-id — the KYC playbook is managed for
you.3
Swap link delivery
Drop
generate-one-time-link + your own email send. Hand the returned primary_link to the
primary founder; secondary members are emailed automatically. Use
verification.resend if a link expires.4
Swap status tracking
Replace the
inquiry.completed webhook with the validation-token
complete call for the primary (instant) and poll
GET /v1/verification/:id for the rest. Gate on
ready_for_formation instead of an inquiry.approved workflow.5
Ship it
At this point your founder-KYC flow runs on Naive. Everything below is upside — the same
identity is now ready to form the company and own its cards, phone, email, and vault.
Consolidate further once you’re on Naive
This is where the migration pays for itself. In Persona, an inquiry verifies a person and stops there — incorporation, banking, cards, and phone all live in separate systems keyed off areference-id string. On Naive, the verified founders are the identity that carries straight
into formation and every downstream primitive.
Gain #1 — one identity across primitives
- With Persona, KYC is an island: an
inquirytagged with areference-idthat you manually re-key into your formation, banking, card, and phone vendors. - With Naive,
naive.forUser(acme.id)is a single handle to KYC and formation and cards and phone and email and vault. The founders you verified are literally the responsible party the company is formed under — demonstrated byformation.submit({ verification_id }), which requires that the KYC passed.
Gain #2 — execution-time permission enforcement
- Whether an agent may start KYC at all is policy on the Account Kit, enforced at execution time — not a Persona API-key scope you manage separately.
- The agent’s code is identical either way —
client.verification.start({ ... }). Whether the call runs is decided at execution time:- An agent whose kit gates
verification.startgets202 { status: "pending_approval", approval_id }instead of starting KYC. A human approves it and KYC begins on replay — see the start endpoint note. - This is the same approval model that gates
formation.submit,cards, anddomains.purchase— one policy surface, not one per vendor.
- An agent whose kit gates
Gain #3 — unified accountability
- Every KYC start, completion, link resend, and the formation it gates lands in one per-user activity log — alongside the company’s card, phone, email, and vault events, not in a separate Persona dashboard:
- That is the question that is hard to answer when KYC lives in Persona, incorporation in Stripe Atlas, and cards in Stripe Issuing. Under Naive it is a single query.
What does not map yet
A migration guide that hides gaps is worse than none. Founder KYC (start → hosted link → status → formation gate) maps cleanly, but the following Persona capabilities have no direct equivalent on Naive’s verification primitive today. Check this list against your app before you commit.Where to go next
verificationprimitive — full start → status → complete → resend lifecycle and theready_for_formationgateverificationAPI reference — typed request/response for every endpointverificationCLI — start, status, complete, resend- Formation — the incorporation the KYC feeds, keyed off
verification_id - Account Kits and Approvals — the policy model behind execution-time KYC governance
- Vault encryption — where verified PII lives so it never touches your database
- Tenant users — the identity that owns the founders’ KYC, the company, and every downstream primitive
Related reading (blog)
- Why consolidate agent infra on one governed identity — migration thesis behind this guide
- Building AI Agents Into Your SaaS — tenant user anchor for every migration
- How To Build An Agentic Incorporation Platform — KYC + formation tutorial