---
title: "Ground Sync"
method: POST
path: "/api/v1/ground"
tags: ["public-api"]
---

# Ground Sync

`POST /api/v1/ground`

## Request

- Base URL: `https://ndi-api.nace.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://ndi-api.nace.ai/api/v1/ground`
- Auth: API key in header `X-API-Key`
- TypeScript: <https://skmtc.dev/nace/apis/ndi-service/docs/api/v1/ground/post.ts> (a function with typed inputs; its response is checked against the schema)

Ground values in a document and wait for the result.

## Query parameters

- `timeout_seconds` number: Max seconds to wait before returning 408 (the job keeps running; poll GET /jobs/{job_id}).

## Request body

- GroundJobRequest: Body for ``POST /ground`` and ``POST /ground_async``.
  - `file` FileInput, required: The document to process.
    - `source_url` string, required: ``s3://bucket/key``, ``https://`` (presigned/public), or ``ndi://file/<uuid>`` from ``POST /upload``.
    - `file_name` string, nullable: Original filename and source identity. Required for ``s3://`` / ``https://``. Optional for ``ndi://file/<uuid>`` (defaults to the name captured at upload); the upload's server-verified format remains authoritative.
  - `items` GroundItem[], required: Items to locate in the source (max 30 per request).
    - `item_id` string, required: Caller-assigned identifier echoed back in the result.
    - `query` string, required: Text, value, or phrase to locate. Closest-match wins.
    - `semantic` boolean: When true, ``query`` is a semantic description of what to find (e.g. 'total liabilities') rather than the literal text.
    - `hints` GroundItemHints
      - `visual` GroundVisualHints
        - `anchor_text` string, nullable: Nearby text used to disambiguate the location.
        - `page_hints` integer[], nullable: 1-based page numbers to prioritize.
      - `spreadsheet` GroundSpreadsheetHints
        - `sheet_name` string, nullable: Sheet name hint.
        - `cell_hint` string, nullable: Cell hint such as 'B12'.
        - `range_hint` string, nullable: Range hint such as 'B12:D18'.
      - `audio` GroundAudioHints
        - `transcript_anchor` string, nullable: Nearby transcript text used as an anchor.
  - `derived` GroundDerivedSources: Artifacts from prior NDI runs that speed up / improve grounding.
    - `markdown_url` string, nullable: Markdown from a prior parse of the same file.
    - `transcript_url` string, nullable: Transcript derived from the source media.
    - `jsonl_url` string, nullable: JSONL artifact derived from the source.
    - `ocr_artifact_url` string, nullable: Word-level OCR artifact from a prior parse of the same file.
  - `options` NdiServiceAppSchemasPublicGroundOptions: Caller-tunable grounding options. Providers and model settings are server-owned.
    - `confidence_threshold` number: Minimum confidence to include a match.
    - `return_cropped_images` boolean: Also upload cropped images of visual matches.
    - `use_word_level_grounding` boolean: Experimental. PDF sources only. Deterministic word-level grounding. Targets under 2 normalized characters return status failed with error needle_too_short.
  - `idempotency_key` string, nullable

## Response `200`

Successful Response

- NdiServiceAppSchemasPublicJobStatus: Response for ``GET /jobs/{job_id}`` and the sync endpoints.
  - `job_id` string, uuid, required
  - `action` string, required: One of ``parse``/``ground``/``categorize``/``extract``.
  - `status` string, required: One of ``pending``/``running``/``succeeded``/``failed``.
  - `result` union: Action-specific result (tagged by ``result_type``); populated only when ``status=succeeded``.
    - NdiServiceAppSchemasPublicParseResult
      - `result_type` 'parse'
      - `status` 'success' | 'failed'
      - `error` string, nullable
      - `item` union
        - ParsedFile
          - `item_type` 'file'
          - `markdown_url` string, required
          - `page_count` integer
          - `char_count` integer
          - `extraction_duration_ms` integer
          - `audio_duration_seconds` number: Duration of the source audio in seconds; non-zero only for audio parses.
        - ParsedTable
          - `item_type` 'table'
          - `sheets` ParsedSheet[]
            - `sheet_name` string, required
            - `markdown_url` string, required
            - `max_row` integer
            - `max_col` integer
            - `char_count` integer
            - `non_empty_cell_count` integer
    - NdiServiceAppSchemasPublicGroundResult
      - `result_type` 'ground'
      - `results` GroundItemResult[]
        - `item_id` string, required
        - `found` boolean
        - `matches` union[]
          - union
            - VisualRegionMatch
              - …
            - AudioRangeMatch
              - …
            - SpreadsheetRangeMatch
              - …
            - TextRangeMatch
              - …
            - JsonlRecordMatch
              - …
            - RowRangeMatch
              - …
            - JsonPointerMatch
              - …
        - `error` string, nullable
      - `total_items_found` integer
      - `total_items_requested` integer
      - `duration_ms` integer
      - `transcript_url` string, nullable: Storage URL of the MediaTimeline JSON used for grounding.
    - NdiServiceAppSchemasPublicCategorizeResult
      - `result_type` 'categorize'
      - `status` 'success' | 'failed'
      - `error` string, nullable
      - `items` union[]
        - union
          - CategorizedSegment
            - `kind` 'document_segment'
            - `file_name` string, required
            - `page_start` integer, required
            - `page_end` integer, required
            - `category` string, required
            - `subcategory` string, required
            - `is_freeform_subcategory` boolean
            - `summary` string, required
            - `keywords` string[]
            - `markdown_url` string, nullable
          - CategorizedSheet
            - `kind` 'sheet'
            - `file_name` string, required
            - `sheet_name` string, required
            - `categories` CategorizedCategory[], required
              - …
            - `has_freeform_subcategories` boolean
            - `summary` string, required
            - `keywords` string[]
            - `markdown_url` string, nullable
    - NdiServiceAppSchemasPublicExtractResult
      - `result_type` 'extract'
      - `status` 'success' | 'failed'
      - `error` string, nullable
      - `data` object, nullable: Extracted values matching the request schema. Fields the document does not contain are null (scalars) or empty arrays.
      - `json_url` string, nullable: URL of the extraction JSON artifact (same content as ``data``).
      - `page_count` integer
      - `sheet_count` integer
  - `error` JobError
    - `code` string, required: Stable machine-readable error code.
    - `message` string, required: Human-readable failure detail.
  - `is_example` boolean: True for provisioned Playground example jobs.
  - `created_at` string, date-time, required
  - `started_at` string, date-time, nullable
  - `completed_at` string, date-time, nullable
  - `credits_used` integer, nullable: Credits charged to this job per the ledger. 0 for failed/cancelled jobs (never charged) and zero-credit example jobs; null while the job is non-terminal (not counted yet) or for a succeeded job predating the ledger.

## Other responses

- `202`: The job started but no sync capacity was available; poll GET /jobs/{job_id}.
- `400`: Bad Request
- `401`: Unauthorized
- `402`: Payment Required
- `403`: Forbidden
- `404`: Not Found
- `408`: The job did not finish within timeout_seconds; poll GET /jobs/{job_id}.
- `409`: Conflict
- `413`: Request Entity Too Large
- `422`: Unprocessable Entity
- `500`: Internal Server Error
- `503`: Service Unavailable

---

[API](https://skmtc.dev/nace/apis/ndi-service.md) - [All operations](https://skmtc.dev/nace/apis/ndi-service/llms.txt) - [OpenAPI document](https://skmtc.dev/nace/apis/ndi-service/revisions/d9d1f8ec2207?raw)
