---
title: "Get extraction response for a document grouped by year (V2)"
method: POST
path: "/internal/api/document/v2/{document_id}/response"
tags: ["DOCUMENT"]
---

# Get extraction response for a document grouped by year (V2)

`POST /internal/api/document/v2/{document_id}/response`

## Request

- Base URL: `https://api.signalshq.io` (the document declares no server; this is the origin it was published from)
- URL: `https://api.signalshq.io/internal/api/document/v2/{document_id}/response`
- Auth: OAuth 2
  - Password
  - Token URL: `/auth/login`

V2 endpoint: Returns extracted attributes for the specified document, grouped and sorted by year. Attributes are grouped using the year column stored in the database. Each year group contains attributes with key, display_name, datatype, confidence_score, bounding_regions, status, and optionally document_key (for LLM extractions). Years are sorted in descending order. The document must belong to the authenticated user's tenant and the specified client.

## Path parameters

- `document_id` string, uuid, required: Document ID

## Request body

- DocumentExtractionRequest: Request schema for document extraction response
  - `client_id` string, uuid, required: Client ID for the document

## Response `200`

Successful Response

- DocumentExtractionResponseV2: V2 Response schema for document extraction grouped by year
  - `document_classification` string, nullable: DEPRECATED legacy LLM classification varchar from tenant_client_dms_documents.document_classification. Frozen at upload — NOT updated on reclassify, so it goes stale once the user supersedes the type. Use document_type_identifier for routing.
  - `document_type_identifier` string, nullable: Canonical document_identifier of the document's CURRENT type (e.g. 'SCH_K1_1065'), resolved from the canonical document_type_id. Source of truth after a reclassify — route the review screen on THIS, not on the (possibly stale) document_classification.
  - `data` YearGroupedAttributes[], required: List of year-grouped attribute data, sorted by year (descending)
    - `year` integer, required: Tax year for these attributes
    - `items` ExtractedAttributeItem[], required: List of attributes for this year
      - `id` string, uuid, required: Extracted attribute ID
      - `key` string, required: Vendor attribute name (e.g., 'Box1', 'Part I, Line 1')
      - `display_name` string, required: Human-readable display name
      - `datatype` string, required: Data type of the attribute
      - `value` union, required: Formatted attribute value: single-line string for ADDRESS, otherwise unchanged (str, number, bool, list, or dict).
        - string
        - integer
        - number
        - boolean
        - unknown[]
          - unknown
        - object
      - `confidence_score` number, nullable: Confidence score (0.0 to 1.0)
      - `bounding_regions` BoundingRegion[]: Bounding regions where the attribute was found
        - `page_number` integer, required: Page number where the attribute was found
        - `x1` number, required: X coordinate of first point
        - `y1` number, required: Y coordinate of first point
        - `x2` number, required: X coordinate of second point
        - `y2` number, required: Y coordinate of second point
        - `x3` number, required: X coordinate of third point
        - `y3` number, required: Y coordinate of third point
        - `x4` number, required: X coordinate of fourth point
        - `y4` number, required: Y coordinate of fourth point
      - `status` string, required: Validation status (e.g., 'NEEDS_REVIEW', 'VERIFIED')
      - `document_key` string, nullable: Original line item name (for LLM extractions only)
  - `provided_document_type_id` string, uuid, nullable: Document type UUID from POST /internal/api/document/extract request body when `document_type_id` was supplied (reextract-with-type). Null when extraction was triggered by upload or by extract without that field; resolved type is still stored on the extraction job as `document_type_id`.
  - `extraction_status` string, nullable: Status of the document's latest extraction job (e.g. COMPLETED, FAILED, SKIPPED, UNSUPPORTED). Lets the UI distinguish a genuinely-empty document from one where automatic extraction FAILED or returned nothing — so it can show an 'extraction unavailable, enter values manually' banner instead of treating blank fields as verified-empty. The fields in `data` are always the document type's editable schema.

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/signalshq/apis/signals-api.md) - [All operations](https://skmtc.dev/signalshq/apis/signals-api/llms.txt) - [OpenAPI document](https://skmtc.dev/signalshq/apis/signals-api/revisions/2c22af3b5576?raw)
