Skip to main content
When you onboard clients through your own app or funnel, Sapt stays behind the scenes. A handful of REST calls spin up a fully-configured client project, connect the client’s tools, and produce links you embed in your own buttons — so the client never receives a Sapt-branded email and never sees the Sapt dashboard until they’re ready. Every client project is created as a sub-project of your parent project — your top-level account project — so it automatically shares that project’s plan and credit pool. You subscribe once and pay from one account, however many clients you run. See Billing & projects for exactly how the shared pool works.

How the pieces fit

Three things are involved. Get these straight and the rest is easy: In one sentence: under your parent project, you stamp a template to create a new child project for the client. Two rules follow from that:
  • The child belongs to the parent project, never to the template. A template isn’t a project — it’s just the configuration that gets copied in. Every client is a sub-project of your parent project, which is exactly why they all share its billing and credits.
  • The template must live on that same parent project. You pass both in one path — …/projects/{parentId}/templates/{templateId}/apply — and Sapt requires the template to belong to that parent. Keep your client templates on your parent project; one project can hold as many as you like. (Sourcing a template from a different project than the billing parent isn’t supported — by design, so a client always resolves to one clear billing owner.)
The only access you need is admin on the parent project — the sub_projects:write permission. No per-client billing, no separate accounts, nothing else to wire up. The pattern across the steps below is the same every time: you call Sapt, Sapt hands you back a link or an id, you drive your own UI with it. Three phases:
Prerequisite — a template saved on your parent project. Create one from the dashboard while in your parent project (Snapshots → Save) or over the API with POST /projects/{parentProjectId}/snapshot, then reference its templateId below. A snapshot captures that project’s configuration — roles, sidebar, workflows, CRM types/relations, branding, brand voice, and agents — and stores it as a reusable template on that same project.

1. Create the client project from your template

One call creates the sub-project and stamps your template onto it.
{projectId} is your parent project (the billing owner, where the template lives); {templateId} is the template on it. The client is created as a sub-project beneath the parent and inherits its billing.
  • data.project.id is the new client project — carry it through every step below.
  • variableValues fills any {{placeholders}} your template declares (client name, support email, brand color, …). Anything you leave out comes back under report.missingVariables and is left as a literal placeholder to fill later.
  • report.failures is empty on a clean apply; anything that couldn’t be created is listed there with a reason rather than failing the whole call.

2. Connect the client’s integrations

Mint a secure connect link for each tool the client needs to hook up — Meta, Gmail, Google Business Profile, and the rest. You hand the client the link (embed it in a button), and you poll until they finish signing in. The client connects their own accounts without ever logging into Sapt.
connectUrl is the link you drop into your funnel — a “Connect Meta” button. After the client finishes, poll the session until it leaves pending:
clientInvite: true extends the link’s lifetime so it survives being embedded in an onboarding step instead of expiring in minutes. To discover which providers a project can connect (and their exact providerId / authKind), call GET /projects/{id}/integrations. The connect flow — every provider, API-key integrations, and the full status table — is covered in Connecting integrations.
Finally, give the client access to their finished workspace. Pass sendEmail: false and Sapt skips its stock email and returns an acceptUrl instead — the link you wire into your own “Get started” button.
Want Sapt to email the invite instead? Omit sendEmail (or set it to true) and Sapt sends the acceptance link directly — acceptUrl comes back null. The sendEmail: false path is the one to use when you own the welcome experience.

Putting it together

The whole funnel, end to end, threading each response into the next with jq:
Both connectUrl and acceptUrl are links you own — wire them into buttons, emails, QR codes, or wherever your funnel lives. Nothing is sent on Sapt’s behalf unless you ask for it.
Auth. Use an API key that holds sub_projects:write on the parent project (step 1) plus access to the new project’s integrations, roles, and members (steps 2–3). The key that creates the project gets that access on the project it just made.