POST /v1/companies
with entity type, state, and founder details, returning an order id), with asynchronous progress
often delivered over signature-verified webhooks. It can handle state filing, EIN, registered
agent, and documents for many founder profiles. But run
directly, it is also a separate vendor account:
- Formation lives behind your Doola partner API key, the Doola partner portal, and Doola’s
customer/companyobject graph — granted only after a signed partner agreement. - A Doola
customerscopes company formation and compliance, and nothing else. It is an onboarding record for filing — it has no idea about the agent’s KYC, its inbox, its vault secrets, its virtual card, or its phone number. - “Who let this agent incorporate a company, and what else can this agent touch?” is answered in Doola for the filing, and in unrelated systems for everything else. There is no shared accountability across the company’s footprint.
formation primitive gives the agent the same
capability — end-to-end LLC incorporation with state filing, EIN, registered agent, and downloadable
documents — but rooted in one identity:
- The tenant user that forms the company is the same user whose founders were KYC-verified, and that then owns its cards, phone number, email inboxes, and vault secrets.
- Verified PII (SSN, DOB, member addresses) is pulled from the encrypted identity vault at submission time — it never lands in your database.
- Whether an agent may file a formation — and whether it freezes for a human first — is decided by that user’s Account Kit at execution time, not by trusting your own code to check first.
- Every verification, formation submit, document fetch, card issue, and phone provision lands in the same per-user activity log.
Doola is a trademark of its owner, used here for identification only. No endorsement or affiliation is implied.
Tested against: the Doola Formation API (partner docs at
developers.doola.com, REST surface POST /v1/companies plus a GraphQL API at POST /graphql,
signature-verified webhooks, sandbox + production environments) and the Naive API
(base https://api.usenaive.ai/v1, docs snapshot June 2026) plus the Naive Node SDK
@usenaive-sdk/server.Version notes:- Doola’s full request/response schema (GraphQL types and REST bodies) is gated behind a signed partner agreement. The Doola code below reflects Doola’s public launch materials (the Formation API page, the launch announcement, and the engineering blog) and is illustrative — verify exact field names against your partner docs.
- Naive forms LLCs only today (
entity_type: "LLC"); Doola also forms C-corps and DAO LLCs. See gaps. - Naive requires founder KYC — a
verification_idwhoseready_for_formationistrue— before formation. Doola does not require KYC for most formation use cases. This is a structural difference, not a flag you toggle. See gaps. - Doola is webhook-first (
Formation Filed/Formation Completed/Registered Agent Assigned). Naive’s public webhook surface advertises onlyemail.receivedandapproval.resolvedtoday, so formation status comes from pollingGET /v1/formation/:id. TreatGET /v1/webhooks/event-typesas the source of truth before depending on any formation event. - Both are evolving APIs — verify method names and the payment model against your installed versions.
Concept map
| Doola | Naive | Notes |
|---|---|---|
| Partner API key (after signed agreement) + sandbox / production base | new Naive({ apiKey }), then naive.forUser(id) | Server-side key in both; Naive scopes formation to a tenant identity. No partner agreement to start |
| Step 1 — create a customer | tenant user naive.users.create({ external_id, email }) → naive.forUser(id) | The identity the company is formed under — but in Naive it also owns cards, phone, email, vault |
| (KYC not required for formation) | verification.start({ members }) → ready_for_formation: true | Naive requires founder KYC before formation; Doola does not — see gaps |
| reference-data lookups (states, entity types) | GET /v1/formation/naics-codes → naics_code_id | Naive requires a NAICS industry code id |
Step 2 — POST /v1/companies { entity_type, state, founders } → order id (REST), or POST /graphql mutation | POST /v1/formation / client.formation.submit({ verification_id, entity_type:"LLC", state, naics_code_id, description, name_options }) | Submit the formation. Naive returns a $249 checkout_url |
| order id | formation id (uuid) + status: "awaiting_payment" + checkout_url | |
| Billing: partner pricing model (rates vary by agreement) | $249 hosted checkout (state filing + registered agent + EIN + documents), paid by the end customer | Different commercial model — no wholesale margin to set — see gaps |
| Dispatch the filing (internal, post-payment) | POST /v1/formation/:id/submit — PII decrypted from the vault and dispatched for filing | Two-step on both: create then submit/execute |
Status webhooks Formation Filed / Formation Completed / Registered Agent Assigned (signed) | GET /v1/formation/:id (poll) → awaiting_payment → pending → submitted → formation_completed | Naive has no advertised formation webhook today — poll. See gaps |
| Formation documents returned via API | GET /v1/formation/:id/documents → ArticlesOfOrganization, EinLetter | Download via temporary signed URL |
| Access control: partner API-key scopes | Account Kit formation primitive, per user, execution time | Filing is policy on the identity — see gains |
| C-corp / DAO LLC formation | — (LLC only) | Real gap — see gaps |
| Non-US founders / SSN requirements (Doola markets broad international support) | KYC typically requires ID scan + selfie + SSN + address for Naive formation | Verify founder eligibility for your geography before migrating non-resident founders — see gaps |
| Ongoing compliance — annual filings, bookkeeping, taxes (OAuth) | — | Not a Naive primitive — see gaps |
Before / after: the core path
The path that matters for almost every agent that incorporates a company is register the founder, submit the formation, then track it to documents. Here it is on both platforms.- KYC is a required prerequisite, not optional. Doola forms the company without KYC. Naive’s
formation.submitrequires averification_idwhoseready_for_formationistrue— the responsible party is structurally the verified founder. That is the accountability win, and a flow change. See gaps. - Payment model. Doola may bill partners on a negotiated rate you mark up. Naive returns a
$249hostedcheckout_urlpaid by the end customer, then yousubmitto file. There is no wholesale/white-label margin to configure on Naive. - Status: poll, not a webhook. Doola is webhook-first. Naive’s public webhook surface does not
advertise a formation event today — poll
GET /v1/formation/:idthroughawaiting_payment → pending → submitted → formation_completed. - The customer is your identity, not a standalone onboarding record. In Doola a
customerexists for filing and compliance. In Naive the formation hangs off a tenant user that also owns the agent’s KYC, inbox, vault, card, and phone.
Submitting and filing
Both platforms separate “submit the formation” from “the company is actually filed.” Doola files asynchronously after payment and reports via webhook; Naive splits it into an explicit submit → pay → execute so the filing only dispatches once funding is confirmed.- On Naive, submitting a formation is sensitive and may be
approval-gated by the Account Kit — the call can return
202 { status: "pending_approval", approval_id }until a human approves, then the API replays it. Formation defaults to requiring approval for agent calls. - A formation moves
awaiting_payment → pendingafter the$249checkout is paid, thensubmitted → formation_completedonce filed. See Formation statuses.
Minimal viable migration
The smallest swap that keeps an incorporating agent running is create the identity → KYC the founder → submit → pay → execute → documents. You do not need to recreate partner billing, C-corp support, or Account Kits to file your first LLC.Install the SDK and set your key
NAIVE_API_KEY (a server-side key from the dashboard).
No partner agreement required to start.Map your customers
A Doola
customer becomes a Naive tenant user. Reuse your own
database id as external_id so the mapping is 1:1, or pass it straight into naive.forUser(id).Add the KYC prerequisite
Doola skips KYC; Naive requires it. Before formation, call
client.verification.start({ members: [...] }) with each founder’s name + email,
ownership_percentage (summing to 100), exactly one role: "primary", and exactly one
is_responsible_party: true. Poll until ready_for_formation is true. See the
verification primitive.Swap formation submission
Replace
POST /v1/companies with client.formation.submit({ verification_id, entity_type:"LLC", state, naics_code_id, description, name_options }). Pick a naics_code_id from
GET /v1/formation/naics-codes. Open the returned checkout_url for the $249 payment.Execute, track, and download
After payment,
POST /v1/formation/:id/submit to dispatch the filing, poll
GET /v1/formation/:id to formation_completed, then GET /v1/formation/:id/documents for the
Articles of Organization and EIN letter. At this point you are off your direct Doola integration
for the core path. Everything below is upside, not a requirement.Consolidate further once you’re on Naive
This is where the migration pays for itself. With Doola direct, acustomer isolates formation
and compliance and nothing else — KYC, cards, phone, and email all live in separate systems keyed
off an order id by hand. On Naive, the unit of isolation is a tenant user, and it isolates the
agent’s entire footprint.
Gain #1 — one identity across primitives
- With Doola, the company filing is an island: an order id you manually re-key into your KYC,
banking, card, and phone vendors. With Naive,
naive.forUser(acme.id)is a single handle to formation and KYC and cards and phone and email and vault. - The founders you verified are literally the
responsible party the company is formed under —
demonstrated by
formation.submit({ verification_id }), which requires that the KYC passed. You provision a company’s whole agent footprint from one identity, and tear it down from one place.
Gain #2 — execution-time permission enforcement
- Whether an agent may file a formation is policy on the Account Kit — not a check you hand-write, and not a Doola partner-key scope you manage separately.
- The agent’s code is identical for every tier —
client.formation.submit({ … }). Whether the call runs is decided by the caller’s kit at execution time:primitives_config.formation.enabled: false→ the exact same line returnsforbidden, no code change.requiresApproval: true(the default for formation) → the filing freezes as a pending approval; the API replays it only after a human approves.- This is the same approval model that gates
verification.start,cards, anddomains.purchase— one policy surface, not one per vendor.
Gain #3 — unified accountability
- Every KYC start, formation submit, document fetch, card issue, and phone provision for a company lands in one per-user activity log — not in a separate Doola portal:
- That is the question that is hard to answer when KYC lives in one vendor, incorporation in Doola, and cards in another. Under Naive it is a single query.
What does not map yet
A migration guide that hides gaps is worse than none. The core path (customer → KYC → submit → pay → execute → documents) maps cleanly for US LLCs with verifiable founders, but Doola has real capabilities Naive’sformation primitive does not match today. Check this list against your app
before you commit — some of these are why you might stay on Doola.
| Doola feature | Status on Naive | Workaround |
|---|---|---|
| C-corp and DAO LLC formation | Not available — entity_type: "LLC" only | Keep Doola (or another formation vendor) for non-LLC entities; use Naive for LLCs |
| Non-US founders / SSN-less paths (Doola markets international support) | Naive founder KYC typically requires ID scan + selfie + SSN + address | Verify Naive’s founder-eligibility for your geography before migrating non-resident founders |
| No-KYC formation | Founder KYC is required (ready_for_formation) before filing | By design — Naive trades Doola’s frictionless path for a verified, accountable one |
Webhook-first status (Formation Filed / Formation Completed / Registered Agent Assigned, signed) | Not advertised today (email.received, approval.resolved only) | Poll GET /v1/formation/:id; confirm via GET /v1/webhooks/event-types before relying on a formation event |
| White-label / wholesale pricing (partner-set markup) | Fixed $249 hosted checkout paid by the end customer | No wholesale margin model on Naive; the fee is end-customer-facing |
| Ongoing compliance — annual state filings, bookkeeping, tax filings (via OAuth) | Not a Naive primitive — formation + EIN + registered agent + documents only | Handle ongoing compliance out of band; Naive covers initial formation |
| Equity / 83(b) / cap table tooling | Not available | Out of scope for formation (more of a C-corp concern — see Stripe Atlas) |
| Mercury / banking introductions, payment-processor access | Not provided by formation | Use the cards primitive for spend; banking introductions are out of scope |
| GraphQL field selection / partial responses | REST/JSON responses with fixed shapes | Read the documented response fields; no GraphQL projection |
Where to go next
formationprimitive — full submit → pay → execute → status → documents lifecycleverificationprimitive — the founder KYC that gates formation, keyed offready_for_formationformationSDK sub-client and CLI — typed method signatures and command-line usage- Account Kits and Approvals — the policy model that makes execution-time formation governance real
- Vault encryption — where verified PII lives so it never touches your database
- Tenant users — the identity that the consolidation hangs off