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

> Send a message to GC AI and receive an AI-generated response.

<Note>
This endpoint is asynchronous: it returns a job envelope, and the result is filled in once the job completes. See [Asynchronous Requests](/api-reference/concepts/async-jobs) for how waiting, polling, and the envelope work.
</Note>

## Multi-turn conversations

Every response includes a `chat_id`. Pass it back as `chat_id` on a later request to continue that conversation. Conversation state (prior messages, tool calls, and any returned documents, emails, or diagrams) is held server-side, so each turn sends only the new `message` (plus any new `file_ids`); never re-send prior turns or previously returned outputs.

Only one turn may be in flight per chat at a time: a request whose `chat_id` already has a turn running is rejected with `409`. Wait for the prior turn to reach a terminal state before sending the next.

Continuing a chat is scoped like [materialization](/api-reference/concepts/chat-visibility): personal keys continue chats they created; organization keys continue organization chats. See [Multi-turn Conversations](/api-reference/concepts/multi-turn).

## Server-side tools

The model can invoke tools automatically while generating a response. Tool calls happen server-side. Only the final assistant text is returned in `result.result`.

| Tool | Description | Key type |
|---|---|---|
| Document reading | Read, query, and search within attached files | All |
| Web search | Search the web for current information | All |
| Research agent | Multi-step web research with synthesis | All |
| Case-law lookup | Search case law databases | User-scoped only |
| Playbook review | Run playbook checks against attached files (requires `playbook_ids`) | All |
| Document editing | Apply redline edits to an attached DOCX. All proposed revisions are auto-accepted; the edited file is returned via `result.documents`. The original file is preserved. | All |
| Document generation | Generate a new DOCX from a prompt. The generated file is returned via `result.documents`. | All |
| Slide generation | Generate a new PowerPoint deck (PPTX) from a prompt. The generated file is returned via `result.documents`. | User-scoped only |
| Email drafting | Draft a structured email from a prompt. The draft is returned via `result.emails` (`to`, `subject`, `body`, …). | All |
| Diagrams | Generate a diagram from a prompt. The diagram is returned via `result.diagrams` as validated Mermaid source (`mermaid`) you can render with any Mermaid-compatible renderer. | All |
| Vault query | Query documents and fields in an attached Contract Intelligence vault (requires `vault_id`) | All (subject to vault authorization) |

The following tools are **not available** via API (the response is plain text with no channel for rich outputs):

| Tool | Reason unavailable |
|---|---|
| Interactive clarification | Requires a back-and-forth channel with the caller |

<Note>
This is an inference endpoint and is [rate limited](/api-reference/concepts/rate-limits): 60 requests/minute per organization (20 per API key). Exceeding the limit returns `429` with a `Retry-After` header.
</Note>



## OpenAPI

````yaml POST /chat/completions
openapi: 3.0.3
info:
  title: GC AI External API
  version: 1.0.0
  description: >-
    The GC AI External API allows programmatic access to GC AI's chat
    capabilities. It's designed for integration with workflow automation tools
    like Zapier, Make, n8n, or custom applications.


    ## Authentication


    All API requests must include an API key in the `Authorization` header:


    ```

    Authorization: gcai_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    ```


    API keys can be created in the GC AI app under **Settings → API**.


    ## Multi-turn Conversations


    Conversations can span multiple turns: pass the `chat_id` returned by a
    completion back on your next request to continue the same chat. See
    [Multi-turn Conversations](/api-reference/concepts/multi-turn).


    ## Current Limitations


    The following is not yet available via API:


    - **Interactive clarification**: the model cannot pause to ask the caller a
    follow-up question; the `askUserQuestions` tool is disabled on the API
    surface


    ## Usage


    Usage is tracked and viewable in the GC AI app under **Settings → API → View
    Usage**.


    ## Support


    For API support, contact [support@gc.ai](mailto:support@gc.ai) or reach out
    to your account representative.
  contact:
    email: support@gc.ai
servers:
  - url: https://app.gc.ai/api/external/v1
    description: Production server
security: []
tags:
  - name: Async Jobs
    description: Poll the status and result of asynchronous API jobs
  - name: Chat
    description: AI chat completion endpoints
  - name: Chats
    description: Chat management, message history, and sharing endpoints
  - name: Contract Intelligence
    description: Vault discovery and document ingestion endpoints for Contract Intelligence
  - name: Files
    description: File upload and management endpoints
  - name: Folders
    description: Folder management endpoints
  - name: Playbooks
    description: Playbook review endpoints
  - name: Profiles
    description: Personal and company profile endpoints
  - name: Projects
    description: Project management endpoints
  - name: Skills
    description: Skill library management endpoints
  - name: Utility
    description: Health check and connectivity endpoints
  - name: Usage
    description: Usage and credit/billing reporting endpoints
paths:
  /chat/completions:
    post:
      tags:
        - Chat
      summary: Create chat completion
      description: >-
        Send a message to GC AI and receive an AI-generated response.


        <Note>

        This endpoint is asynchronous: it returns a job envelope, and the result
        is filled in once the job completes. See [Asynchronous
        Requests](/api-reference/concepts/async-jobs) for how waiting, polling,
        and the envelope work.

        </Note>


        ## Multi-turn conversations


        Every response includes a `chat_id`. Pass it back as `chat_id` on a
        later request to continue that conversation. Conversation state (prior
        messages, tool calls, and any returned documents, emails, or diagrams)
        is held server-side, so each turn sends only the new `message` (plus any
        new `file_ids`); never re-send prior turns or previously returned
        outputs.


        Only one turn may be in flight per chat at a time: a request whose
        `chat_id` already has a turn running is rejected with `409`. Wait for
        the prior turn to reach a terminal state before sending the next.


        Continuing a chat is scoped like
        [materialization](/api-reference/concepts/chat-visibility): personal
        keys continue chats they created; organization keys continue
        organization chats. See [Multi-turn
        Conversations](/api-reference/concepts/multi-turn).


        ## Server-side tools


        The model can invoke tools automatically while generating a response.
        Tool calls happen server-side. Only the final assistant text is returned
        in `result.result`.


        | Tool | Description | Key type |

        |---|---|---|

        | Document reading | Read, query, and search within attached files | All
        |

        | Web search | Search the web for current information | All |

        | Research agent | Multi-step web research with synthesis | All |

        | Case-law lookup | Search case law databases | User-scoped only |

        | Playbook review | Run playbook checks against attached files (requires
        `playbook_ids`) | All |

        | Document editing | Apply redline edits to an attached DOCX. All
        proposed revisions are auto-accepted; the edited file is returned via
        `result.documents`. The original file is preserved. | All |

        | Document generation | Generate a new DOCX from a prompt. The generated
        file is returned via `result.documents`. | All |

        | Slide generation | Generate a new PowerPoint deck (PPTX) from a
        prompt. The generated file is returned via `result.documents`. |
        User-scoped only |

        | Email drafting | Draft a structured email from a prompt. The draft is
        returned via `result.emails` (`to`, `subject`, `body`, …). | All |

        | Diagrams | Generate a diagram from a prompt. The diagram is returned
        via `result.diagrams` as validated Mermaid source (`mermaid`) you can
        render with any Mermaid-compatible renderer. | All |

        | Vault query | Query documents and fields in an attached Contract
        Intelligence vault (requires `vault_id`) | All (subject to vault
        authorization) |


        The following tools are **not available** via API (the response is plain
        text with no channel for rich outputs):


        | Tool | Reason unavailable |

        |---|---|

        | Interactive clarification | Requires a back-and-forth channel with the
        caller |


        <Note>

        This is an inference endpoint and is [rate
        limited](/api-reference/concepts/rate-limits): 60 requests/minute per
        organization (20 per API key). Exceeding the limit returns `429` with a
        `Retry-After` header.

        </Note>
      operationId: createChatCompletion
      parameters:
        - schema:
            type: integer
            nullable: true
            minimum: 0
            description: >-
              Optional long-poll wait time in seconds. Use `0` for
              fire-and-forget behavior. If both `wait` and `Prefer: wait=...`
              are supplied, they must match. Values above 90 are clamped.
            example: 0
          required: false
          description: >-
            Optional long-poll wait time in seconds. Use `0` for fire-and-forget
            behavior. If both `wait` and `Prefer: wait=...` are supplied, they
            must match. Values above 90 are clamped.
          name: wait
          in: query
        - schema:
            type: string
            description: >-
              Optional RFC 7240 wait preference, for example `wait=0`. If both
              this header and the `wait` query parameter are supplied, they must
              match.
            example: wait=0
          required: false
          description: >-
            Optional RFC 7240 wait preference, for example `wait=0`. If both
            this header and the `wait` query parameter are supplied, they must
            match.
          name: Prefer
          in: header
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChatCompletionRequest'
      responses:
        '200':
          description: Job completed within the effective wait window
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatCompletionResponse'
        '202':
          description: >-
            Job accepted but not yet complete, including fire-and-forget
            requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatCompletionResponse'
        '400':
          description: Invalid request body or invalid/conflicting wait controls
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Missing or malformed API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: >-
            Invalid API key, playbook review not enabled for this account, or
            Contract Intelligence is not enabled for this account (when
            `vault_id` is set)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: >-
            One or more `file_ids`, one or more `playbook_ids`, the `chat_id`,
            the `company_id`, or the `vault_id` were not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >-
            The `chat_id` refers to a non-API chat, a turn is already in
            progress for that chat, `company_id` / `vault_id` differs from the
            chat's pinned value (each is fixed for the life of a chat), or
            `vault_id` conflicts with the vault linked to `project_id`
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: >-
            Rate limit exceeded. See [Rate
            Limits](/api-reference/concepts/rate-limits) for the tiers, limits,
            and how to back off.
          headers:
            Retry-After:
              schema:
                type: string
                description: Seconds to wait before retrying after a rate-limit block.
                example: '60'
              required: true
              description: Seconds to wait before retrying after a rate-limit block.
            RateLimit-Limit:
              schema:
                type: string
                description: Request quota for the applicable window.
                example: '3'
              required: true
              description: Request quota for the applicable window.
            RateLimit-Remaining:
              schema:
                type: string
                description: Requests remaining in the current window.
                example: '0'
              required: true
              description: Requests remaining in the current window.
            RateLimit-Reset:
              schema:
                type: string
                description: Seconds until the quota resets.
                example: '60'
              required: true
              description: Seconds until the quota resets.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: Service temporarily unavailable
          headers:
            Retry-After:
              schema:
                type: string
                description: >-
                  Seconds to wait before retrying after a transient service
                  outage.
                example: '5'
              required: true
              description: >-
                Seconds to wait before retrying after a transient service
                outage.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
        - ApiKeyAuth: []
components:
  schemas:
    ChatCompletionRequest:
      type: object
      properties:
        message:
          type: string
          minLength: 1
          description: The user's message or prompt
          example: What are the key terms to look for in a software license agreement?
        file_ids:
          type: array
          items:
            type: string
            format: uuid
          description: >-
            Optional uploaded file IDs to attach as context for this completion.
            Upload files first via `POST /files`.
          example:
            - 123e4567-e89b-12d3-a456-426614174000
        playbook_ids:
          type: array
          items:
            type: string
            format: uuid
          maxItems: 20
          description: >-
            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.
          example:
            - f9e8d7c6-b5a4-3210-fedc-ba0987654321
        playbook_id:
          type: string
          description: >-
            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.
          deprecated: true
        skill_ids:
          type: array
          items:
            type: string
            format: uuid
          description: >-
            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`.
          example:
            - b2c3d4e5-f6a7-4890-bcde-f12345678901
        chat_id:
          type: string
          format: uuid
          description: >-
            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).
          example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
        project_id:
          type: string
          format: uuid
          description: >-
            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).
          example: d4c3b2a1-f6e5-0987-dcba-fedcba098765
        materialize:
          type: boolean
          description: >-
            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).
          example: true
        company_id:
          type: string
          format: uuid
          description: >-
            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).
          example: d4c3b2a1-f6e5-0987-dcba-fedcba098765
        vault_id:
          type: string
          format: uuid
          description: >-
            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.
          example: e5d4c3b2-a1f6-7890-bcde-f1234567890a
      required:
        - message
    ChatCompletionResponse:
      type: object
      properties:
        job_id:
          type: string
          format: uuid
          description: Async job identifier
        kind:
          type: string
          enum:
            - chat/completions
          description: Stable job kind for this endpoint
        status:
          type: string
          enum:
            - pending
            - running
            - succeeded
            - failed
            - canceled
          description: Current job status
        result:
          $ref: '#/components/schemas/ChatCompletionResult'
        error:
          type: object
          nullable: true
          properties:
            code:
              type: string
            message:
              type: string
          required:
            - code
            - message
          description: Failure payload when the job has failed
        created_at:
          type: string
          description: ISO 8601 creation timestamp
        completed_at:
          type: string
          nullable: true
          description: ISO 8601 completion timestamp, or null when not terminal
      required:
        - job_id
        - kind
        - status
        - result
        - error
        - created_at
        - completed_at
    Error:
      type: object
      properties:
        error:
          type: string
          description: Error message
        code:
          type: string
          description: >-
            Machine-readable error code present on some errors (e.g.
            `RATE_LIMITED`, `INSUFFICIENT_CREDITS`, `TRIAL_NOT_STARTED`,
            `BILLING_NOT_CONFIGURED`). Branch on this rather than the
            human-readable `error` string.
        message:
          type: string
          description: Additional error details
        details:
          type: object
          additionalProperties:
            nullable: true
          description: Validation error details (for 400 errors)
      required:
        - error
    ChatCompletionResult:
      type: object
      nullable: true
      properties:
        result:
          type: string
          description: The AI-generated response text
          example: >-
            When reviewing a software license agreement, key terms to examine
            include:


            1. **License Grant** - Understand the scope of rights granted...
        chat_id:
          type: string
          format: uuid
          description: >-
            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).
        chat_url:
          type: string
          format: uri
          description: >-
            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.
          example: https://app.gc.ai/chat/a1b2c3d4-e5f6-7890-abcd-ef1234567890
        documents:
          type: array
          items:
            $ref: '#/components/schemas/ApiDocument'
          description: >-
            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`.
        emails:
          type: array
          items:
            $ref: '#/components/schemas/ApiEmail'
          description: >-
            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.
        diagrams:
          type: array
          items:
            $ref: '#/components/schemas/ApiDiagram'
          description: >-
            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.
      required:
        - result
        - chat_id
      description: Completion payload when the job has succeeded
    ApiDocument:
      type: object
      properties:
        file_id:
          type: string
          format: uuid
          description: >-
            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.
        original_file_id:
          type: string
          format: uuid
          description: >-
            The `file_id` the changes were applied to (edits only). The original
            file is preserved unchanged. Omitted for newly generated documents.
        filename:
          type: string
          description: >-
            Filename of the produced document (edits are prefixed with
            `edited_`).
        original_filename:
          type: string
          description: >-
            Filename of the source file the changes were applied to (edits
            only). Omitted for newly generated documents.
        signed_url:
          type: string
          format: uri
          description: >-
            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.
        download_url:
          type: string
          format: uri
          description: >-
            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.
      required:
        - file_id
        - filename
        - signed_url
        - download_url
    ApiEmail:
      type: object
      properties:
        to:
          type: string
          description: >-
            Recipient email address(es), comma-separated. May be an empty string
            when the prompt named no recipient; fill it in before sending.
        cc:
          type: string
          description: CC recipient email address(es), comma-separated.
        bcc:
          type: string
          description: BCC recipient email address(es), comma-separated.
        subject:
          type: string
          description: >-
            Email subject line. Always present, inferred from context when the
            prompt did not specify one.
        body:
          type: string
          description: Email body in markdown.
        plaintext_body:
          type: string
          description: Email body with markdown stripped, for plain-text clients.
      required:
        - to
        - subject
        - body
        - plaintext_body
    ApiDiagram:
      type: object
      properties:
        title:
          type: string
          description: A short descriptive title for the diagram.
        diagram_type:
          type: string
          description: >-
            The semantic type of diagram, e.g. orgChart, dealStructure,
            workflow, timeline, sequence, entityRelationship, or general.
        mermaid:
          type: string
          description: >-
            The diagram source as validated Mermaid syntax. Render it with any
            Mermaid-compatible renderer.
      required:
        - title
        - diagram_type
        - mermaid
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: |-
        API key for authentication. Format: `gcai_xxxxxxxxx`

        Create API keys in the GC AI app under Settings → API.

````

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