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.)
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.idis the new client project — carry it through every step below.variableValuesfills any{{placeholders}}your template declares (client name, support email, brand color, …). Anything you leave out comes back underreport.missingVariablesand is left as a literal placeholder to fill later.report.failuresis 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.3. Hand off an invite link — not an email
Finally, give the client access to their finished workspace. PasssendEmail: 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 withjq:
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.