Docs / API and agents
Onboarding steps and gates
The ordered "Finish setting up" steps for a customer or supplier business, how each is derived, and which actions wait for which step.
GET /v1/onboarding answers where the signed-in person's business stands; the dashboard card (customers: /contractor/dashboard, suppliers: /applications) renders it. Steps can be done in any order and from any point, including by someone who never started: with no business yet the first step is "Create your business".
Who can use it#
Any signed-in business user reads it. Skipping a step needs org.onboarding (Owner and Administrator by default). Staff sessions get 404: they have no business to set up.
Steps#
State is derived from real data; only a skip is stored. States: done, todo, skipped, waiting (someone else must act), unavailable (the provider is off, counts as satisfied).
| Step | Side | Done when | Skippable |
|---|---|---|---|
business | both | the person belongs to a business | no |
approval | supplier | VendorLogic approved the account (waiting otherwise) | no |
profile | customer | legal name, address and phone saved on the person's business profile | no |
signature | customer | a default signature is saved | yes |
bank | customer | bank name and account last four saved | yes |
kyb | both | latest KYB verification is Approved; waiting while Didit reviews; unavailable when GET /v1/kyb says available: false | customer only |
form | supplier | the credit application is published | no |
team | both | another person is a member or invited | yes |
share | supplier | a customer invitation was queued or an application arrived | yes |
The side follows the active workspace role: APPLICANT is customer, every other business role is supplier.
Gates#
An endpoint named below calls the shared check and answers 409 { code: "onboarding_incomplete", details: { action, missing: [stepId] } } while a required step is open. Reading, drafting, and finishing onboarding itself are never gated. The table lives in packages/contracts/src/onboarding.ts (ONBOARDING_GATES).
| Action (permission key) | Endpoint | Needs |
|---|---|---|
applications.create | POST /v1/applications when signed in as a customer (anonymous invitation or QR intake stays open) | profile |
finder.apply | POST /v1/find-vendors/apply | profile |
invitations.supplier | POST /v1/customer/supplier-invitations, POST /v1/customer/vendor-invite | profile |
builder.manage (publish only) | PATCH /v1/admin/credit-app-config with intent publish | kyb |
invitations.customer | POST /v1/invite-customer | approval, form |
connectors.install | POST /v1/connect/registry/:slug/installations | approval, kyb |
mcp.propose_decision, mcp.remind_reference | MCP write tools | kyb |
KYB is required only for supplier trust actions (publishing, third-party data access, agent writes) and only when Didit is configured; a customer may skip it. A missing provider never blocks a business.
With
KYB_REQUIRED=1thekybstep is no longer skippable for customers,applications.createalso needskyb, and thekybgates apply to ungated (older) organizations too. See Business verification.
Organizations created before onboarding existed (and staff-onboarded suppliers) have
Organization.onboardingGated = false: they see the card but nothing is blocked. Self-service signup sets it to true.
Skipping#
POST /v1/onboarding/steps/:id/skip answers the new state. 404 for a step of the other side, 409 not_skippable for a required one, 403 without org.onboarding. It writes the audit event onboarding.step_skipped (actor, organization, step id) in the same transaction. Doing a skipped step later marks it done.
How the customer web shows it#
The customer dashboard, /apply and /find-vendors read GET /v1/onboarding and, while blocked["applications.create"] or blocked["finder.apply"] is set, show a gate notice (gate-notice): why the action waits (each open step with its own sentence), who must act (a step in waiting, such as verification in review, says "We are checking your business. Nothing is needed from you"), what the person can still do (browse suppliers, save references, invite colleagues, each only if their role may) and one button to the step that unblocks them. The steps themselves are a task list on the dashboard (setup-task-<step id>, any order, hidden when done). Supplier pages keep the compact card.