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

# Get structured output

> Returns the JSON object the run produced against its output schema — the
payload shaped by the agent's configured output keys, or by the
`output_config` sent with `POST /v1/agents/{agent_id}/run`.

This is the endpoint to poll when you want machine-readable fields.
`/summary` returns the agent's final written answer; `/result` returns the
whole reasoning transcript. Neither is the schema'd object.

Short of an infrastructure failure, the call answers `200` while the task
exists and belongs to your workspace — a run that produced nothing is not an
error here. Which field is populated says what happened:

| Field | Meaning |
|---|---|
| `structured_response` | The output, present and readable. |
| `message` | The run has not finished (`pending`, `queued`, `running`, `waiting_for_input`, `awaiting_review`). Poll again. |
| `error` | No output schema is configured on the agent or the task, or the run ended without writing one. |




## OpenAPI

````yaml GET /api/v1/tasks/{task_id}/structured-response
openapi: 3.1.0
info:
  title: Nanonets Agents Platform — Public API
  version: 1.0.0
  summary: >-
    Programmatically run AI agents, send follow-up messages, fetch results, and
    update agent prompts.
  description: >
    The Nanonets Agents Platform Public API lets you trigger agents, stream task
    progress,

    and integrate agent outputs into your own systems.


    ## Authentication


    All requests must include a workspace API key as a Bearer token:


    ```

    Authorization: Bearer YOUR_API_KEY

    ```


    Workspace API keys are minted from the web app under **Settings → API
    Keys**. Each key

    is scoped to a single workspace; requests against agents or tasks outside
    that workspace

    return `403`.


    ## Lifecycle


    A typical integration is three calls:


    1. `POST /v1/agents/{agent_id}/run` — start a task. Returns a `task_id`
    immediately.

    2. Poll `GET /v1/tasks/{task_id}` until `status` is a terminal value
    (`completed`,
       `failed`, or `stopped`), **or** wait until it reaches `waiting_for_input` to
       respond with `POST /v1/tasks/{task_id}/message`.
    3. `GET /v1/tasks/{task_id}/summary` for the final answer, or `/result` for
    the full
       reasoning trace.

    ## Errors


    Every error response is `{"error": "<human-readable message>"}`. The HTTP
    status

    indicates the class:


    | Status | Meaning |

    |--------|---------|

    | 400 | Malformed request (bad UUID, missing required field, file too large)
    |

    | 401 | Missing or invalid API key |

    | 403 | API key is valid but the agent/task belongs to a different workspace
    |

    | 404 | Agent or task not found |

    | 500 | Server error — safe to retry with backoff |
  contact:
    name: Nanonets Support
    url: https://nanonets.com/support
  license:
    name: Proprietary
servers:
  - url: https://agents.nanonets.com
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Agents
    description: Manage agents — create, list, update, run, and version.
  - name: Tasks
    description: >-
      Inspect task status, fetch results, list and cancel tasks, and send
      follow-up messages.
paths:
  /api/v1/tasks/{task_id}/structured-response:
    get:
      tags:
        - Tasks
      summary: Get the task's structured output
      description: >
        Returns the JSON object the run produced against its output schema — the

        payload shaped by the agent's configured output keys, or by the

        `output_config` sent with `POST /v1/agents/{agent_id}/run`.


        This is the endpoint to poll when you want machine-readable fields.

        `/summary` returns the agent's final written answer; `/result` returns
        the

        whole reasoning transcript. Neither is the schema'd object.


        Short of an infrastructure failure, the call answers `200` while the
        task

        exists and belongs to your workspace — a run that produced nothing is
        not an

        error here. Which field is populated says what happened:


        | Field | Meaning |

        |---|---|

        | `structured_response` | The output, present and readable. |

        | `message` | The run has not finished (`pending`, `queued`, `running`,
        `waiting_for_input`, `awaiting_review`). Poll again. |

        | `error` | No output schema is configured on the agent or the task, or
        the run ended without writing one. |
      operationId: getStructuredResponse
      parameters:
        - $ref: '#/components/parameters/TaskIdPath'
        - $ref: '#/components/parameters/IncludeCitations'
      responses:
        '200':
          description: Task metadata plus the structured output, when one is available.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetStructuredResponseResponse'
              examples:
                plain:
                  summary: Default — plain values
                  value:
                    task_id: f1c2a3b4-0000-0000-0000-000000000000
                    agent_id: 9a8b7c6d-0000-0000-0000-000000000000
                    status: completed
                    created_at: '2026-09-22T10:00:00Z'
                    updated_at: '2026-09-22T10:00:42Z'
                    structured_response:
                      invoice_number: INV-1043
                      total: 1290.5
                withCitations:
                  summary: include_citations=true
                  value:
                    task_id: f1c2a3b4-0000-0000-0000-000000000000
                    agent_id: 9a8b7c6d-0000-0000-0000-000000000000
                    status: completed
                    created_at: '2026-09-22T10:00:00Z'
                    updated_at: '2026-09-22T10:00:42Z'
                    structured_response:
                      invoice_number:
                        value: INV-1043
                        bounding_boxes:
                          - citation_id: 41
                            file: invoice.pdf
                            page: 1
                            bounding_box:
                              - 812
                              - 190
                              - 1015
                              - 222
                            normalized_bounding_box:
                              - x: 0.477
                                'y': 0.086
                              - x: 0.596
                                'y': 0.086
                              - x: 0.596
                                'y': 0.101
                              - x: 0.477
                                'y': 0.101
                    documents:
                      - file: invoice.pdf
                        url: https://files.nanonets.com/...
                        pages:
                          - page: 1
                            width: 1700
                            height: 2200
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/ServerError'
components:
  parameters:
    TaskIdPath:
      name: task_id
      in: path
      required: true
      description: UUID of the task.
      schema:
        type: string
        format: uuid
    IncludeCitations:
      name: include_citations
      in: query
      required: false
      description: >
        `true` returns each value with the place in the source document it was
        read

        from, plus a `documents` block resolving those files.


        Two separate switches, deliberately: **Keep citations**

        (`structured_output_citations`) on the agent decides whether citations
        are

        *produced*; this parameter decides whether they are *returned*. So
        turning

        the agent setting on for the dashboard never changes the bytes an
        existing

        API consumer already parses.


        Off (the default), every leaf is a plain value, whether or not the agent

        keeps citations. On, a leaf that has provenance becomes

        `{"value": ..., "bounding_boxes": [...]}`; leaves with no document
        source

        (a value from a database lookup, say) stay plain. Asking an agent that

        keeps no citations is not an error — the payload comes back unchanged
        and

        `documents` is omitted.


        Prefer `normalized_bounding_box` (0–1, origin top-left) when drawing:

        `bounding_box` is absolute pixels and needs the page dimensions from

        `documents`. Spreadsheet and text sources carry `sheet`/`cell` or

        `line_start`/`line_end` instead of a box.
      schema:
        type: boolean
        default: false
  schemas:
    GetStructuredResponseResponse:
      type: object
      required:
        - task_id
        - agent_id
        - status
        - created_at
        - updated_at
      properties:
        task_id:
          type: string
          format: uuid
        agent_id:
          type: string
          format: uuid
        status:
          $ref: '#/components/schemas/TaskStatus'
        title:
          type:
            - string
            - 'null'
        structured_response:
          description: >
            The run's output against its schema. Leaves are plain values unless

            `include_citations=true`, in which case a leaf with provenance
            becomes

            `{ "value": ..., "bounding_boxes": [...] }`.


            Key filtering rides along with citations rather than being
            universal:

            `include_citations=true` also drops the platform's internal keys

            (`__`-prefixed, plus `_meta` on a cited leaf). The default path
            unwraps

            leaves and filters nothing, so an internal key a run happened to
            write

            reaches you unchanged. Read the keys your schema declares rather
            than

            assuming the object holds only those.


            Omitted when no output is available — read `message` / `error` to
            tell

            "not yet" from "never".
        documents:
          type: array
          description: >
            The source files this response's citations name, so a value can be
            drawn

            on the page it came from. Present only with `include_citations=true`
            on a

            run that produced citations.
          items:
            $ref: '#/components/schemas/ExtractionDocument'
        message:
          type: string
          description: >-
            Set when the run is still in flight, so the output may yet appear.
            Poll again.
        error:
          type: string
          description: >
            Set when no output can ever arrive for this task — no output schema
            is

            configured, or the run reached a terminal state without writing one.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    TaskStatus:
      type: string
      description: >
        Lifecycle status of a task.


        - `pending` — created, not yet picked up

        - `queued` — held back by admission control (agent at concurrent-task
        limit)

        - `running` — being processed by the worker

        - `waiting_for_input` — agent called `ask_user`; reply with `POST
        /tasks/{id}/message`

        - `awaiting_review` — agent is paused for human approval of a sensitive
        step

        - `completed` — terminal: finished successfully

        - `failed` — terminal: errored out

        - `stopped` — terminal: cancelled by a user or system
      enum:
        - pending
        - queued
        - running
        - waiting_for_input
        - awaiting_review
        - completed
        - failed
        - stopped
    ExtractionDocument:
      type: object
      required:
        - file
      properties:
        file:
          type: string
          description: File name as the citation records it.
        url:
          type: string
          description: >
            Time-limited link to the document. Absent when the file cannot be

            resolved (deleted, or generated by a tool rather than uploaded) —
            the

            citation is still valid, it just cannot be rendered from this
            response.
        pages:
          type: array
          description: |
            Pixel dimensions each page's `bounding_box` values are relative to.
            Derived, and omitted for a page too sparse to derive them from;
            `normalized_bounding_box` needs none of this.
          items:
            type: object
            required:
              - page
            properties:
              page:
                type: integer
              width:
                type: integer
              height:
                type: integer
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          description: Human-readable error message.
          examples:
            - Invalid agent_id format
  responses:
    BadRequest:
      description: >-
        Malformed request — invalid UUID, missing required field, or oversized
        file.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: API key is valid but the resource belongs to a different workspace.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: Agent or task not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    RateLimited:
      description: |
        Rate limit exceeded for this API key. Rate limiting is enabled per
        environment, and where it is on the bucket is per key across the whole
        /v1 surface rather than per route — so polling draws on the same budget
        as runs. Wait the interval in Retry-After before retrying.
      headers:
        Retry-After:
          schema:
            type: integer
          description: Seconds to wait. Never 0.
    ServerError:
      description: Unexpected server error. Safe to retry with exponential backoff.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: |
        Workspace API key issued from the web app. Pass as
        `Authorization: Bearer YOUR_API_KEY`.

````