---
title: "Get job status"
method: GET
path: "/jobs/{job_id}"
tags: ["jobs"]
---

# Get job status

`GET /jobs/{job_id}`

## Request

- Base URL: `https://api.scipot.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.scipot.ai/jobs/{job_id}`
- Auth: none declared
- TypeScript: <https://skmtc.dev/scipot/apis/scipot-core-api/docs/jobs/:job_id/get.ts> (a function with typed inputs; its response is checked against the schema)

Get status of an ingestion job.

Poll this endpoint to track progress of async ingestion.

**Job Lifecycle:**
- `pending`: Job queued, not started
- `processing`: Job in progress (check `progress` field)
- `completed`: Job finished successfully (check `result` field)
- `failed`: Job failed (check `error` field)

**M17 Phase Progress:**
When processing, the `progress` field includes:
- `phase`: Current pipeline phase (extracting, indexing, detecting_edges, propagating_scores)
- `phase_index`/`phases_total`: Phase position (e.g., 2/4)
- `phase_detail`: Sub-step detail within the phase
- `overall_percent`: Overall progress estimate (0-100)

The `poll_interval_ms` field suggests an appropriate polling interval.

## Path parameters

- `job_id` string, uuid, required

## Response `200`

Job status retrieved

- JobResponse: Full job status response.
  - `job_id` string, uuid, required
  - `pot_id` string, uuid, required
  - `status` 'pending' | 'processing' | 'completed' | 'failed', required: Job lifecycle states.
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required
  - `progress` JobProgress: Progress info for long-running jobs.
    - `current_step` string, required: Current processing step
    - `chunks_total` integer, nullable: Total chunks to process
    - `chunks_done` integer, nullable: Chunks processed so far
    - `facts_extracted` integer, nullable: Facts extracted so far
    - `phase` 'extracting' | 'indexing' | 'detecting_edges' | 'propagating_scores': Phases of the ingestion pipeline (M17).
    - `phase_index` integer, nullable: Phase index (1-based: 1=extracting, 2=indexing, ...)
    - `phases_total` integer, nullable: Total phases (always 4 for ingestion)
    - `phase_detail` string, nullable: Sub-step detail within current phase
    - `overall_percent` integer, nullable: Overall progress estimate 0-100
  - `result` union
    - JobResult: Result when job completes successfully (possibly partially).
      - `chunks_processed` integer, required: LLM chunks in the document; chunks_failed counts the ones that failed, including chunks skipped after a document-wide failure
      - `facts_created` integer, required
      - `fact_ids` string[]: IDs of created facts
      - `facts_duplicated` integer, required
      - `document_context` DocumentContext, required: Global context extracted from a document.
        - `title` string, required: Main topic or title of the document
        - `key_entities` string[], required: 5-10 key entities mentioned in document
        - `main_themes` string[], required: 3-5 main themes or topics discussed
        - `document_type` 'technical' | 'conceptual' | 'reference' | 'guide' | 'other', required: Document type classification
        - `language` string, nullable: ISO 639-1 language code of the document (e.g. 'es', 'en'). None if mixed-language or undetermined.
        - `scope_hint` 'own' | 'third_party' | 'mixed_context' | 'unknown', nullable: Document-level scope hint inferred during context generation. 'own' = describes the operating organization's own data/operations; 'third_party' = describes external entities (case studies, customer data); 'mixed_context' = contains both first-party and third-party content; 'unknown' = cannot determine. None = scope inference not performed.
      - `processing_time_ms` integer, required
      - `phase_timings_ms` object: Milliseconds per phase, in the order they ran: context, tables, chunking, extraction, building_facts, pii, dedup (near-duplicate judge included), persisting, indexing (embeddings and vector store), edges (contradiction detection, its verification and the score recompute). Empty on jobs from before v0.7.84.0.
      - `extraction_audit` unknown
      - `detail` string, nullable: Why a completed job stored no fact, in a sentence for the integrator; null when it stored some, or when chunks failed (see chunks_failed). Since v0.7.103.0.
      - `detail_code` 'all_filtered' | 'no_facts_found' | 'all_withheld' | 'all_duplicates', nullable: detail as a code: all_filtered (every statement the model found failed the quality filter, see extraction_audit.filtered_by_reason), no_facts_found, all_withheld (the PII layer kept them out), all_duplicates (all already in the POT). Extensible: a client should treat an unknown code like null and show detail
      - `pii` PiiRunSummary: What the PII layer did across one extraction run (job or preview).
        - `mode` 'off' | 'anonymize' | 'block', required
        - `provider` string, required
        - `provider_version` string, nullable: Detector configuration that ran (guardrail id:version, pattern-set tag).
        - `entitlement` 'premium' | 'floor', required
        - `facts_scanned` integer
        - `facts_anonymized` integer
        - `facts_blocked` integer
        - `by_type` object
        - `coverage` 'full' | 'partial' | 'none'
        - `language` string, nullable
        - `units` integer: Billable text units (1 unit = 1000 chars)
        - `free_units` integer
        - `chars` integer: Characters sent to the detector
        - `processing_ms` integer
      - `edges_created` integer: Constitution edges created
      - `contradictions_created` integer: Pairs of facts the new edges contradict (a pair, not an edge: a two-way contradiction is two edges). A pair a replacement in force covers counts as a replacement; a pending replacement counts here. 0 on jobs before v0.7.85.0.
      - `supersedes_created` integer: Pairs of facts a new approved replacement (supersedes, auto-approved or validated) covers. Approved, not necessarily applied: a repeal the level guard holds back still counts here (see the fact's validity).
      - `clash_sample` ClashPair[]: Up to 10 of the new contradictions and replacements, one per pair of facts, replacements first: which new fact clashes with which other one.
        - `new_fact_id` string, required
        - `other_fact_id` string, required
        - `relation` 'contradicts' | 'supersedes', required
        - `new_fact_role` 'replaces' | 'replaced' | 'contradicts'
      - `scores_updated` integer: Facts with updated POT Scores
      - `chunks_failed` integer: Chunks whose LLM extraction failed; facts from the other chunks were kept
      - `errors` ChunkError[]: One entry per failed chunk (first 25 at most)
        - `chunk_index` integer, required: 0-based chunk position
        - `code` string, required: Error code (LLM_TIMEOUT, LLM_RATE_LIMIT, ...)
        - `message` string, required: Human-readable error message
        - `retryable` boolean: Whether re-extracting the document is likely to succeed
      - `facts_indexed` integer, nullable: Facts whose vector reached the vector store. Below facts_created when indexing failed or rejected vectors; null when the phase did not run (no vector store wired) or on records older than v0.7.4.0.
      - `indexing_error` JobError: Error info when job fails, or (on ``JobResult.indexing_error``) when one phase of a job that otherwise completed did.
        - `code` string, required: Error code (LLM_RATE_LIMIT, LLM_TIMEOUT, LLM_NOT_CONFIGURED, ...); see the error reference at docs.scipot.ai/api-reference/errors
        - `message` string, required: Human-readable error message
        - `step` string, nullable: Step where failure occurred
        - `retryable` boolean: Whether job can be retried
      - `usage` JobUsage: LLM tokens one ingestion job consumed (v0.7.32.0, R10). The same numbers the job's usage events carry (``operation`` ``ingestion_fact_extraction`` and ``edge_detection``, both attributed to this ``job_id``), which are what the monthly token quota counts. It leaves out embedding calls (not metered) and the PII layer, whose work is metered in text units and reported on ``JobResult.pii``.
        - `extraction` TokenUsage: LLM tokens of one phase of a job, exactly as its usage events billed them.
          - `llm_calls` integer: LLM responses billed
          - `prompt_tokens` integer: Input tokens
          - `completion_tokens` integer: Output tokens
          - `cached_prompt_tokens` integer: Share of prompt_tokens served from the provider's prompt cache
          - `cache_write_tokens` integer: Share of prompt_tokens written to the provider's prompt cache
          - `total_tokens` integer, required: prompt_tokens + completion_tokens (the cache split is inside prompt_tokens)
        - `edge_detection` TokenUsage: LLM tokens of one phase of a job, exactly as its usage events billed them.
          - `llm_calls` integer: LLM responses billed
          - `prompt_tokens` integer: Input tokens
          - `completion_tokens` integer: Output tokens
          - `cached_prompt_tokens` integer: Share of prompt_tokens served from the provider's prompt cache
          - `cache_write_tokens` integer: Share of prompt_tokens written to the provider's prompt cache
          - `total_tokens` integer, required: prompt_tokens + completion_tokens (the cache split is inside prompt_tokens)
        - `total_tokens` integer, required: extraction.total_tokens + edge_detection.total_tokens
      - `partial` boolean, required: True when chunks_failed > 0 or indexing_error is set: the document was only partially extracted or its facts are not all searchable. Re-extract it to fill the gaps (deduplication keeps existing facts).
    - RepropagationJobResult: Result of a ``repropagation`` job: the POT Scores recomputed after a source type's weight or an axiom changed (v0.7.45.0). The counts the PATCH answered in v0.7.44.0 live here now.
      - `trigger` string, required: What queued it: `source_weight`, `axiom`, or `document_authority` (a document's source type changed, v0.7.75.0).
      - `source_type` string, nullable: The source type whose weight changed; for `document_authority`, the type the document's facts moved to.
      - `document_id` string, nullable: `document_authority`: the document whose facts moved (v0.7.75.0).
      - `previous_weight` number, nullable: The weight it had before.
      - `weight` number, nullable: The weight it has now.
      - `facts_recomputed` integer: Facts whose starting score moved with the weight.
      - `facts_saved` integer: Facts saved after propagating again.
      - `skipped_curated` integer: Left as a person curated them.
      - `skipped_endorsed` integer: Left as a person vouched for them.
      - `skipped_unknown_start` integer: `document_authority`: facts left as they are because the score they started with is not known (extracted under a profile version the change did not read).
      - `processing_time_ms` integer, required
  - `error` JobError: Error info when job fails, or (on ``JobResult.indexing_error``) when one phase of a job that otherwise completed did.
    - `code` string, required: Error code (LLM_RATE_LIMIT, LLM_TIMEOUT, LLM_NOT_CONFIGURED, ...); see the error reference at docs.scipot.ai/api-reference/errors
    - `message` string, required: Human-readable error message
    - `step` string, nullable: Step where failure occurred
    - `retryable` boolean: Whether job can be retried
  - `poll_interval_ms` integer, nullable: Suggested polling interval in milliseconds

## Other responses

- `404`: Job not found
- `422`: Validation Error

## Changes

- **2026-10-24** `87bd973b9c0f`: 2 info
  - added the optional property `result/anyOf[subschema #1: JobResult]/detail` to the response with the `200` status
  - added the optional property `result/anyOf[subschema #1: JobResult]/detail_code` to the response with the `200` status
- **2026-10-17** `cffe0f63cacb`: 4 info
  - added the optional property `result/anyOf[subschema #1: JobResult]/clash_sample` to the response with the `200` status
  - added the optional property `result/anyOf[subschema #1: JobResult]/contradictions_created` to the response with the `200` status
  - added the optional property `result/anyOf[subschema #1: JobResult]/phase_timings_ms` to the response with the `200` status
  - added the optional property `result/anyOf[subschema #1: JobResult]/supersedes_created` to the response with the `200` status
- **2026-10-16** `b42345c0cf93`: 2 info
  - added the optional property `result/anyOf[subschema #2: RepropagationJobResult]/document_id` to the response with the `200` status
  - added the optional property `result/anyOf[subschema #2: RepropagationJobResult]/skipped_unknown_start` to the response with the `200` status
- **2026-10-12** `4ec43ee51b64`: 1 info
  - added `#/components/schemas/RepropagationJobResult` to the `result` response property `anyOf` list for the response status `200`
- **2026-10-03** `83313fd64b1c`: 1 info
  - added the optional property `result/anyOf[subschema #1: JobResult]/usage` to the response with the `200` status

[Operation history](https://skmtc.dev/scipot/apis/scipot-core-api/changes/jobs/:job_id/get.md)

---

[API](https://skmtc.dev/scipot/apis/scipot-core-api.md) - [All operations](https://skmtc.dev/scipot/apis/scipot-core-api/llms.txt) - [OpenAPI document](https://skmtc.dev/scipot/apis/scipot-core-api/revisions/7620af82156a?raw)
