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

# Publish an assistant as a website widget

> Publish one assistant as an embeddable website widget and receive its widget key. The key is public by design; what protects the embed is its allowed origins.

A widget deployment is one embed of one assistant on your website. Creating it returns a `widget_key` (`arukz_wk_…`) that you paste into your page. The key is **public by design**: it lives in your page source, it is not a secret, and you can read it back at any time. What protects the embed is its origin allowlist, its fixed assistant and the narrow permissions it grants: a visitor can start a conversation and ask questions, and nothing else. See [Website widget](/channels/widget).

The assistant must exist in your organization, or the request fails with `404`. It cannot be changed later; to point a page at a different assistant, create a new deployment and revoke the old one. Deployment names are unique within your organization; a name that is already taken returns `409`.

You need the `assistant.publish` permission, which the owner, admin and editor roles hold. Authenticate with an `arukz_sk_` API key or a signed-in console session.

<ParamField body="name" type="string" required>
  A label for the embed. Leading and trailing whitespace is trimmed; the result must be 1 to 120
  characters, with no control, invisible formatting (such as zero-width or bidirectional-override),
  private-use or line-separator characters.
</ParamField>

<ParamField body="assistant_id" type="string" required>
  ID (UUID) of the assistant to embed. Fixed for the life of the deployment. A value that is not a
  UUID returns `400`.
</ParamField>

<ParamField body="allowed_origins" type="string[]" default="[]">
  The website origins allowed to host this widget, at most 20. Each entry must be exactly `scheme://host` or `scheme://host:port`:

  * `http` or `https` only.
  * **Exact match.** No wildcards: `*` and `*.example.com` are refused. List each subdomain separately.
  * **No trailing slash, path, query or credentials.** `https://docs.example.com/` is refused.
  * ASCII hosts only. Scheme and host are compared case-insensitively, and a default port (`:443` for `https`, `:80` for `http`) is ignored.

  An empty list permits no origin, so the widget will not load anywhere until you add one with [Update a widget deployment](/api-reference/widget-deployments/update-widget-deployment). An origin must also be permitted by your MITHUNAI deployment's platform-wide widget allowlist.
</ParamField>

<ParamField body="expires_in_days" type="integer">
  Lifetime in whole days, from 1 to 730. Omit it, or send `null`, for an embed that does not expire.
  An expired embed stops working without further action.
</ParamField>

## Response

Returns `201 Created` with the deployment.

<ResponseField name="id" type="string" required>
  The deployment's ID (UUID).
</ResponseField>

<ResponseField name="name" type="string" required>
  The embed's label.
</ResponseField>

<ResponseField name="widget_key" type="string" required>
  The public key to put in your page: `arukz_wk_` followed by the deployment ID. Send it in the
  `X-ARUKZ-Widget-Key` header.
</ResponseField>

<ResponseField name="assistant_id" type="string" required>
  The embedded assistant's ID.
</ResponseField>

<ResponseField name="status" type="string" required>
  Always `active` on creation.
</ResponseField>

<ResponseField name="allowed_origins" type="string[]" required>
  The accepted origins, de-duplicated and sorted, in the spelling you sent.
</ResponseField>

<ResponseField name="created_at" type="string" required>
  When the deployment was created, ISO 8601 in UTC.
</ResponseField>

<ResponseField name="created_by" type="string | null" required>
  ID of the user who created it, or `null` when it was created with an API key.
</ResponseField>

<ResponseField name="expires_at" type="string | null" required>
  When the embed expires, or `null` if it does not.
</ResponseField>

<ResponseField name="revoked_at" type="string | null" required>
  Always `null` on creation.
</ResponseField>

<ResponseField name="last_used_at" type="string | null" required>
  Always `null` on creation.
</ResponseField>

<RequestExample>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl --request POST "$MITHUNAI_URL/arukz/api/v1/widget-deployments" \
    --header "Authorization: Bearer $MITHUNAI_API_KEY" \
    --header "Content-Type: application/json" \
    --data '{
      "name": "Docs site widget",
      "assistant_id": "5b1e9c2a-7d4f-4e3b-9a61-0c8f2d7e4a13",
      "allowed_origins": ["https://docs.example.com", "https://www.example.com"],
      "expires_in_days": 365
    }'
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import os, requests

  response = requests.post(
      f"{os.environ['MITHUNAI_URL']}/arukz/api/v1/widget-deployments",
      headers={"Authorization": f"Bearer {os.environ['MITHUNAI_API_KEY']}"},
      json={
          "name": "Docs site widget",
          "assistant_id": "5b1e9c2a-7d4f-4e3b-9a61-0c8f2d7e4a13",
          "allowed_origins": ["https://docs.example.com", "https://www.example.com"],
          "expires_in_days": 365,
      },
      timeout=30,
  )
  response.raise_for_status()
  print(response.json()["widget_key"])
  ```

  ```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const response = await fetch(`${process.env.MITHUNAI_URL}/arukz/api/v1/widget-deployments`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.MITHUNAI_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      name: 'Docs site widget',
      assistant_id: '5b1e9c2a-7d4f-4e3b-9a61-0c8f2d7e4a13',
      allowed_origins: ['https://docs.example.com', 'https://www.example.com'],
      expires_in_days: 365,
    }),
  })
  console.log((await response.json()).widget_key)
  ```
</RequestExample>

<ResponseExample>
  ```json 201 theme={"theme":{"light":"github-light","dark":"github-dark"}}
  {
    "id": "8d0f5a2e-3c41-4b7a-9e6d-1f2a3b4c5d6e",
    "name": "Docs site widget",
    "widget_key": "arukz_wk_8d0f5a2e-3c41-4b7a-9e6d-1f2a3b4c5d6e",
    "assistant_id": "5b1e9c2a-7d4f-4e3b-9a61-0c8f2d7e4a13",
    "status": "active",
    "allowed_origins": ["https://docs.example.com", "https://www.example.com"],
    "created_at": "2026-09-20T14:03:11.482190+00:00",
    "created_by": null,
    "expires_at": "2027-09-20T14:03:11.482190+00:00",
    "revoked_at": null,
    "last_used_at": null
  }
  ```

  ```json 400 theme={"theme":{"light":"github-light","dark":"github-dark"}}
  { "code": "validation_error", "message": "A widget deployment may name at most 20 origins." }
  ```

  ```json 401 theme={"theme":{"light":"github-light","dark":"github-dark"}}
  { "code": "authentication_error", "message": "Authentication is required." }
  ```

  ```json 403 theme={"theme":{"light":"github-light","dark":"github-dark"}}
  { "code": "authorization_error", "message": "You do not have permission to perform this action." }
  ```

  ```json 404 theme={"theme":{"light":"github-light","dark":"github-dark"}}
  { "code": "not_found", "message": "The requested resource was not found." }
  ```

  ```json 409 theme={"theme":{"light":"github-light","dark":"github-dark"}}
  { "code": "conflict", "message": "A widget deployment with that name already exists." }
  ```
</ResponseExample>
