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

# Edit a batch cell

> Override one extracted field on a batch document.

Override one field on a `BatchDocument`. Same rules as the attachment cell route. Not billed.


## OpenAPI

````yaml PATCH /api/v2/batches/{batch_id}/documents/{doc_id}/cells/
openapi: 3.1.0
info:
  title: Abacus Docs API
  version: 1.0.0
  description: |
    REST + SSE surface for Abacus Docs on the same host as the web app
    (`https://abacusdocs.com`). Paths are `/api/v2/…`.

    Authenticate with an organisation API key (`sk-abacus-*`) as a Bearer
    token, or an Auth0 access token. Cross-tenant reads return **404**, not
    403. Page-based lists use `?page=` and `?page_size=`.

    Extraction, reprocess, schema tests, and chat turns spend credits.
    See the help centre Credits pages for rates.
  contact:
    name: Abacus Docs
    url: https://abacusdocs.com/contact
servers:
  - url: https://abacusdocs.com
    description: Production (Extract)
security: []
paths:
  /api/v2/batches/{batch_id}/documents/{doc_id}/cells/:
    patch:
      tags:
        - v2/batches
      summary: Edit one cell on a batch document
      description: >-
        Persists a user-supplied override into
        ``ChatAttachment.extraction_overrides`` keyed by ``field_id``. Send
        ``value: null`` to clear the override and revert the cell to the
        LLM-extracted value.


        The override layer survives reprocess: the user's correction is treated
        as ground truth even when a fresh LLM extraction lands. To drop an edit
        and accept a new LLM value, clear the override explicitly.


        Permission rule: per-user ownership for individual orgs; org moderator
        required for enterprise orgs (stricter than ``BatchReprocessView``,
        which only requires org membership). Read-access alone does NOT grant
        edit rights.
      operationId: v2_batches_documents_cells_partial_update
      parameters:
        - in: path
          name: batch_id
          schema:
            type: integer
          required: true
        - in: path
          name: doc_id
          schema:
            type: integer
          required: true
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchedCellEditRequestRequest'
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CellEditResponse'
          description: ''
        '400':
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
          description: ''
        '403':
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
          description: ''
        '404':
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
          description: ''
      security:
        - extractApiKey: []
        - bearerAuth: []
        - cookieAuth: []
components:
  schemas:
    PatchedCellEditRequestRequest:
      type: object
      description: |-
        PATCH body for editing one cell on one batch document.

        Fields:
            field_id: ID of the schema field whose cell is being edited. Must
                be present in the document's pinned ``StructVersion.schema_json``.
            value: The user-supplied override. ``null`` clears the override and
                reverts the cell to the LLM-extracted value. May be a scalar
                (text/number/date/enum) or a structured object (currency =
                ``{amount, currency}``; table = ``list[dict]``).
            source: Bounded UI surface label so the metric on cell edits stays
                cardinality-safe. ``"grid"`` (default) covers the Hebbia-style
                table on ``/batch/<id>/``; ``"viewer"`` is the side-by-side
                page; ``"modal_table"`` is the nested-table editor modal.
            side: Which side of a translatable field is being edited. Defaults
                to ``"original"`` for backward compatibility with the
                pre-translation request shape. ``"translated"`` is rejected by
                the view when the field is untranslatable (number/currency/
                date/enum) or the schema has no ``output_language`` —
                those cells have no translated side to edit.
      properties:
        field_id:
          type: string
          minLength: 1
          maxLength: 200
        value:
          oneOf:
            - {}
            - type: 'null'
        source:
          allOf:
            - $ref: '#/components/schemas/SourceEnum'
          default: grid
        side:
          allOf:
            - $ref: '#/components/schemas/SideEnum'
          default: original
    CellEditResponse:
      type: object
      description: >-
        200 response from PATCH
        /api/v2/batches/{batch_id}/documents/{doc_id}/cells/.


        Fields:
            cell: The fully-merged cell payload (as returned by ``_to_cell()``).
                Includes both ``v`` (effective value, with override applied)
                and ``v_llm`` (original LLM-extracted value), plus the
                ``is_edited`` boolean and audit fields. The client uses this
                to repaint the single cell in place without a re-fetch. ``null``
                when the user cleared an override on a field the LLM never
                extracted (no row left to render) — clients guard with
                ``if (!cell)`` and skip the in-place repaint.
            doc_summary: Per-doc edit aggregates after the PATCH. Lets the
                client update its "edited X of Y" row badge without doing
                its own bookkeeping.
      properties:
        cell:
          oneOf:
            - {}
            - type: 'null'
        doc_summary:
          $ref: '#/components/schemas/CellEditDocSummary'
      required:
        - cell
        - doc_summary
    SourceEnum:
      enum:
        - grid
        - viewer
        - modal_table
      type: string
      description: |-
        * `grid` - grid
        * `viewer` - viewer
        * `modal_table` - modal_table
    SideEnum:
      enum:
        - original
        - translated
      type: string
      description: |-
        * `original` - original
        * `translated` - translated
    CellEditDocSummary:
      type: object
      description: |-
        Per-doc edit aggregate returned alongside the freshly-merged cell.

        Fields:
            edit_count: Number of fields on this doc with a non-null override
                after the PATCH lands. Equal to ``len(extraction_overrides)``
                but reported here so the client doesn't need a follow-up GET.
            field_count: Total number of fields in the doc's pinned schema
                version. Used by the client to render an "edited X of Y"
                badge on the row.
            edit_ratio: ``edit_count / field_count`` clamped to [0.0, 1.0].
                Always 0.0 when ``field_count == 0`` (plain transcription /
                no-schema doc — the endpoint rejects those before reaching
                this point, but the field is still typed for safety).
      properties:
        edit_count:
          type: integer
          minimum: 0
        field_count:
          type: integer
          minimum: 0
        edit_ratio:
          type: number
          format: double
          maximum: 1
          minimum: 0
      required:
        - edit_count
        - edit_ratio
        - field_count
  securitySchemes:
    extractApiKey:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: |
        Organisation API key from Settings → API / `/api/keys/`. The secret is
        shown once. Send `Authorization: Bearer sk-abacus-…`. One active key
        per organisation. Ingest (`/api/v2/ingest/*`) refuses API keys — that
        surface is Auth0-only with `ingest:read` / `ingest:write` scopes.
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >
        Auth0 access token for a signed-in user. Send `Authorization: Bearer
        <token>`.

        The SPA and desktop agent use this. Prefer an organisation API key for

        server-to-server integrations.
    cookieAuth:
      type: apiKey
      in: cookie
      name: sessionid
      description: |
        Django session cookie from a browser login. Present so the web app can
        call `/api/v2` without a header. Do not rely on this for integrations.

````