Invite a user

Invite a user to a sub-account and send the invitation email (valid 7 days). Inviting an email that already has a pending invitation refreshes it (new token and expiry) and re-sends it instead of creating a duplicate.

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

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.

Path parameters

NameTypeRequiredDescription
idstring (uuid)YesThe sub-account id. Must belong to the key’s agency and not be deleted.

Body parameters

NameTypeRequiredDefaultDescription
emailstringYes—Email to invite (max 320 characters). Lower-cased.
rolestringYes—One of sub_account_owner, sub_account_admin, sub_account_user.
first_namestringNo—First name (max 200 characters).
last_namestringNo—Last name (max 200 characters).
phonestringNo—Phone number (max 40 characters).

Request body

{
  "email": "[email protected]",
  "role": "sub_account_admin",
  "first_name": "Alex",
  "last_name": "Kim",
  "phone": "+14155550123"
}

Example

curl -X POST "https://api.centerfy.ai/webhooks/inbound/agency/sub-accounts/{id}/users" \
  -H "x-api-key: $CENTERFY_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "[email protected]",
  "role": "sub_account_admin",
  "first_name": "Alex",
  "last_name": "Kim",
  "phone": "+14155550123"
}'
import { CenterfyAgencyClient } from "@centerfy/sdk";

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

const result = await agency.subAccountUsers.invite("<subAccountId>", {
  "email": "[email protected]",
  "role": "sub_account_admin",
  "first_name": "Alex",
  "last_name": "Kim",
  "phone": "+14155550123"
});
console.log(result);
centerfy --agency subAccountUsers invite <subAccountId> '{"email":"[email protected]","role":"sub_account_admin","first_name":"Alex","last_name":"Kim","phone":"+14155550123"}'

MCP tool: centerfy_agency_sub_account_users_invite (see MCP server)

Response

{
  "status": "success",
  "message": "Invitation is sent to [email protected]",
  "invitation_id": "af6e8173-d092-43b4-af50-6b7c8d9eaf06",
  "email": "[email protected]",
  "role": "sub_account_admin",
  "resent": false,
  "expires_at": "2026-10-13T12:00:00.000Z"
}

Errors

  • 201 — on success; resent is true when an existing pending invitation was refreshed.
  • 400 — if email is invalid or role is not allowed.
  • 403 — when the sub-account is at its seat limit (max_users counts active members; a negative max_users means unlimited) — the body adds current_users and max_users.
  • 502 — if the invitation was saved but the email could not be sent; the body carries the same invitation fields plus details, and calling again re-sends it.
  • 404 — when the sub-account id is not a uuid, does not exist, is deleted, or belongs to another agency.
  • 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.
© 2026 Centerfy AI. All rights reserved.