---
title: "Stage an external indexer's candidate batch"
method: POST
path: "/v1/documents/{id}/candidates"
tags: ["Indexer work"]
---

# Stage an external indexer's candidate batch

`POST /v1/documents/{id}/candidates`

## Request

- Base URL: `https://brain.inite.ai`
- URL: `https://brain.inite.ai/v1/documents/{id}/candidates`
- Auth: HTTP bearer

A remote indexer that read a stored document submits its reading here. With `runId` + `claimToken` the submission fulfils a claimed work item; without them it opens its own run (claimless flow). Candidates are grounded against the stored text; the Brain commits once every run for the document is settled. Max 200 items per kind. Throttled to 10 requests/min per credential. Part of the document pipeline — answers `503 feature_disabled` until `DOCUMENT_INGEST_ENABLED=1`. Source: src/documents/external-candidates.controller.ts.

Required scope: `indexer:write`.

## Path parameters

- `id` string, required

## Request body

- SubmitCandidatesRequest
  - `claimToken` string
  - `entities` SubmittedEntity[], required
    - `canonical` string
    - `externalId` string: The system-of-record's own id for the entity (a CRM contact id): the authoritative identity — same id ⇒ same entity whatever the name; never merged by name alone.
    - `name` string, required
    - `type` string
  - `facts` SubmittedFact[], required
    - `clause` string
    - `confidence` number
    - `endTime` string: YYYY-MM-DD the value stopped holding; absent = still holds.
    - `entityIndex` integer, required
    - `eventTime` string: YYYY-MM-DD the value began to hold; absent = from when the document says it.
    - `object` string, required
    - `predicate` string, required: Must be namespaced `<indexerId>__*` or a core predicate.
  - `indexerId` string, required: The pack id this indexer is registered as (mode 'external').
  - `packVersion` string: Optional claim of the pack version; must match the installed one.
  - `relations` SubmittedRelation[]
    - `confidence` number
    - `endTime` string: YYYY-MM-DD the relation stopped holding; absent = still holds.
    - `eventTime` string: YYYY-MM-DD the relation began to hold; absent = from when the document says it.
    - `fromEntityIndex` integer, required
    - `kind` string, required
    - `toEntityIndex` integer, required
  - `runId` string: A claimed work item this submission fulfils. Provided together with claimToken or not at all (claimless flow opens its own run).
  - `scenes` object[]: Pack-schema-conforming scene hypotheses (0110). Rejected 400 unless PACK_MEMORY_PROJECTIONS_ENABLED; schemaId must be one of the submitting pack's declared memoryModel.sceneSchemas ids.
    - `confidence` number
    - `gist` string, required: Scene gist text (≤2000 chars).
    - `label` string, required: Short human label (≤200 chars).
    - `occurredFrom` string: ISO datetime; provided together with occurredTo, from ≤ to.
    - `occurredTo` string
    - `schemaId` string, required: ∈ the pack's memoryModel.sceneSchemas[].id.
  - `sourceVersion` object: The revision of the external system of record these claims were read at. Rejected 400 unless PACK_SOURCE_VERSION_STALENESS. Rides into every committed fact's source.sourceVersion, and sweeps the pack's DERIVABLE facts (memoryModel.verificationRules with requires=source_version_match) that were read at an older revision, marking them stale for re-verification.
    - `readAt` string, required: ISO 8601 datetime the derivation read that revision.
    - `ref` string, required: The line within that system — a branch/ref, a matter id, a study series.
    - `system` string, required: System of record the claims were read from: 'git', 'dms', 'ehr', 'ledger', …
    - `version` string, required: The exact revision read — a commit sha, a document revision id.
  - `stateDeltas` object[]: Lifecycle-transition claims (0110) riding scenes of this submission (sceneIndex). Validated against the pack's memoryModel.stateModels; declared transitions stay advisory (never a gate).
    - `confidence` number
    - `from` string: Declared state of the model, when known.
    - `sceneIndex` integer, required: Index into this submission's `scenes` array.
    - `stateModelId` string, required: ∈ the pack's memoryModel.stateModels[].id.
    - `subject` string, required: The subject whose lifecycle moved (≤256 chars).
    - `to` string, required: Declared state of the model.

## Response `201`

Staged (and possibly committed).

- SubmitCandidatesResponse
  - `commit` object, nullable, required: null when the document vanished between staging and commit.
    - `committed` boolean, required
    - `counts` CommitCounts, required
      - `committed` integer, required
      - `merged` integer, required
      - `pending` integer, required
      - `rejected` integer, required
    - `deferred` boolean, required
  - `dropped` GroundingDrop[], required
    - `detail` string, required
    - `index` integer, required
    - `kind` 'entity' | 'fact' | 'relation', required
    - `reason` 'ungrounded_entity' | 'ungrounded_value' | 'orphan_reference', required
  - `packId` string, required
  - `packVersion` string, required
  - `runId` string, required
  - `staged` object, required
    - `entities` integer, required
    - `facts` integer, required
    - `relations` integer, required
    - `scenes` integer
    - `stateDeltas` integer
  - `ungrounded` boolean, required: true when the document has no stored content — spans unverifiable.

## Other responses

- `400`: Validation failed.
- `401`: Missing or unknown bearer key.
- `403`: The key lacks the required scope.
- `404`: No such resource in this tenant.
- `409`: State conflict — e.g. a lost/mismatched claim token, an already claimed work item, or an immutable-version republish.
- `429`: Per-credential throttle exceeded.
- `503`: The document pipeline is dark (DOCUMENT_INGEST_ENABLED off).

---

[API](https://skmtc.dev/inite/apis/inite-brain-platform-api.md) · [All operations](https://skmtc.dev/inite/apis/inite-brain-platform-api/llms.txt) · [OpenAPI document](https://skmtc.dev/inite/apis/inite-brain-platform-api/revisions/c7c3eb5e304b?raw)
