---
title: "Answer the questions an extraction stopped to ask"
method: POST
path: "/extractions/{extraction_id}/answers"
tags: ["Extractions"]
---

# Answer the questions an extraction stopped to ask

`POST /extractions/{extraction_id}/answers`

## Request

- Base URL: `https://api.invoicedataextraction.com/v1`
- URL: `https://api.invoicedataextraction.com/v1/extractions/{extraction_id}/answers`
- Auth: HTTP bearer

Answers open questions of an extraction whose status is `input_required`. Answer every
open question in one request or across several; the extraction continues the moment
every open question has an answer. The response is the extraction's status after the
answers, exactly as `getExtraction` returns it.

An answer governs the whole extraction, every document in it and not only the one in
the question's example; where the right answer differs by document type, say so in
`text`, which is accepted on every question. Your own words are screened before they are
used: an answer given in bad faith, one that tries to misuse the service rather than
answer the question, is refused and the question is asked again with
`previous_answer_rejected: true`; after three refused answers the extraction is
cancelled with `cancellation_reason: answers_rejected`. A vague or undecided answer is
not refused: it is applied, and the matter may be asked again as a new question.

An answer to a question that is no longer waiting changes nothing and returns the
current status, so a request can be repeated after a dropped connection. Only a request
that could never be right is refused, whole, with `INVALID_INPUT`.

Rate limit: 30 requests per minute per API key.

## Path parameters

- `extraction_id` string, uuid, required

## Query parameters

- `scope` 'own' | 'team'

## Request body

- AnswerQuestionsRequest
  - `answers` Answer[], required
    - union: Names a question and gives one of: a `choice_id`, with `text` beside it if you like; `text` alone; or `accept_recommended: true`.
      - object
        - `question_id` string, required
        - `choice_id` string, required: A `choice_id` of a `single_choice` question.
        - `text` string: Your own words. Accepted on every question, alone or beside a `choice_id`.
      - object
        - `question_id` string, required
        - `text` string, required: Your own words. Accepted on every question, alone or beside a `choice_id`.
      - object
        - `question_id` string, required
        - `accept_recommended` true, required: Take the recommended choice, or on a `free_text` question the recommended approach.

## Response `200`

The extraction's status after the answers.

- union: The status response, one shape per `status`.
  - ExtractionProcessing
    - `success` true, required
    - `status` 'processing', required
    - `extraction_id` string, uuid, required
    - `progress` integer, required
  - ExtractionInputRequired: The extraction stopped to ask. Questions appear the moment they exist, and every open question of the extraction is listed together. If the questions are not all answered within about four minutes, the extraction pauses and waits, and the account owner is emailed that a task is waiting for an answer, with a second email before the deadline. If the questions are not all answered by `answer_by`, which is 40 hours after the files were uploaded, the extraction is cancelled with `cancellation_reason: unanswered` and the work done so far is charged. The extraction continues the moment every open question has an answer.
    - `success` true, required
    - `status` 'input_required', required
    - `extraction_id` string, uuid, required
    - `progress` integer, required
    - `answer_by` string, date-time, required
    - `questions` Question[], required
      - `question_id` string, required: Use it when answering.
      - `type` 'single_choice' | 'free_text', required: `single_choice` offers `choices`; answer with one, with words added if you like. `free_text` wants your own words, or the recommended approach. Words are accepted on every question, so an unrecognised type can still be answered with `text`.
      - `question` string, required
      - `example_from_documents` string: A real instance from the documents that the answer would change.
      - `scope` QuestionScope, required
        - `level` 'extraction', required: What the answer governs. `extraction` is the only value today: every document in the extraction, not only the one in the example. Treat a value you do not recognise as narrower than the extraction and read `applies_to`.
        - `applies_to` string, required: The scope in words, for whoever is answering.
      - `choices` QuestionChoice[], required: Empty for `free_text`.
        - `choice_id` string, required: A letter, `a` onwards.
        - `label` string, required
        - `cell_would_contain` string: The value this choice would put in the cell for the example, when known.
        - `recommended` true: Present on the one choice the extraction recommends.
      - `recommended_approach` string: On a `free_text` question, what the extraction does if you accept the recommendation.
      - `previous_answer_rejected` true: Present when an earlier answer to this question was refused. Answer differently.
  - ExtractionCompleted
    - `success` true, required
    - `status` 'completed', required
    - `extraction_id` string, uuid, required
    - `credits_deducted` integer, nullable, required: One credit per successfully processed page.
    - `credits_balance` integer, required: The account's total balance after this extraction was charged.
    - `credits_reserved` integer, required: Credits held by extractions still in progress; usable balance is `credits_balance` minus this.
    - `output_structure` 'per_invoice' | 'per_line_item', required: The resolved structure, also when `automatic` was submitted.
    - `output_expires_at` string, date-time, required: 90 days after submission; after it the output URLs are `null` and the rows and files are gone.
    - `pages` Pages, required: Which pages were processed and which failed; data from failed pages is missing from the output.
      - `successful_count` integer, required
      - `failed_count` integer, required
      - `successful` PageReference[], required
        - `file_name` string, required
        - `page` integer, required
      - `failed` PageReference[], required
        - `file_name` string, required
        - `page` integer, required
      - `failure_reasons` PageFailureReason[], required
        - `code` string, required
        - `message` string, required
        - `affected_pages` object[], required
          - `file_name` string, required
          - `pages` integer[], required
    - `ai_uncertainty_notes` UncertaintyNote[], required
      - `topic` string, required
      - `description` string, required
      - `suggested_prompt_additions` object[], required
        - `purpose` string, required
        - `instructions` string[], required
    - `review_needed` ReviewNeeded, required: Rows that need a human's check before the data is relied on. Check `count` first.
      - `count` integer, required
      - `items` ReviewNeededItem[], required
        - `message` string, required
        - `affected_fields` string[], required: Empty when the concern is about the row or document rather than particular fields.
        - `output_row_numbers` integer[], required: 1-based data row numbers, not counting the header row.
        - `source_references` string[], required
    - `output` OutputUrls, required: Signed URLs valid for 5 minutes; `null` when a format was not generated or the output has expired.
      - `xlsx_url` string, uri, nullable, required
      - `csv_url` string, uri, nullable, required
      - `json_url` string, uri, nullable, required
  - ExtractionFailed: HTTP 200 with `success: false`. Where the next step is to submit again, use a new `submission_id`.
    - `success` false, required
    - `status` 'failed', required
    - `extraction_id` string, uuid, required
    - `error` ExtractionFailureError, required
      - `code` 'INSUFFICIENT_CREDITS' | 'FILE_PAGE_LIMIT_EXCEEDED' | 'ENCRYPTED_FILE' | 'CONCURRENT_TASK_LIMIT' | 'NO_PAGES_FOUND' | 'VALIDATION_FAILED' | 'PROMPT_REJECTED' | 'PROMPT_UNCLEAR' | 'FILE_SIZE_LIMIT_EXCEEDED' | 'PROCESSING_FILE_SIZE_LIMIT_EXCEEDED' | 'SUBMISSION_STALLED' | 'INTERNAL_ERROR', required: Why an extraction failed. Retryable codes may succeed when submitted again with a new `submission_id`: `CONCURRENT_TASK_LIMIT` (as many extractions running as the account allows, 15 by default and more on request, counting those started in the web app), `SUBMISSION_STALLED`, `INTERNAL_ERROR`. The others need a change first: `INSUFFICIENT_CREDITS` (details: `credits_required`, `credits_balance`, `credits_reserved`), `FILE_PAGE_LIMIT_EXCEEDED` and `ENCRYPTED_FILE` (details: `file_names`), `NO_PAGES_FOUND`, `VALIDATION_FAILED`, `PROMPT_REJECTED`, `PROMPT_UNCLEAR`, `FILE_SIZE_LIMIT_EXCEEDED`, `PROCESSING_FILE_SIZE_LIMIT_EXCEEDED`.
      - `message` string, required
      - `retryable` boolean, required
      - `details` object, nullable, required
  - ExtractionCancelled: No output is produced; `credits_deducted` covers the work done before the extraction stopped.
    - `success` true, required
    - `status` 'cancelled', required
    - `extraction_id` string, uuid, required
    - `credits_deducted` integer, nullable, required
    - `cancellation_reason` 'user' | 'unanswered' | 'answers_rejected', required: `user`: cancelled from the dashboard or with `cancelExtraction`. `unanswered`: a question was not answered by `answer_by`. `answers_rejected`: three answers were refused.
    - `credits_balance` integer, required
    - `credits_reserved` integer, required

## Other responses

- `400`: `INVALID_INPUT`: the id is not a UUID, `scope` is not `own` or `team`, or the body could never be right: `details.issues` names the answer and the field, for a `question_id` the extraction never asked, a `choice_id` it does not offer, empty or over-long `text`, `accept_recommended` sent with `choice_id` or `text`, or a question answered twice in one request.
- `401`: `UNAUTHENTICATED`, `API_KEY_EXPIRED` or `API_KEY_REVOKED`.
- `403`: `FORBIDDEN`: `scope=team` from a caller who is not a team admin.
- `404`: `EXTRACTION_NOT_FOUND`: no extraction with this id within the caller's scope.
- `429`: `RATE_LIMITED`: wait `details.retry_after_seconds` (also the `Retry-After` header), then retry.
- `500`: `INTERNAL_ERROR`: retry after a short delay.

---

[API](https://skmtc.dev/invoicedataextraction/apis/invoice-data-extraction-api.md) · [All operations](https://skmtc.dev/invoicedataextraction/apis/invoice-data-extraction-api/llms.txt) · [OpenAPI document](https://skmtc.dev/invoicedataextraction/apis/invoice-data-extraction-api/revisions/16d920350483?raw)
