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

# Upsert documents

> Creates or replaces one to 50 documents in an index. `doc_id` is the idempotency identity within the index.

A syntactically valid batch returns HTTP 200 after all items are evaluated, even if individual items fail. Clients must inspect `failed` before considering the batch complete.




## OpenAPI

````yaml /openapi/openapi.yaml post /v1/indexes/{index_id}/documents
openapi: 3.1.0
info:
  title: BreadBowl Embed API (Alpha)
  version: 0.1.0-alpha
  description: >
    REST API for managed multi-vector retrieval and transient document scoring.


    BreadBowl Embed accepts source text and returns ranked document and chunk
    references. It does not return conventional embedding vectors.
servers:
  - url: https://embed.breadbowl.ai
    description: Production API
security:
  - bearerAuth: []
tags:
  - name: Service health
    description: Unauthenticated liveness and readiness checks
  - name: Indexes
    description: Create and discover tenant-scoped indexes
  - name: Documents
    description: Upsert and delete indexed documents
  - name: Retrieval
    description: Search an index or score a transient candidate set
  - name: Usage
    description: Inspect current UTC-month usage and assigned limits
paths:
  /v1/indexes/{index_id}/documents:
    post:
      tags:
        - Documents
      summary: Upsert documents
      description: >
        Creates or replaces one to 50 documents in an index. `doc_id` is the
        idempotency identity within the index.


        A syntactically valid batch returns HTTP 200 after all items are
        evaluated, even if individual items fail. Clients must inspect `failed`
        before considering the batch complete.
      operationId: upsertDocuments
      parameters:
        - $ref: '#/components/parameters/IndexId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpsertDocumentsRequest'
            example:
              documents:
                - doc_id: help-center:refunds
                  text: Refund requests are accepted within 30 days of purchase.
                  metadata:
                    source: help-center
                    locale: en
                    status: published
      responses:
        '200':
          description: Batch evaluated; inspect `failed` for item-level failures
          headers:
            x-request-id:
              $ref: '#/components/headers/RequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpsertDocumentsResponse'
              examples:
                complete:
                  summary: All documents succeeded
                  value:
                    index_id: 739c40ce-fa7e-4ba1-bcc2-46632fd13088
                    upserted_documents: 1
                    upserted_chunks: 3
                    failed: []
                    usage:
                      input_tokens: 420
                      document_count: 1
                      chunk_count: 3
                      candidate_count: 0
                      latency_ms: 1800
                partial:
                  summary: One document failed
                  value:
                    index_id: 739c40ce-fa7e-4ba1-bcc2-46632fd13088
                    upserted_documents: 1
                    upserted_chunks: 2
                    failed:
                      - doc_id: empty-document
                        error: document produced no chunks
                    usage:
                      input_tokens: 210
                      document_count: 1
                      chunk_count: 2
                      candidate_count: 0
                      latency_ms: 1200
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
components:
  parameters:
    IndexId:
      name: index_id
      in: path
      required: true
      description: Tenant-scoped index UUID returned by index creation.
      schema:
        type: string
        format: uuid
  schemas:
    UpsertDocumentsRequest:
      type: object
      additionalProperties: false
      required:
        - documents
      properties:
        documents:
          type: array
          minItems: 1
          maxItems: 50
          description: Document IDs must be unique within the request.
          items:
            $ref: '#/components/schemas/DocumentInput'
    UpsertDocumentsResponse:
      type: object
      additionalProperties: false
      required:
        - index_id
        - upserted_documents
        - upserted_chunks
        - failed
        - usage
      properties:
        index_id:
          type: string
          format: uuid
        upserted_documents:
          type: integer
          minimum: 0
        upserted_chunks:
          type: integer
          minimum: 0
        failed:
          type: array
          items:
            $ref: '#/components/schemas/DocumentFailure'
        usage:
          $ref: '#/components/schemas/RequestUsage'
    DocumentInput:
      type: object
      additionalProperties: false
      required:
        - doc_id
        - text
      properties:
        doc_id:
          type: string
          minLength: 1
          maxLength: 255
          description: Idempotency identity within one index.
        text:
          type: string
          minLength: 1
          description: Non-empty source text, at most 100 KiB encoded as UTF-8.
        metadata:
          allOf:
            - $ref: '#/components/schemas/Metadata'
          default: {}
    DocumentFailure:
      type: object
      additionalProperties: false
      required:
        - doc_id
        - error
      properties:
        doc_id:
          type: string
        error:
          type: string
          description: >-
            Diagnostic message. Do not parse application behavior from message
            text.
    RequestUsage:
      type: object
      additionalProperties: false
      required:
        - input_tokens
        - document_count
        - chunk_count
        - candidate_count
        - latency_ms
      properties:
        input_tokens:
          type: integer
          minimum: 0
        document_count:
          type: integer
          minimum: 0
        chunk_count:
          type: integer
          minimum: 0
        candidate_count:
          type: integer
          minimum: 0
        latency_ms:
          type: integer
          minimum: 0
    ErrorResponse:
      type: object
      additionalProperties: false
      required:
        - error
      properties:
        error:
          type: object
          additionalProperties: false
          required:
            - code
            - message
          properties:
            code:
              type: string
              examples:
                - validation_error
            message:
              type: string
            issues:
              type: array
              description: Optional field-level validation details.
              items: {}
    Metadata:
      type: object
      additionalProperties: true
      description: Customer-defined top-level JSON metadata.
  headers:
    RequestId:
      description: Correlation ID for logging and support. This is not a credential.
      schema:
        type: string
        minLength: 1
  responses:
    Unauthorized:
      description: API key is missing, invalid, or revoked
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: authentication_failed
              message: Authentication failed
    Forbidden:
      description: Tenant is suspended
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: tenant_suspended
              message: Tenant is suspended
    NotFound:
      description: Tenant-scoped resource was not found
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: not_found
              message: Not found
    ValidationError:
      description: Request failed validation or would exceed the document allowance
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: validation_error
              message: Request validation failed
              issues: []
    RateLimited:
      description: Request, concurrency, or monthly token limit was reached
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
        Retry-After:
          description: Minimum seconds before retrying.
          schema:
            type: integer
            minimum: 1
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            rate:
              value:
                error:
                  code: rate_limit_exceeded
                  message: Tenant request rate exceeded
            concurrency:
              value:
                error:
                  code: concurrency_limit_exceeded
                  message: Tenant concurrency limit exceeded
            usage:
              value:
                error:
                  code: usage_limit_exceeded
                  message: Monthly input-token allowance exhausted
    InternalError:
      description: Unexpected service failure
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: internal_error
              message: Internal server error
    ServiceUnavailable:
      description: Service cannot process the request temporarily
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: service_unavailable
              message: Service is temporarily unavailable
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: BreadBowl Embed API key
      description: Tenant-scoped API key beginning with `qkv_live_`.

````