curl -X POST "https://api.sitespeak.ai/v1/agency/clients" \
-H "Accept: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: billing-account-1001" \
-d '{
"name": "Acme Inc",
"external_reference": "billing-account-1001",
"message_limit": 1000,
"source_limit": 50,
"chatbot_limit": 2,
"chatbot": {
"name": "Acme Support Agent",
"website_url": "https://acme.example"
},
"invite_email": "owner@acme.example",
"invite_role": "admin"
}'
const response = await fetch('https://api.sitespeak.ai/v1/agency/clients', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_API_TOKEN',
'Content-Type': 'application/json',
'Idempotency-Key': 'billing-account-1001'
},
body: JSON.stringify({
name: 'Acme Inc',
external_reference: 'billing-account-1001',
message_limit: 1000,
source_limit: 50,
chatbot_limit: 2,
chatbot: {
name: 'Acme Support Agent',
website_url: 'https://acme.example'
},
invite_email: 'owner@acme.example',
invite_role: 'admin'
})
});
const data = await response.json();
console.log(data);
Agency
Create Client Workspace
Creates a client workspace, with an optional AI agent and portal invitation, in one call
POST
/
v1
/
agency
/
clients
curl -X POST "https://api.sitespeak.ai/v1/agency/clients" \
-H "Accept: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: billing-account-1001" \
-d '{
"name": "Acme Inc",
"external_reference": "billing-account-1001",
"message_limit": 1000,
"source_limit": 50,
"chatbot_limit": 2,
"chatbot": {
"name": "Acme Support Agent",
"website_url": "https://acme.example"
},
"invite_email": "owner@acme.example",
"invite_role": "admin"
}'
const response = await fetch('https://api.sitespeak.ai/v1/agency/clients', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_API_TOKEN',
'Content-Type': 'application/json',
'Idempotency-Key': 'billing-account-1001'
},
body: JSON.stringify({
name: 'Acme Inc',
external_reference: 'billing-account-1001',
message_limit: 1000,
source_limit: 50,
chatbot_limit: 2,
chatbot: {
name: 'Acme Support Agent',
website_url: 'https://acme.example'
},
invite_email: 'owner@acme.example',
invite_role: 'admin'
})
});
const data = await response.json();
console.log(data);
Available on agency plans. The API token must belong to the agency owner.
Use this endpoint to provision a client from your own billing system: create the workspace, set its limits, create the first AI agent, and get an invitation link for your client, all in one request.
Headers
| Name | Type | Description |
|---|---|---|
| Accept* | String | application/json |
| Authorization* | String | Bearer |
| Content-Type* | String | application/json |
| Idempotency-Key* | String | A unique key for this request (for example your own account or order ID). Retrying with the same key and body returns the original response instead of creating a duplicate workspace. |
Body Parameters
| Name | Type | Description |
|---|---|---|
| name* | String | The client workspace name. |
| external_reference | String | Your own identifier for this client (for example a billing system account ID). You can filter the client list by this value. |
| message_limit | Integer | Monthly message credit limit for this client. Omit or null for no client-level limit. |
| source_limit | Integer | Source limit for this client. Omit or null for no client-level limit. |
| chatbot_limit | Integer | Maximum number of AI agents for this client. Omit or null for no client-level limit. |
| chatbot | Object | Optionally create the client’s first AI agent in the same call. |
| chatbot.name* | String | The AI agent name. Required when chatbot is present. |
| chatbot.website_url | String | A website URL to crawl and train the agent on. |
| chatbot.accent_color | String | Accent color for the agent widget. A random gradient is used when omitted. |
| invite_email | String | Optionally create a portal invitation for this email address. The response includes the signed accept_url, which you deliver to your client (for example in your own onboarding email). |
| invite_role | String | Role for the invited user: admin, editor or member. Defaults to admin. |
curl -X POST "https://api.sitespeak.ai/v1/agency/clients" \
-H "Accept: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: billing-account-1001" \
-d '{
"name": "Acme Inc",
"external_reference": "billing-account-1001",
"message_limit": 1000,
"source_limit": 50,
"chatbot_limit": 2,
"chatbot": {
"name": "Acme Support Agent",
"website_url": "https://acme.example"
},
"invite_email": "owner@acme.example",
"invite_role": "admin"
}'
const response = await fetch('https://api.sitespeak.ai/v1/agency/clients', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_API_TOKEN',
'Content-Type': 'application/json',
'Idempotency-Key': 'billing-account-1001'
},
body: JSON.stringify({
name: 'Acme Inc',
external_reference: 'billing-account-1001',
message_limit: 1000,
source_limit: 50,
chatbot_limit: 2,
chatbot: {
name: 'Acme Support Agent',
website_url: 'https://acme.example'
},
invite_email: 'owner@acme.example',
invite_role: 'admin'
})
});
const data = await response.json();
console.log(data);
Response
chatbot and invitation only appear when you sent them in the request.
The accept_url is a signed link your client uses to create their login and join the workspace. Deliver it in your own onboarding email. When your agency has a verified custom domain, the link points there, so your client signs up on your own portal.
- 201 Created
- 400 Missing Idempotency-Key
- 403 Not an agency account
- 409 Request in progress
- 422 Validation error
{
"client": {
"id": "dfcee2e1-3ace-41c6-9803-fb2b7c7cdfc7",
"name": "Acme Inc",
"external_reference": "billing-account-1001",
"limits": {
"chatbots": 2,
"sources": 50,
"messages": 1000
},
"usage": {
"chatbots": 1,
"sources": 0,
"messages": 0
},
"messages_remaining": 1000,
"credits_reset_at": null,
"created_at": "2026-07-22T19:31:40+00:00"
},
"chatbot": {
"id": "cd2c8560-6669-486b-9a47-2f68b25a1d22",
"name": "Acme Support Agent",
"enabled": true,
"accent_color": "linear-gradient(135deg, #34d399, #6ee7b7)",
"messages_remaining": 1000,
"created_at": "2026-07-22T19:31:41+00:00"
},
"invitation": {
"email": "owner@acme.example",
"role": "admin",
"accept_url": "https://sitespeak.ai/team-invitations/123?signature=..."
}
}
Returns when the
Idempotency-Key header is missing.Returns when the API token does not belong to an agency account owner.
Returns when a request with the same
Idempotency-Key is still being processed. Retry shortly.Returns when a field is invalid, the workspace limit for your plan is reached, or the
Idempotency-Key was already used with a different request body.Last modified on July 23, 2026
⌘I