> ## Documentation Index
> Fetch the complete documentation index at: https://sitespeak.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Client Workspace

> Creates a client workspace, with an optional AI agent and portal invitation, in one call

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 {api_token}                                                                                                                                                                     |
| 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`.                                                                                                            |

<RequestExample>
  ```bash cURL theme={null}
  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"
    }'
  ```

  ```javascript JavaScript theme={null}
  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);
  ```
</RequestExample>

## 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.

<Tabs>
  <Tab title="201 Created">
    ```json theme={null}
    {
      "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=..."
      }
    }
    ```
  </Tab>

  <Tab title="400 Missing Idempotency-Key">
    Returns when the `Idempotency-Key` header is missing.
  </Tab>

  <Tab title="403 Not an agency account">
    Returns when the API token does not belong to an agency account owner.
  </Tab>

  <Tab title="409 Request in progress">
    Returns when a request with the same `Idempotency-Key` is still being processed. Retry shortly.
  </Tab>

  <Tab title="422 Validation error">
    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.
  </Tab>
</Tabs>
