Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
description: 'The API for Relay by Flume Health.
For more information about how Flume can power your health plan, please [contact us](mailto:sales@flumehealth.com).
[Redoc](/api/docs/) | [Swagger - Try It](/api/swagger/)
'
title: Flume Console Context Knowledge API
contact: {}
version: '1.0'
x-logo:
altText: Flume Health
url: https://public-static.flume.health/front/logo-margin-512.png
servers:
- url: https://console.flumehealth.com/
- url: http://console.flumehealth.com/
tags:
- name: Context Knowledge
paths:
/api/v1/context/knowledge:
get:
description: 'Lists curated knowledge for the authenticated account, ordered by fqn and filterable by scope, kind, status, and fqn-prefix. The agent reads knowledge via graph-search/graph-query (K1); this is the CURATOR/manage surface. A read, so — like get — it is not gated by the knowledge_write_manage flag: a write-off rollback still serves it. One curator-scoped rule applies: a NON-curator never sees status=proposed rows (unapproved content is what the review-queue and proposal-list gates protect, and an inventory must not route around them); a non-curator filtering for proposed gets an empty list, not an error. The result is BOUNDED (limit defaults to 200, ceiling 1000) and the envelope carries no cursor, so an account past the ceiling is truncated — the truncation is logged server-side, and wire pagination is the fix rather than a larger bound.'
tags:
- Context Knowledge
summary: List knowledge
operationId: listKnowledge
parameters:
- description: Filter by scope type (flume_core, account, project, user, session)
name: scope
in: query
schema:
type: string
- description: Filter by kind. Matched exactly and NOT validated against a closed set — kind is open-with-declaration (G8), so an account's declared kind:ontology values are legal filter values.
name: kind
in: query
schema:
type: string
- description: Filter by lifecycle status (proposed, active, superseded, archived, rejected, tombstoned)
name: status
in: query
schema:
type: string
- description: Filter by fqn prefix (opaque, store-minted knowledge/{id}; C16)
name: fqn_prefix
in: query
schema:
type: string
- description: Max entities to return (default 200, ceiling 1000)
name: limit
in: query
schema:
type: integer
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/knowledge.KnowledgeListResponse'
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'500':
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
security:
- BearerAuth: []
post:
description: 'Creates a knowledge entity. account_id comes from request context, fqn is store-minted (C16), and curator_role from auth — none may be supplied in the body. TWO paths share this route by a body-value dispatch on status (AIP: not a bespoke verb): the default status=active is the CURATOR-gated create, while status=proposed is the save-this proposal (FL-29879) — NOT curator-gated, any authenticated author may propose. A proposal lands status=proposed plus one review_items row and is never retrieval-eligible until a curator approves it via the row-scoped review-items/{review_item_id}:approve. The propose-only evidence fields (proposed_target, sensitivity, verification_interval) are accepted ONLY with status=proposed; the source evidence link rides in source_refs, which already documents exactly that purpose.'
tags:
- Context Knowledge
summary: Create a knowledge entity
operationId: createKnowledge
responses:
'201':
description: Created
content:
application/json:
schema:
$ref: '#/components/schemas/knowledgestore.KnowledgeEntity'
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'503':
description: Service Unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
security:
- BearerAuth: []
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/knowledgemanager.CreateKnowledgeInput'
description: Knowledge to create
required: true
/api/v1/context/knowledge/artifacts:
post:
description: Persists a content-addressed :Artifact (code/document/image). Identity is the content_hash (derived from the payload; a supplied hash is verified). Byte-identical content dedups to one row (FR-33). Raw PHI bytes are never injected — only the sanitized extracted_text is embedded/injected. A binary artifact's `bytes` are retained (FL-30227), stored against the content_hash outside the graph and served only through GET /api/v1/context/knowledge/artifacts/{content_hash}/content, which is role- and sensitivity-gated. Identity, size, media_type, extracted_text, and sensitivity/scope persist on the artifact itself.
tags:
- Context Knowledge
summary: Create a content-addressed artifact
operationId: createKnowledgeArtifact
responses:
'201':
description: Created
content:
application/json:
schema:
$ref: '#/components/schemas/knowledge.CreateArtifactResponse'
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'503':
description: Service Unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
security:
- BearerAuth: []
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/knowledge.CreateArtifactRequest'
description: Artifact to create
required: true
/api/v1/context/knowledge/artifacts/{content_hash}/content:
get:
description: Streams the raw bytes of a stored binary artifact, addressed by content_hash. Requires Editor or above; a phi_bearing or unclassified artifact additionally requires a curator (SystemAdmin). Returns 404 when no payload is stored — including for artifacts created before payload persistence existed, whose bytes were discarded and cannot be recovered except by re-creating the artifact from the same content. Raw bytes are never injected or embedded; only the sanitized extracted_text is.
tags:
- Context Knowledge
summary: Download a binary artifact's payload
operationId: getKnowledgeArtifactContent
parameters:
- description: Artifact content hash (sha256-…)
name: content_hash
in: path
required: true
schema:
type: string
responses:
'200':
description: The artifact payload
content:
application/octet-stream:
schema:
type: string
format: binary
'400':
description: Bad Request
content:
application/octet-stream:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'401':
description: Unauthorized
content:
application/octet-stream:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'403':
description: Forbidden
content:
application/octet-stream:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'404':
description: Not Found
content:
application/octet-stream:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'503':
description: Service Unavailable
content:
application/octet-stream:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
security:
- BearerAuth: []
/api/v1/context/knowledge/graph:
get:
description: 'Returns the read-only knowledge graph (nodes + edges) for the graph view (FR-25). Read-only: mutation happens on the manage surface. Not yet implemented (501).'
tags:
- Context Knowledge
summary: Get the read-only knowledge graph
operationId: getKnowledgeGraph
parameters:
- description: Filter by scope type
name: scope
in: query
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/knowledge.KnowledgeGraphResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'501':
description: Not Implemented
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
security:
- BearerAuth: []
/api/v1/context/knowledge/prefix:
get:
description: 'Returns the near-static {ontology} schema-card and the debounced/versioned {index} block with their current versions, for the gateway proxy flow to attach to the cached system-prefix (FR-34). These blocks are read-side only: they do NOT pass the per-turn relevance gate or count against the per-turn budget. Gated by knowledge_read_inject; with the flag off the endpoint returns 503 (read-off rollback).'
tags:
- Context Knowledge
summary: Get the stable knowledge prefix blocks
operationId: getKnowledgePrefix
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/knowledge.KnowledgePrefixResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'500':
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'503':
description: Service Unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
security:
- BearerAuth: []
/api/v1/context/knowledge/proposals:
get:
description: Lists status=proposed knowledge items awaiting curator review (FR-7, FR-27). Account-isolated and CURATOR-GATED (a non-curator gets 403, even though the route-level policy admits editors) — the list carries unapproved proposal content. Each entry is hydrated from the LIVE :Knowledge node, so a curator's edits before approval are what the queue shows; the reason comes from the review row. A read, so — like get — it is not gated by the knowledge_write_manage flag.
tags:
- Context Knowledge
summary: List knowledge proposals
operationId: listKnowledgeProposals
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/knowledge.ProposalListResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'500':
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
security:
- BearerAuth: []
/api/v1/context/knowledge/review-items:
get:
description: 'Returns the account''s curator review queue (proposed_knowledge, bulk_seed_ambiguity and feedback_flag rows) for the review-queue UI (Story 5.2, pulled into v1), optionally filtered by status. Account-isolated and CURATOR-GATED (a non-curator gets 403, even though the route-level policy admits editors). A read, so — like get — it is not gated by the knowledge_write_manage flag: a write-off rollback still serves the queue.'
tags:
- Context Knowledge
summary: Get the curator review queue
operationId: getKnowledgeReviewQueue
parameters:
- description: Filter by review status (open, accepted, rejected, dismissed)
name: status
in: query
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/knowledge.ReviewQueueResponse'
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'500':
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
security:
- BearerAuth: []
/api/v1/context/knowledge/review-items/{review_item_id}/promotion-preflight:
get:
description: 'Returns everything the propose->active promotion gate needs, in one read (FL-29879''s 2026-08-05 AC): the proposal''s §3.4 evidence, the FR-27 field NAMES it is missing, and a FRESH artifact-revision verdict. Both gate results are server-authoritative — missing_evidence because several FR-27 fields are not on ProposalPayload at all, and artifact_freshness because the revision flip skips proposed referrers, so the proposal''s own needs_review badge reads clean on exactly the case this catches. It writes nothing and is safe (and intended) to re-run on every promotion-dialog open: a verdict computed at mount would answer with the graph as it was at mount, and the failure this exists for is a revision landing while the proposal waited. CURATOR-gated. A row that is not a proposed_knowledge item has no promotion to preflight (400).'
tags:
- Context Knowledge
summary: Preflight a proposal's promotion
operationId: getKnowledgePromotionPreflight
parameters:
- description: Review item id (a bare UUIDv7 — review rows carry no collection prefix)
name: review_item_id
in: path
required: true
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/knowledge.PromotionPreflightResponse'
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'404':
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'409':
description: the proposal was promoted or its row disposed in another tab
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'500':
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
security:
- BearerAuth: []
/api/v1/context/knowledge/review-items/{review_item_id}:approve:
post:
description: 'Disposes a review row as accepted. On a proposed_knowledge row this is ONE call that does BOTH halves of the promotion: it promotes the entity proposed->active (emitting the `approved` event) and disposes the row open->accepted. They are one call because the two writes span different datasets with no shared transaction, so the sequencing has to be the server''s — a client issuing two calls would own a half-applied promotion it cannot repair. On a bulk_seed_ambiguity or feedback_flag row there is no entity to promote, so it is queue bookkeeping only. Promotion enforces the FR-27 evidence floor AND the artifact-freshness re-check, refusing with 400 invalid_input and a `field` naming what blocked it (`artifacts` for a revised or unconfirmable artifact, otherwise the missing evidence field). A refused promotion writes NOTHING. CURATOR-gated.'
tags:
- Context Knowledge
summary: Approve a review item
operationId: approveKnowledgeReviewItem
parameters:
- description: Review item id
name: review_item_id
in: path
required: true
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
additionalProperties:
type: string
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'404':
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'409':
description: Conflict
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'503':
description: Service Unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
security:
- BearerAuth: []
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/knowledge.ApproveReviewItemRequest'
description: Optional approver overrides (recall_policy, verification_interval). The queue UI approves with no body, in which case the proposal's own values stand.
/api/v1/context/knowledge/review-items/{review_item_id}:dismiss:
post:
description: 'Disposes a review row as dismissed — the curator judged it not actionable. PURE queue bookkeeping on every item type: no knowledge effect and no knowledge_audit_log event, because a queue transition is not itself a :Knowledge state change (§1.5 keeps the two logs distinct). This is the feedback_flag disposition; a triage prompt is not a proposal, so it is never "rejected". CURATOR-gated.'
tags:
- Context Knowledge
summary: Dismiss a review item
operationId: dismissKnowledgeReviewItem
parameters:
- description: Review item id
name: review_item_id
in: path
required: true
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
additionalProperties:
type: string
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'404':
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'503':
description: Service Unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
security:
- BearerAuth: []
/api/v1/context/knowledge/review-items/{review_item_id}:merge:
post:
description: 'Folds a proposed_knowledge row''s content into an EXISTING entity and disposes the row as accepted. There is deliberately no `merged` audit event — the sixteen-type set is closed, and a merge decomposes into exactly two recorded effects: an `edited` event on the target and an `approved` event on the review item. Only the target is client-supplied; the FIELDS folded are derived server-side from the proposal (from the LIVE node, so a curator''s pre-merge edits are what lands), because letting a client name them would make merge a general edit wearing a proposal''s disposition. Only a proposed_knowledge row can be merged. CURATOR-gated.'
tags:
- Context Knowledge
summary: Merge a proposal into an existing entity
operationId: mergeKnowledgeReviewItem
parameters:
- description: Review item id
name: review_item_id
in: path
required: true
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
additionalProperties:
type: string
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'404':
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'409':
description: Conflict
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'503':
description: Service Unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
security:
- BearerAuth: []
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/knowledge.MergeReviewItemRequest'
description: Merge target
required: true
/api/v1/context/knowledge/review-items/{review_item_id}:reject:
post:
description: Disposes a review row as rejected. On a proposed_knowledge row it also terminates the entity (proposed->rejected) and emits a `rejected` event carrying the reason when one is supplied; the body is optional, because a curator dispositioning without typing a reason sends none. Rejecting a knowledge entity that is not a proposal is a 409 — `rejected` is a proposal-lifecycle terminus, not a general retraction (that is DELETE/tombstone). CURATOR-gated.
tags:
- Context Knowledge
summary: Reject a review item
operationId: rejectKnowledgeReviewItem
parameters:
- description: Review item id
name: review_item_id
in: path
required: true
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
additionalProperties:
type: string
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'404':
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'409':
description: Conflict
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'503':
description: Service Unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
security:
- BearerAuth: []
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/knowledge.RejectReviewItemRequest'
description: Optional rejection reason
/api/v1/context/knowledge/turns/{message_id}:
get:
description: 'Returns the injected-knowledge panel + RecallTrace payload for a conversation turn (FR-24). A zero-injection turn returns gate_decision=none with no recall_trace. SOURCE AND ITS LIMITS: served from an in-process retention ring on the injection-audit writer, NOT from the durable injection_audit table (whose context-db receiver does not exist yet). It is therefore SINGLE-POD (the API runs several replicas; only the pod that served the turn holds the record), RESTART-LOSSY, and BOUNDED (old turns age out). A turn this pod did not serve, or that has aged out, returns the SAME zero-injection payload as a turn that genuinely injected nothing — the two are not distinguishable, and this endpoint never 404s or 500s for a missing turn. Treat it as a demo/debug surface; the durable trail is the audit table. ADDRESSING: the gateway mints a per-turn message id and returns it as the X-Flume-Message-Id response header on the LLM proxy call that served the turn (FL-30412) — read it there and address this route with it. A conversation id is also accepted, for clients that do not read that header yet, and resolves to that conversation''s MOST RECENT retained turn — correct for a dock rendering the live answer, wrong for one pinned to an older answer. PER-ITEM FIDELITY: title, kind and scope are re-read from the entity at request time, so they reflect the entity NOW rather than at turn time; badge.freshness, conflict and phi are computed during retrieval and are NOT carried by the audit record, so they are absent/false here rather than recomputed from a second, divergable opinion.'
tags:
- Context Knowledge
summary: Get injected knowledge for a turn
operationId: getTurnKnowledge
parameters:
- description: Message id segment of the turn — the opaque id only, not a slash-bearing resource name (chi path params cannot contain a slash). Take it from the X-Flume-Message-Id response header of the LLM proxy call that served the turn. A conversation id is also accepted and resolves to that conversation's most recent retained turn.
name: message_id
in: path
required: true
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/knowledge.TurnKnowledgePayload'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
security:
- BearerAuth: []
/api/v1/context/knowledge/{id}:
get:
description: 'Returns a single knowledge entity by its opaque fqn (knowledge/{id}). This curator read is intentionally NOT gated by the knowledge_write_manage flag: per the flag''s design, the write/manage surface is dark-launched and rolled back independently of reads (see writeEnabled), so a write-off rollback still serves reads of already-curated entities. The flag gates mutations only, not the whole surface.'
tags:
- Context Knowledge
summary: Get a knowledge entity
operationId: getKnowledge
parameters:
- description: Knowledge id (opaque; the full fqn is knowledge/{id}, C16)
name: id
in: path
required: true
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/knowledgestore.KnowledgeEntity'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
'404':
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/responses.ErrorResponse'
security:
- BearerAuth: []
delete:
description: Soft-deletes a knowledge entity — maps to status=tombstoned + body redaction (audited), never a hard row delete.
tags:
- Context Knowledge
summa
# --- truncated at 32 KB (91 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/flume-health/refs/heads/main/openapi/flume-health-context-knowledge-api-openapi.yml