API Reference
A small REST API for looking up your clients and what they've connected. If you want ClientInvite to push data to you instead, use webhooks.
Updated 28 September 2026
An earlier version of this page described parameters and fields the API didn't have. It now matches the API exactly. If you built against the old page, the names it used still work (see Compatibility), but new code should use the ones below.
Authentication
Create an API key in Settings → API & Webhooks. The key is shown once, so store it somewhere safe. Send it on every request:
Authorization: Bearer ci_live_xxxxxxxxxxxxX-Api-Key: ci_live_xxxxxxxxxxxx works too. The dashboard shows when each key was last used, and you can revoke a key there at any time.
Call it from your server, not a browser
Anyone with the key can read your client list, so never put it in browser code, mobile apps, or public repos. The API doesn't allow cross-origin browser requests, so calls from a web page fail with a CORS error. Call it from your backend, a serverless function, or an automation tool.
The API is available on the Agency plan. Requests from other plans return 403.
Base URL, versioning & responses
https://app.clientinvite.com/api/v1The version is in the path (/v1). Breaking changes will only ever ship under a new version. Every response uses the same envelope:
{ "error": false, "data": ... }{
"error": true,
"msg": "Invalid status. Use 'pending' or 'completed'.",
"code": "INVALID_PARAMETER"
}| Field | Type | Description |
|---|---|---|
| 200 | — | Success. |
| 400 | INVALID_PARAMETER | A query parameter has a value the API doesn’t accept. msg says which. |
| 401 | UNAUTHORIZED | The key is missing, malformed, unknown, or revoked. |
| 403 | PLAN_UPGRADE_REQUIRED | Your workspace isn’t on the Agency plan. |
| 404 | NOT_FOUND | No client matches that ID or ref, or there’s no endpoint at that path. msg lists the endpoints. |
| 429 | RATE_LIMITED | More than 60 requests in a minute. Wait for the Retry-After header’s seconds. |
Rate limit: 60 requests per minute per key.
GET /me
Check that your key works and see which workspace it belongs to.
curl https://app.clientinvite.com/api/v1/me \
-H "Authorization: Bearer ci_live_xxxxxxxxxxxx"{
"error": false,
"data": {
"id": "3e8a1f5c-7d2b-4e9a-8c6f-1b0d4a7e2c93",
"name": "Acme Agency",
"plan": "Agency",
"apiAccessEnabled": true,
"agencyName": "Acme Agency",
"keyCreatedAt": "2026-07-01T08:12:04.000Z"
}
}| Field | Type | Description |
|---|---|---|
| id | string | Your workspace ID. |
| name | string | null | Your agency name, falling back to your account name. |
| plan | string | null | Your current plan, e.g. "Agency". null if you have no active plan. |
| apiAccessEnabled | boolean | Whether your plan includes the API. |
| keyCreatedAt | string | When the key you used was created. |
GET /clients
List your clients, newest first.
| Field | Type | Description |
|---|---|---|
| ref | string | Only the client tagged with this exact customRef. |
| string | Only clients who entered this email (capitalisation is ignored). | |
| status | string | "pending" (started but not finished) or "completed". |
| limit | integer | Page size, 1–100. Default 25. |
| cursor | string | The nextCursor from a previous response, to get the next page. |
| sort | string | "newest" (default) or "oldest", by when the client started onboarding. |
curl "https://app.clientinvite.com/api/v1/clients?status=completed&limit=25" \
-H "Authorization: Bearer ci_live_xxxxxxxxxxxx"{
"error": false,
"data": {
"items": [
{
"id": "9c2d7f14-6b3e-4a8f-b1d2-7e5c0a9f3b21",
"name": "Acme Co",
"email": "hello@acme.com",
"customRef": "crm-record-8841",
"status": "completed",
"assetCount": 3,
"createdAt": "2026-07-13T09:38:02.000Z",
"lastConnectedAt": "2026-07-13T09:41:25.000Z",
"connectedAt": "2026-07-13T09:41:25.000Z",
"clientSummaryUrl": "https://app.clientinvite.com/clients"
}
],
"nextCursor": "eyJ0IjoiMjAyNi0wNy0xM1QwOTozODowMi4wMDAwMDAiLCJpZCI6IjljMmQ3ZjE0LTZiM2UtNGE4Zi1iMWQyLTdlNWMwYTlmM2IyMSJ9"
}
}| Field | Type | Description |
|---|---|---|
| id | string | The client’s ID (a UUID). |
| name | string | The name the client entered. |
| string | null | The email the client entered. | |
| customRef | string | null | Your own reference for this client, if the link included ?ref=. |
| status | string | null | "pending" or "completed". |
| assetCount | integer | How many assets the client has granted access to. |
| createdAt | string | When the client started onboarding (ISO 8601). |
| lastConnectedAt | string | null | When the client last granted access to an asset. |
| clientSummaryUrl | string | Your Clients page in the ClientInvite dashboard. |
Pagination: when more results exist, nextCursor is set. Pass it back as ?cursor=, keeping the other parameters the same. nextCursor is null on the last page.
GET /clients/{id}
One client, with every asset on their access link. {id} accepts the client's ID or your own customRef, so you can go straight from a CRM record to a lookup:
curl https://app.clientinvite.com/api/v1/clients/crm-record-8841 \
-H "Authorization: Bearer ci_live_xxxxxxxxxxxx"{
"error": false,
"data": {
"id": "9c2d7f14-6b3e-4a8f-b1d2-7e5c0a9f3b21",
"name": "Acme Co",
"email": "hello@acme.com",
"customRef": "crm-record-8841",
"status": "completed",
"assetCount": 3,
"createdAt": "2026-07-13T09:38:02.000Z",
"lastConnectedAt": "2026-07-13T09:41:25.000Z",
"connectedAt": "2026-07-13T09:41:25.000Z",
"clientSummaryUrl": "https://app.clientinvite.com/clients",
"assets": [
{
"platform": "facebook",
"type": "facebook_ads",
"name": "Acme Co",
"externalId": "act_1086344871362999",
"permission": "admin",
"status": "GRANTED"
},
{
"platform": "facebook",
"type": "facebook_page",
"name": "Acme Co",
"externalId": "104217693118841",
"permission": "admin",
"status": "GRANTED"
},
{
"platform": "google",
"type": "google_ads",
"name": "acme.com",
"externalId": "7342018841",
"permission": "admin",
"status": "GRANTED"
}
],
"customRefs": [
"crm-record-8841"
],
"requestId": "5b0f3c8e-2d1a-4c7e-9a61-3f2e8d4b7c10",
"requestName": "Onboarding - Meta & Google",
"requestUrl": "https://app.clientinvite.com/workspace/acme-agency/onboarding",
"connectionAssets": [
{
"id": "act_1086344871362999",
"name": "Acme Co",
"type": "Meta ads",
"platform": "Meta",
"connectionStatus": "Connected",
"accessLevel": "admin",
"time": "2026-07-13T09:40:51.000Z",
"linkToAsset": null
},
{
"id": "104217693118841",
"name": "Acme Co",
"type": "Facebook page",
"platform": "Meta",
"connectionStatus": "Connected",
"accessLevel": "admin",
"time": "2026-07-13T09:40:12.000Z",
"linkToAsset": null
},
{
"id": "7342018841",
"name": "acme.com",
"type": "Google ads",
"platform": "Google",
"connectionStatus": "Connected",
"accessLevel": "admin",
"time": "2026-07-13T09:41:25.000Z",
"linkToAsset": null
}
]
}
}Everything from GET /clients, plus:
| Field | Type | Description |
|---|---|---|
| customRefs | string[] | null | Every ref this client has been tagged with, oldest first. |
| requestId | string | The ID of the access link the client used. |
| requestName | string | The access link’s name. |
| requestUrl | string | The access link’s URL. |
| connectionAssets[] | array | One entry per asset on the link, including ones not connected yet. |
| connectionAssets[].id | string | null | The platform’s own ID for the account (e.g. act_… or a Google Ads customer ID). null if not connected. |
| connectionAssets[].name | string | null | The account’s name on the platform. |
| connectionAssets[].type | string | e.g. "Meta ads", "Facebook page", "Google ads". |
| connectionAssets[].platform | string | "Meta", "Google", "LinkedIn" or "Shopify". |
| connectionAssets[].connectionStatus | string | "Connected", "In progress" or "Not Connected". |
| connectionAssets[].accessLevel | string | The access your link asks for: "view", "admin" or "whitelisting". |
| connectionAssets[].time | string | null | When the client connected this asset. |
connectionAssets has exactly the same shape as in the webhook payload.
Compatibility with the earlier docs
If you wrote code against the previous version of this page, these still work:
| Field | Type | Description |
|---|---|---|
| status=CONNECTED | query | Same as status=completed. |
| sort=connectedAt / -connectedAt | query | Same as sort=newest / sort=oldest. |
| connectedAt | field | Same value as lastConnectedAt. |
| agencyName | field (/me) | Same value as name. |
| assets[] | field (/clients/{id}) | platform, type, name, externalId, permission, and status ("GRANTED", "PENDING" or "NOT_CONNECTED") for each asset. |
Client IDs are UUIDs, and error codes are the uppercase ones in the table above. Code that expected cl_… IDs or lowercase codes needs updating.