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

# Add a document for a widget's AI to answer from

> Gives the widget's AI a document to answer visitors' questions from. Send the title and the plain text. The call
returns once the document is ready to be used, which takes a few seconds, longer for a long text.

**How it is used.** The text is cleaned, cut into short passages and each passage is turned into numbers (an
embedding) so the widget can find the passages nearest to a question. When a visitor asks, the nearest passages and
the question are shown to an AI model, which writes the answer from them and from nothing else; if the documents
say nothing about the question the visitor is told so, and the owner is not charged for that question. The titles of
the documents an answer used are shown to the visitor as its sources.

**What leaves Widgetic.** The text of a document is sent to OpenAI to be embedded when it is added, and the
passages used for a question are sent to the AI model that writes the answer. Say so in your privacy policy.

**Treat every document as public.** An answer can quote or paraphrase anything a document says, to any visitor of
the widget. Do not add passwords, keys, personal data or anything that must stay private.

**Limits.** A widget holds up to 20 documents, each up to 100000 characters, and up to 400000 characters in all
(`getAiAnswersKnowledge` reports the current numbers). This call takes text. To add a text file or a picture of a
document (a PDF too, once PDFs are read) without turning it into text yourself, use `addAiAnswersKnowledgeFile`. Adding a document costs no
credits. The same text cannot be added twice to one widget (409).

The caller must be allowed to change the widget. An API key needs the `content:write` scope. Adds are limited to ten
in ten minutes per person. A partner's customer in an editor session is one person of its own: its adds are not
counted with the partner's other customers'.




## OpenAPI

````yaml /openapi/widgetic-api-public.json post /compositions/{id}/adapters/ai-answers/knowledge/documents
openapi: 3.0.0
info:
  title: Widgetic API Gateway
  version: 1.0.0
  description: API documentation for the Widgetic API Gateway
  license:
    name: Widgetic Integration License
    url: https://docs.widgetic.com/resources/license
servers:
  - url: https://api.widgetic.com/v1
    description: Production server
    variables:
      env:
        default: production
        description: Environment
      apiUrl:
        default: https://api.widgetic.com
        description: API URL
      apiVersion:
        default: /v1
        description: API Version path prefix
security: []
tags: []
paths:
  /compositions/{id}/adapters/ai-answers/knowledge/documents:
    post:
      tags:
        - Compositions
      summary: Add a document for a widget's AI to answer from
      description: >
        Gives the widget's AI a document to answer visitors' questions from.
        Send the title and the plain text. The call

        returns once the document is ready to be used, which takes a few
        seconds, longer for a long text.


        **How it is used.** The text is cleaned, cut into short passages and
        each passage is turned into numbers (an

        embedding) so the widget can find the passages nearest to a question.
        When a visitor asks, the nearest passages and

        the question are shown to an AI model, which writes the answer from them
        and from nothing else; if the documents

        say nothing about the question the visitor is told so, and the owner is
        not charged for that question. The titles of

        the documents an answer used are shown to the visitor as its sources.


        **What leaves Widgetic.** The text of a document is sent to OpenAI to be
        embedded when it is added, and the

        passages used for a question are sent to the AI model that writes the
        answer. Say so in your privacy policy.


        **Treat every document as public.** An answer can quote or paraphrase
        anything a document says, to any visitor of

        the widget. Do not add passwords, keys, personal data or anything that
        must stay private.


        **Limits.** A widget holds up to 20 documents, each up to 100000
        characters, and up to 400000 characters in all

        (`getAiAnswersKnowledge` reports the current numbers). This call takes
        text. To add a text file or a picture of a

        document (a PDF too, once PDFs are read) without turning it into text
        yourself, use `addAiAnswersKnowledgeFile`. Adding a document costs no

        credits. The same text cannot be added twice to one widget (409).


        The caller must be allowed to change the widget. An API key needs the
        `content:write` scope. Adds are limited to ten

        in ten minutes per person. A partner's customer in an editor session is
        one person of its own: its adds are not

        counted with the partner's other customers'.
      operationId: addAiAnswersKnowledgeDocument
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
            format: uuid
          description: The widget (composition) to add the document to
        - $ref: '#/components/parameters/ManagedUserScopeId'
        - $ref: '#/components/parameters/ManagedUserScopeExternalId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddAiAnswersKnowledgeDocumentRequest'
      responses:
        '201':
          description: The document was added and is ready to be used
          content:
            application/json:
              schema:
                title: AiAnswersKnowledgeDocumentResponse
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/AiAnswersKnowledgeDocument'
                  meta:
                    $ref: '#/components/schemas/ResponseMeta'
                required:
                  - success
                  - data
        '400':
          description: >-
            The widget id is not valid, the body is not exactly `title` and
            `text`, or the title or the text is missing or too long
            (KNOWLEDGE_TITLE_REQUIRED, KNOWLEDGE_TITLE_TOO_LONG,
            KNOWLEDGE_TEXT_REQUIRED)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: The API key is missing or invalid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: >-
            The widget belongs to another account, or the API key lacks the
            `content:write` scope
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: There is no such widget
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: >-
            The same text is already in this widget, or the widget already holds
            the most documents it can (KNOWLEDGE_DUPLICATE_DOCUMENT,
            KNOWLEDGE_LIMIT_DOCUMENTS)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '413':
          description: >-
            The text is longer than a document may be, or would take the widget
            past the most text it can hold in all (KNOWLEDGE_TEXT_TOO_LONG,
            KNOWLEDGE_LIMIT_TOTAL_TEXT). Nothing was saved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: >-
            Too many documents added in a short time. Try again after the
            Retry-After seconds.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '502':
          description: >-
            The document could not be processed or saved
            (KNOWLEDGE_NOT_COMPLETED). Nothing was saved: try again
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: >-
            The knowledge base is not available right now, or the service is
            busy (KNOWLEDGE_UNAVAILABLE, KNOWLEDGE_BUSY). Nothing was saved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - apiKeyAuth: []
      x-code-samples:
        - lang: TypeScript
          label: TypeScript SDK
          source: >
            import { Configuration, CompositionsApi } from
            '@widgetic/api-sdk-ts';


            const compositionsApi = new CompositionsApi(new Configuration({
            apiKey: 'YOUR_API_KEY' }));


            const { data: document } = await
            compositionsApi.addAiAnswersKnowledgeDocument({
              id: compositionId,
              addAiAnswersKnowledgeDocumentRequest: {
                title: 'Shipping and returns',
                text: 'Orders ship within 2 business days. Returns are accepted for 30 days after delivery.',
              },
            });

            console.log(document.id, document.status);
components:
  parameters:
    ManagedUserScopeId:
      in: header
      name: X-Managed-User-Id
      required: false
      description: >-
        The id Widgetic gave the managed user (`POST /managed-users`). Makes
        this call for one of your managed users, so that a mistake in your own
        code cannot reach another customer's work. Send this header, or the
        other one, never both. Left out, the call works on your whole account,
        as it always has. With it, the call reaches only that user's
        compositions and workflows: a list shows only theirs, a composition or a
        workflow the call makes is filed under them, and one of another user, or
        one that does not exist, answers `404` (the same answer, so the call
        cannot be used to find out what another customer has). A managed user
        that is not yours answers `404` with `MANAGED_USER_NOT_FOUND`. An empty,
        repeated or malformed header is `400` with `MANAGED_USER_SCOPE_INVALID`;
        an empty header is never read as no header. A call that is about the
        whole account, such as the list of your managed users, is refused with
        `403` and `MANAGED_USER_SCOPE_ROUTE_NOT_AVAILABLE`: send it without the
        header. Only your API key can send it. The header is a limit the call
        asks for: whoever holds the key can leave it out, so for a credential
        that a customer's browser holds, use an editor session. An
        `Idempotency-Key` is kept apart for each managed user.
      schema:
        type: string
        format: uuid
        example: 3f2b8c1e-7a4d-4e0b-9c55-2d1a6b7e8f90
    ManagedUserScopeExternalId:
      in: header
      name: X-Managed-User-External-Id
      required: false
      description: >-
        Your own id for the managed user (its `externalId`), when you do not
        keep Widgetic's. Makes this call for one of your managed users, so that
        a mistake in your own code cannot reach another customer's work. Send
        this header, or the other one, never both. Left out, the call works on
        your whole account, as it always has. With it, the call reaches only
        that user's compositions and workflows: a list shows only theirs, a
        composition or a workflow the call makes is filed under them, and one of
        another user, or one that does not exist, answers `404` (the same
        answer, so the call cannot be used to find out what another customer
        has). A managed user that is not yours answers `404` with
        `MANAGED_USER_NOT_FOUND`. An empty, repeated or malformed header is
        `400` with `MANAGED_USER_SCOPE_INVALID`; an empty header is never read
        as no header. A call that is about the whole account, such as the list
        of your managed users, is refused with `403` and
        `MANAGED_USER_SCOPE_ROUTE_NOT_AVAILABLE`: send it without the header.
        Only your API key can send it. The header is a limit the call asks for:
        whoever holds the key can leave it out, so for a credential that a
        customer's browser holds, use an editor session. An `Idempotency-Key` is
        kept apart for each managed user.
      schema:
        type: string
        minLength: 1
        maxLength: 255
        example: customer-1042
  schemas:
    AddAiAnswersKnowledgeDocumentRequest:
      type: object
      required:
        - title
        - text
      additionalProperties: false
      properties:
        title:
          type: string
          maxLength: 120
          description: >-
            What the document is called, on one line. Visitors see it as the
            source of an answer. Line breaks and invisible characters are
            removed
          example: Shipping and returns
        text:
          type: string
          maxLength: 100000
          description: >-
            The text of the document, as plain text. It is cleaned (line endings
            are made the same, invisible characters and surplus blank lines are
            removed) and then counted: up to 100000 characters. Markup is not
            interpreted, so paste the words, not a web page
          example: >-
            Orders ship within 2 business days. Returns are accepted for 30 days
            after delivery, in the original packaging.
      example:
        title: Shipping and returns
        text: >-
          Orders ship within 2 business days. Returns are accepted for 30 days
          after delivery, in the original packaging.
    AiAnswersKnowledgeDocument:
      type: object
      description: >-
        One document in a widget's knowledge base: what the widget's AI answers
        visitors' questions from. Its text is not part of this: it is kept so
        the widget can find the passages that answer a question, and is never
        returned.
      required:
        - id
        - title
        - status
        - charCount
        - chunkCount
        - createdAt
        - readyAt
      properties:
        id:
          type: string
          format: uuid
          description: Use it to remove the document
        title:
          type: string
          maxLength: 120
          description: >-
            What the document is called. Visitors see it as the source of an
            answer, so write it for them
          example: Shipping and returns
        status:
          type: string
          enum:
            - processing
            - ready
          description: >-
            `ready` documents are used to answer questions. A `processing`
            document is not: it is being added, or an add was interrupted.
            Remove one that stays in this state and add it again
        charCount:
          type: integer
          description: How many characters of text the document holds, after it was cleaned
          example: 4210
        chunkCount:
          type: integer
          description: >-
            Into how many passages the text was cut. Zero until the document is
            ready
          example: 6
        createdAt:
          type: string
          format: date-time
        readyAt:
          type: string
          format: date-time
          nullable: true
          description: When the document became ready. Null while it is not
      example:
        id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        title: Shipping and returns
        status: Example status
        charCount: 4210
        chunkCount: 6
        createdAt: '2026-01-15T09:30:00.000Z'
        readyAt: '2026-01-15T09:30:00.000Z'
    ResponseMeta:
      type: object
      description: >-
        Extra information about the answer: where a page sits in a list, the
        cursor of the next page, or warnings about a call that succeeded with a
        caveat.
      additionalProperties: true
      properties:
        page:
          type: integer
          description: The page that was read, counting from 1.
          example: 1
        size:
          type: integer
          description: How many items one page holds.
          example: 20
        total:
          type: integer
          description: How many items the whole list has.
          example: 135
        limit:
          type: integer
          description: The same as `size`.
          example: 20
        offset:
          type: integer
          description: How many items come before this page.
          example: 0
        hasNextPage:
          type: boolean
          example: true
        hasPreviousPage:
          type: boolean
          example: false
        nextCursor:
          type: string
          nullable: true
          description: >-
            Pass this as `cursor` to read the next page of a list that is read
            by cursor. `null` on the last page.
        warnings:
          type: array
          items:
            type: string
          description: >-
            Things the call did not do, though it succeeded (for example a table
            that could not be created just now).
    ErrorResponse:
      type: object
      required:
        - success
        - message
        - error
      additionalProperties: true
      properties:
        success:
          type: boolean
          description: Always `false` on a failure.
          example: false
        message:
          type: string
          description: The same text as `error.message`, for a caller that reads one line.
        error:
          $ref: '#/components/schemas/ErrorDetail'
    ErrorDetail:
      type: object
      required:
        - code
        - message
        - timestamp
      properties:
        code:
          type: string
          description: Machine-readable error code.
          example: RESOURCE_NOT_FOUND
        message:
          type: string
          description: Human-readable explanation.
          example: Composition not found
        param:
          type: string
          description: The field that caused the error, when one did.
          example: name
        docUrl:
          type: string
          description: Where this error is explained.
        suggestedAction:
          type: string
          description: What to do about it.
        retryAfter:
          type: integer
          description: >-
            Seconds to wait before trying again (rate limits). The same number
            is in the `Retry-After` header.
          example: 60
        details:
          type: object
          additionalProperties: true
          description: >-
            More about the error: the fields that failed, a limit that was
            reached.
        correlationId:
          type: string
          description: Quote this when you ask support about the call.
          example: req_123e4567-e89b-12d3-a456-426614174000
        timestamp:
          type: string
          format: date-time
          example: '2026-10-15T10:00:00.000Z'
  securitySchemes:
    apiKeyAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````

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