---
title: "Get a single fact by ID"
method: GET
path: "/pots/{pot_id}/facts/{fact_id}"
tags: ["facts"]
---

# Get a single fact by ID

`GET /pots/{pot_id}/facts/{fact_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/pots/{pot_id}/facts/{fact_id}`
- Auth: none declared
- TypeScript: <https://skmtc.dev/scipot/apis/scipot-core-api/docs/pots/:pot_id/facts/:fact_id/get.ts> (a function with typed inputs; its response is checked against the schema)

Get a single fact by ID, including whether a newer fact has retired it.

Currency is one constitution read plus the edges that touch this fact.
A storage error on those edges is 503. A score a repeal of this fact still
needs is re-read consistently: a failed read is 503, and a fact that is
gone does not retire it. An unreadable constitution retires nothing.

## Path parameters

- `pot_id` string, uuid, required
- `fact_id` string, uuid, required

## Query parameters

- `as_of` string, date, nullable: Day to judge validity on (ISO 8601). Omitted = today (UTC).

## Response `200`

Fact retrieved successfully

- FactRead: A stored fact as ``GET /pots/{pot_id}/facts/{fact_id}`` returns it. ``superseded``, ``superseded_by`` and the currency fields are computed for that response on ``as_of``. They are not stored.
  - `restated_by` RestatedByRef[]: Facts that restate this one from another document (not independent sources: they add no support). Empty when none, or when the edges could not be read.
    - `fact_id` string, required: The restating fact (from_id --restates--> this fact)
    - `document_id` string, nullable: Its document; null when it has none
    - `source_type` string, nullable: Its POT source type (provenance.sources[0].authority); null = none
    - `document_date` string, date-time, nullable: Its document's own date; null when unknown (never the upload's)
    - `locator` string, nullable: Where in its document: the section path, or sheet!cell for XLSX
    - `partial` boolean: Since v0.7.105.0: it repeats only part of this fact. Together with the other facts split from the same passage of its document, it repeats all of it.
  - `restates` string, nullable: The fact this one restates (this fact --restates--> it): it repeats that fact's values and is not independent evidence. Null when it restates none.
  - `restates_all` string[]: Since v0.7.104.0: every fact this one restates (up to 20), when it repeats more than one (a summary of two facts of the same act). Ordered by the figures both facts give, then similarity, then the judge's confidence, then ascending id. Edges without those keys (written before v0.7.104.0, or created by hand) come after the rest, by confidence. `restates` is unchanged: the most confident one, which may not be the first here. Empty when it restates none.
  - `currency` 'current' | 'pending' | 'future' | 'not_current': current: in force on as_of. pending: in force, with a warning (a repeal of it waits for a curator or is blocked, or a conflict with a later value cannot be ordered by date). future: starts holding after as_of. not_current: a repeal in effect on as_of replaces it (its POT Score is unchanged).
  - `valid_until` string, date, nullable: Day the fact stops holding: the effective day of the repeal that replaces it, or of one scheduled after as_of. Null = open.
  - `superseded_at` string, date-time, nullable: When SciPot recorded the repeal that replaces it (transaction time).
  - `currency_reason` object, nullable: What decides the currency: the repeal ({edge_id, kind, basis}, with status pending or blocked when it does not apply yet), a tacit conflict ({edge_id: tacit:<contradicts id>, kind: tacit}), or the fact's valid_from.
  - `id` string, uuid, required: Unique identifier (UUID)
  - `pot_id` string, uuid, required: POT this fact belongs to
  - `workspace_id` string, uuid, nullable: Multi-tenant isolation. Defaults to DEV_WORKSPACE_ID if None.
  - `content` string, required: The actual claim or statement
  - `title` string, nullable: Short title (max 50 chars, hard limit 80) for graph node labels. Generated by LLM during extraction. None for legacy facts.
  - `content_hash` string, nullable: SHA-256 hash of content for deduplication
  - `pot_score` number, required: Certainty score (0.0-1.0, where 1.0 = CONSTITUTION)
  - `original_pot_score` number, nullable: Pre-propagation POT Score. None if propagation hasn't run.
  - `level` 'CONSTITUTION' | 'VERIFIED' | 'SUPPORTED' | 'INFERRED' | 'HYPOTHESIS' | 'SPECULATION', required: POT Index levels matching score ranges.
  - `embedding_model` string, nullable: Embedding model used, e.g. text-embedding-3-small
  - `provenance` Provenance, required: Provenance information for a fact.
    - `type` string, required: Type of provenance (extracted, manual, inferred, imported)
    - `sources` object[]: Where the fact came from. One entry today. Its typed keys: `contributor_id` (the registered contributor who brought the source in: the uploader of the document, the author of a contribution) and `episode_id` (the session it was written in); `authority` is the POT source type, `source_type` the file format. A contribution may carry `basis_quote`: the contributor's own words it is based on, after the PII layer; a citation that no score reads.
    - `derivation` object, nullable: Derivation info for inferred facts
    - `profile_id` string, uuid, nullable: Extraction profile applied (T4); null when none.
    - `profile_version` integer, nullable: Version of that profile at enqueue time; set iff profile_id is set.
  - `classification` Classification: Classification metadata for a fact.
    - `domain` string: Domain category
    - `subdomain` string, nullable: Subdomain category
    - `tags` string[]: Tags for search (max 20). Inherited from SourceMetadata.tags during ingestion.
    - `entity_mentions` string[]: Entities mentioned
  - `status` string: Processing status (processing, ready, error)
  - `validation_status` string: Validation status (pending, validated, disputed, rejected)
  - `created_at` string, date-time: When fact was created
  - `updated_at` string, date-time: When fact was last updated
  - `valid_from` string, date, nullable: First day the fact holds in the world (valid time, not when it was stored). Taken from the document's effective date, else its date; null = not known.
  - `valid_from_source` 'document_effective' | 'document_date' | 'contributor' | 'imported' | 'curator', nullable: Where valid_from came from: document_effective, document_date, contributor, imported or curator. Null when valid_from is null.
  - `document_id` string, uuid, nullable: Document UUID this fact was extracted from. None for constitution facts and inline ingestion.
  - `language` string, nullable: ISO 639-1 language code of the fact content (e.g. 'es', 'en'). Inherited from document language detection during extraction.
  - `location` DocumentLocation: Location metadata tracing a fact back to its source in the document. Populated during ingestion when document_index_enabled=True. Available fields depend on document format: - PDF: section_path, source_text - DOCX: section_path, source_text - PPTX: section_path, source_text - XLSX: sheet_name, row_number, cell_ref, source_text - MD/TXT: section_path, source_text Ingestion does not set page_number from PDF pages or PPTX slides: page tracing is off in every ingestion path since v0.5.7.1.
    - `page_number` integer, nullable: Page number (1-indexed): PDF page or PPTX slide. Ingestion does not set it from PDF or PPTX since v0.5.7.1 (page tracing is off).
    - `section_path` string, nullable: Heading breadcrumb, e.g. '## Resultados > ### Q3 2024'.
    - `source_text` string, nullable: Verbatim text excerpt from the document this fact was derived from.
    - `sheet_name` string, nullable: XLSX sheet (tab) name where the fact was found.
    - `row_number` integer, nullable: XLSX row number (1-indexed).
    - `cell_ref` string, nullable: XLSX cell reference, e.g. 'B7' or 'B7:D7'.
  - `scope_inferred` 'own' | 'third_party' | 'mixed_context' | 'unknown', nullable: Per-fact scope classification from scope-aware extraction. 'own' = describes the operating organization's data; 'third_party' = describes external entities (case studies, customers); 'mixed_context' = blends first- and third-party content; 'unknown' = LLM could not determine. None = legacy fact, extraction predates scope-aware prompt.
  - `scope_confidence` number, nullable: LLM-reported confidence (0.0-1.0) on the scope_inferred classification. ≥0.7 = trust; 0.4-0.7 = hint; <0.4 = manually verify. None when scope_inferred is None.
  - `scope_reason` string, nullable: Short LLM-generated explanation of the scope_inferred classification (why this scope, what signal the LLM used). Used by KB2B tooltip to explain confidence to admins. None when scope_inferred is None.
  - `context_attachment_ids_used` string[], nullable: Snapshot of context_attachment_ids in scope at extraction time. Empty list = extraction ran under M21+ with zero attachments. None = legacy fact (pre-M21) or non-extraction-pipeline fact.
  - `pii` FactPii: What the PII layer did to one fact. Counts and states only — no values.
    - `applied` boolean, required: True when at least one entity was masked
    - `mode` 'off' | 'anonymize' | 'block', required
    - `entities` object: Masked entities by type, e.g. {'NAME': 2, 'EMAIL': 1}
    - `coverage` 'full' | 'partial' | 'none'
    - `language` string, nullable
    - `unmasked_content` string, nullable: The fact before masking. Only on the extraction preview with include_unmasked=true; never persisted.
  - `version` integer: Version number (increments on update)
  - `flags` string[]: Special flags (needs_review, deprecated, etc.)
  - `notes` string, nullable: Internal notes
  - `warnings` FactWarning[]: Patterns detected on the fact for curators (e.g. a stated repeal).
    - `pattern` string, required: Pattern name, e.g. `repeal`
    - `message` string, required: Human-readable warning
    - `detail` string, nullable: What matched, e.g. the cited reference
    - `probability` number, nullable: Decisions API confidence; null when the filter alone decided
  - `edge_summary` EdgeSummary: Denormalized edge count summary stored on each fact. Enables KB2B to display edge counts per fact without extra API calls. Updated atomically when edges are created or deleted.
    - `total_in` integer: Total incoming edges
    - `total_out` integer: Total outgoing edges
    - `by_type` object: Edge counts broken down by type (e.g. supports, contradicts)
  - `superseded` boolean: A newer fact retires this one. Only an auto-approved or validated repeal counts; a pending or rejected one, and one the Supported floor or an active axiom blocks, does not.
  - `superseded_by` string[]: Ids of the facts that replace this one (from_id --supersedes--> this fact).

## Other responses

- `404`: POT or fact not found
- `422`: Validation Error
- `503`: The edges that touch this fact, or a repeal's score, could not be read

## Changes

- **2026-10-24** `7764b32b043b`: 2 info
  - added the optional property `restated_by/items/partial` to the response with the `200` status
  - added the optional property `restates_all` to the response with the `200` status
- **2026-10-24** `0fb6ed61ba72`: 2 info
  - added the optional property `restated_by` to the response with the `200` status
  - added the optional property `restates` to the response with the `200` status
- **2026-10-14** `34be7df24641`: 1 warning, 6 info
  - removed the optional property `decay_rate` from the response with the `200` status
  - added the new optional `query` request parameter `as_of`
  - added the optional property `currency` to the response with the `200` status
  - added the optional property `currency_reason` to the response with the `200` status
  - …3 more
- **2026-10-12** `4ec43ee51b64`: 3 info
  - added the non-success response with the status `503`
  - added the optional property `superseded` to the response with the `200` status
  - added the optional property `superseded_by` to the response with the `200` status
- **2026-09-14** `a3feb62260cf`: 1 info
  - added the optional property `pii` to the response with the `200` status

[Operation history](https://skmtc.dev/scipot/apis/scipot-core-api/changes/pots/:pot_id/facts/:fact_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)
