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

# Create chat completion

> Ask GC AI a legal question or give it a task.

<Note>
  The MCP server is in public beta. It is open to use and still being refined, so tools and behavior may change.
</Note>

<Info>
  **Tool** `ask_gcai` · **Behavior** Open world
</Info>

Ask GC AI a legal question or give it a task. Optionally ground it in uploaded files (`file_ids`), playbooks (`playbook_ids`), skills (`skill_ids`), or a Contract Intelligence vault (`vault_id`). Returns a job envelope, not a final answer: while `status` is `pending` or `running`, keep polling `ask_gcai_status` with the returned `job_id` until `status` is `succeeded` (then `result` holds the answer). Pass `chat_id` to continue a prior conversation, sending only the new message (conversation state is kept server-side).

## Input parameters

<ParamField body="message" type="string" required>
  The user's message or prompt
</ParamField>

<ParamField body="file_ids" type="string (uuid)[]">
  Optional uploaded file IDs to attach as context for this completion. Upload files first via `POST /files`.
</ParamField>

<ParamField body="playbook_ids" type="string (uuid)[]">
  Optional playbook IDs to ground the completion in (up to 20). The model uses each playbook's checks and guidance to structure its review of the attached files. Discover playbooks via `GET /playbooks`.

  Org-scoped keys can use org-visible and official playbooks.
</ParamField>

<ParamField body="playbook_id" type="string">
  Deprecated and no longer accepted. Use `playbook_ids` (an array) instead. Requests that include this field are rejected with a 400 so the playbook is never silently dropped.
</ParamField>

<ParamField body="skill_ids" type="string (uuid)[]">
  Optional skill IDs to run on the first turn. Each skill's instructions are injected as context for this completion. Discover skills via `GET /skills`.

  Only valid when starting a new chat; omit them when continuing with `chat_id`.
</ParamField>

<ParamField body="chat_id" type="string (uuid)">
  Optional chat ID to continue an existing conversation, from the `chat_id` of a prior completion. Omit to start a new chat.

  Conversation state is held server-side, so send only your new `message` (plus any new `file_ids`); do **not** re-send prior turns or previously returned documents/emails/diagrams. Only one turn may be in flight per chat at a time. See [Multi-turn Conversations](/api-reference/concepts/multi-turn).
</ParamField>

<ParamField body="project_id" type="string (uuid)">
  Optional project to file the chat into. Requires write access to the project. Discover projects via `GET /projects`.

  This does two things: it grounds the completion in the project's files, and it files the chat under that project. Filing alone does not make the chat visible to people, because API chats stay out of chat history until they are materialized. Pass `materialize: true` (or call `POST /chat/{id}/materialize` afterwards) for the chat to appear under `GET /projects/{id}/chats` and in the GC AI web app. See [Chat Visibility](/api-reference/concepts/chat-visibility).
</ParamField>

<ParamField body="materialize" type="boolean">
  Surface this chat into chat history as part of the same call, instead of making a second request to `POST /chat/{id}/materialize`. Defaults to `false`, which keeps the chat headless.

  Set this when a person is meant to open the chat. An organization-scoped key shares the materialized chat with the whole organization, so any member can open it and keep chatting in it. A user-scoped key keeps the chat owned by the caller.

  On success the response includes `chat_url`. If that field is absent, materialization did not happen and the chat is still headless; retry with `POST /chat/{id}/materialize` using the returned `chat_id`. Continuing an already-materialized chat is a no-op. See [Chat Visibility](/api-reference/concepts/chat-visibility).
</ParamField>

<ParamField body="company_id" type="string (uuid)">
  Optional company profile to ground the completion in, so the model has that company's context (industry, jurisdiction, regulations, risk posture). Discover company profiles via `GET /company-profiles`.

  The company is fixed for the life of a chat. On a new chat, supply this to target a specific company (the only way to ground against a particular one in a multi-company organization); when omitted, a company is auto-resolved: user-scoped keys use the caller's active (default) company, and org-scoped keys use the organization's sole company, or none when there are several.

  When continuing a chat with `chat_id`, omit this to reuse the chat's company. You may echo the same `company_id`, but a different one is rejected with `409` (start a new chat to use a different company).
</ParamField>

<ParamField body="vault_id" type="string (uuid)">
  Optional Contract Intelligence vault to ground the completion in, so the model can query that vault's documents and fields. Copy the vault ID from the GC AI web app.

  **Authorization:** User-scoped keys need the Vault Chat permission, Contract Intelligence access, and view access to the vault. Organization-scoped keys need the organization to have Contract Intelligence entitlement; they can attach any vault in the organization because organization keys have no user identity for per-vault access checks.

  The vault is fixed for the life of a chat. When continuing with `chat_id`, omit this to reuse the chat's vault. You may echo the same `vault_id`, but a different one is rejected with `409` (start a new chat to use a different vault).

  When also filing into a project (`project_id`) that is linked to a vault, `vault_id` must match that vault. A different one is rejected with `409`; omit `vault_id` to use the project's vault.
</ParamField>

## Response

<ResponseField name="job_id" type="string">
  Job identifier. Pass it to the matching `*_status` tool to poll.
</ResponseField>

<ResponseField name="status" type="'pending' | 'running' | 'succeeded' | 'failed' | 'canceled'">
  `succeeded` means `result` is populated; `running`/`pending` means poll again; `failed`/`canceled` are terminal.
</ResponseField>

<ResponseField name="result" type="object | null">
  Typed result when `status` is `succeeded`; `null` until then.

  <Expandable title="properties">
    <ResponseField name="result" type="string">
      The AI-generated response text
    </ResponseField>

    <ResponseField name="chat_id" type="string (uuid)">
      The chat ID. API chats stay out of chat history until you materialize them. Pass `materialize: true` on the request to surface the chat in the same call, or pass this ID to `POST /chat/{id}/materialize` afterwards. See [Chat Visibility](/api-reference/concepts/chat-visibility).
    </ResponseField>

    <ResponseField name="chat_url" type="string (uri)">
      Deep link that opens the chat in the GC AI web app. Present only when the request set `materialize: true` and the chat was surfaced, so its absence means the chat is still headless.
    </ResponseField>

    <ResponseField name="documents" type="object[]">
      Documents produced during this completion: either edits of an attached file (the document editing tool) or newly generated files (the document or slide generation tools). Present only when at least one document was produced. Each entry exposes a new `file_id` and a signed download URL; edits also reference the preserved original via `original_file_id`.

      <Expandable title="properties">
        <ResponseField name="file_id" type="string (uuid)">
          The new uploaded file ID for the produced document. Use it with `POST /chat/completions` `file_ids` to apply further edits to this version. Download via `signed_url` for the finished file.
        </ResponseField>

        <ResponseField name="original_file_id" type="string (uuid)">
          The `file_id` the changes were applied to (edits only). The original file is preserved unchanged. Omitted for newly generated documents.
        </ResponseField>

        <ResponseField name="filename" type="string">
          Filename of the produced document (edits are prefixed with `edited_`).
        </ResponseField>

        <ResponseField name="original_filename" type="string">
          Filename of the source file the changes were applied to (edits only). Omitted for newly generated documents.
        </ResponseField>

        <ResponseField name="signed_url" type="string (uri)">
          Time-limited direct download URL (no login required). Valid for 7 days from job completion. Download promptly; the URL is not re-minted, so re-fetching the job after expiry returns the same expired URL. For a link you intend to store or email, use `download_url` instead.
        </ResponseField>

        <ResponseField name="download_url" type="string (uri)">
          Permanent, login-gated download link for the produced document. Unlike `signed_url` it never expires: it points at a GC AI web page that mints a fresh download for a signed-in user with access to the file, and redirects to GC AI login otherwise. Use this for links you store or email. The produced document inherits the source document's access, so it opens for whoever can already see the source: a document uploaded to the organization is org-visible, one in a project is visible to that project's members, and one in personal files stays private to the uploader. Recipients still need a GC AI login.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="emails" type="object[]">
      Email drafts produced during this completion by the email drafting tool. Present only when at least one email was drafted. Each entry is a structured draft (`to`, `subject`, `body`, …) ready to send via your own mail client or provider.

      <Expandable title="properties">
        <ResponseField name="to" type="string">
          Recipient email address(es), comma-separated. May be an empty string when the prompt named no recipient; fill it in before sending.
        </ResponseField>

        <ResponseField name="cc" type="string">
          CC recipient email address(es), comma-separated.
        </ResponseField>

        <ResponseField name="bcc" type="string">
          BCC recipient email address(es), comma-separated.
        </ResponseField>

        <ResponseField name="subject" type="string">
          Email subject line. Always present, inferred from context when the prompt did not specify one.
        </ResponseField>

        <ResponseField name="body" type="string">
          Email body in markdown.
        </ResponseField>

        <ResponseField name="plaintext_body" type="string">
          Email body with markdown stripped, for plain-text clients.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="diagrams" type="object[]">
      Diagrams produced during this completion by the diagram tool. Present only when at least one diagram was produced. Each entry exposes validated Mermaid source (`mermaid`) you can render with any Mermaid-compatible renderer.

      <Expandable title="properties">
        <ResponseField name="title" type="string">
          A short descriptive title for the diagram.
        </ResponseField>

        <ResponseField name="diagram_type" type="string">
          The semantic type of diagram, e.g. orgChart, dealStructure, workflow, timeline, sequence, entityRelationship, or general.
        </ResponseField>

        <ResponseField name="mermaid" type="string">
          The diagram source as validated Mermaid syntax. Render it with any Mermaid-compatible renderer.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="status_tool" type="string">
  The exact tool to call to poll this job. Call it yourself with `job_id`; do not ask the user to poll.
</ResponseField>

<ResponseField name="poll_after_seconds" type="number | null">
  While `status` is `pending`/`running`, wait this many seconds, then call `status_tool` with `job_id`. `null` once the job is terminal.
</ResponseField>

<ResponseField name="hint" type="string">
  Plain-language next step. Follow it before responding.
</ResponseField>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.