Create a sub-account

Provision a sub-account and email its owner a sub_account_owner invitation (valid 7 days). Limits and features come from the agency defaults, or from the named agency pricing plan; the agency's signup credit (if any) is added to the new wallet.

POST https://api.centerfy.ai/webhooks/inbound/agency/sub-accounts

Headers

HeaderRequiredValueDescription
x-api-keyYesyour agency API key (cfy_…)Agency (organization-wide) API key, created in the agency workspace under Settings → API Keys (“Agency API Keys”; the tab only appears on White Label or SaaS Mode plans). Or send Authorization: Bearer <key>; x-api-key wins if both are present. Keys must start with cfy_. A sub-account key is rejected with 401.
Content-TypeYesapplication/jsonThe request body is JSON.

Body parameters

NameTypeRequiredDefaultDescription
namestringYes—Sub-account name, 1–200 characters. Also used to build the slug (a base-36 suffix is added if the slug is taken).
emailstringYes—Owner email (3–320 characters); receives the invitation. Lower-cased.
planstringNo—Name of an active agency pricing plan; sets limits, features and rebilling pricing. Omit to use the agency defaults.

Request body

{
  "name": "Acme Roofing",
  "email": "[email protected]",
  "plan": "starter"
}

Example

curl -X POST "https://api.centerfy.ai/webhooks/inbound/agency/sub-accounts" \
  -H "x-api-key: $CENTERFY_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Roofing",
  "email": "[email protected]",
  "plan": "starter"
}'
import { CenterfyAgencyClient } from "@centerfy/sdk";

const agency = new CenterfyAgencyClient({ apiKey: process.env.CENTERFY_AGENCY_API_KEY! });

const result = await agency.subAccounts.create({
  "name": "Acme Roofing",
  "email": "[email protected]",
  "plan": "starter"
});
console.log(result);
centerfy --agency subAccounts create '{"name":"Acme Roofing","email":"[email protected]","plan":"starter"}'

MCP tool: centerfy_agency_sub_accounts_create (see MCP server)

Response

{
  "status": "success",
  "sub_account_id": "5a1f3c2e-8b4d-4e6f-9a7b-1c2d3e4f5a01",
  "sub_account_slug": "acme-roofing",
  "invitation_token": "c18e0395-f2b4-45d6-8172-8d9eafb0c108",
  "plan": "starter",
  "email_sent": true
}

Errors

  • 201 — on success.
  • 400 — if name is blank or email is invalid.
  • 403 — if the agency is inactive or has reached its sub-account limit (max_sub_accounts, default 5).
  • 404 — if plan does not match an active plan of this agency.
  • 500 — ‘Sub-account created but invitation failed’ includes sub_account_id.
  • 401 — when the key is missing, not cfy_-prefixed or unknown (including sub-account keys); 403 when the agency is not on a White Label or SaaS Mode plan; 429 above 50 requests per minute per agency (Retry-After header set); 500 ‘database error’ on an internal failure.

Notes

A failed invitation email does not fail the call: email_sent is false and email_error explains why. GHL locationID auto-connect is not supported here — use the legacy create-subaccount-webhook for that.

© 2026 Centerfy AI. All rights reserved.