This document covers all HTTP routes exposed by the sfl-engine API. For the underlying database schema, see Data Model. For system-level diagrams of how these routes fit into the architecture, see Architecture Diagrams.
Note: All
curlexamples assumelocalhost:3001(the default for local development). Adjust host and port for your environment — the engine supportsHOSTandPORTenv vars.
Wire Format
The API uses SFL::Core::Wire.dump to serialize types across the process boundary. Times are converted to ISO8601 strings.
AnnotatedClause
{
"id": "clause-uuid",
"text": "The engine compiles the text.",
"syntactic": {
"id": "syntactic-uuid",
"text": "The engine compiles the text.",
"tokens": [...],
"groups": [...],
"root_index": 2,
"sentence_index": 0,
"document_id": "doc-uuid",
"parent_clause_id": null,
"readability": null
},
"ideational": {
"clause_id": "clause-uuid",
"process_type": "material",
"participants": [...],
"circumstances": [...],
"raw_transitivity": {...}
},
"interpersonal": {
"clause_id": "clause-uuid",
"mood": "declarative",
"modality_weight": 0.8,
"tenor": 0.5,
"speaker_attitude": "objective",
"reasoning": "...",
"annotation_source": "llm",
"reasoning_trace": {
"premises": [{ "label": "...", "value": "..." }],
"inference_rule": "SFL mood + modality rule",
"conclusion": { "mood": "declarative", "modality_weight": 0.8 },
"confidence": 0.92,
"derivation_hash": "sha256-hex-string",
"generated_at": "2023-01-01T00:00:00Z"
},
"raw_classification": "declarative",
"classification_status": "canonical",
"untrusted": false
},
"textual": null,
"document_id": "doc-uuid",
"compiled_at": "2023-01-01T00:00:00Z",
"untrusted": false
}
RetrievalResult
{
"clause_id": "clause-uuid",
"text": "The engine compiles the text.",
"document_id": "doc-uuid",
"rrf_score": 0.95,
"semantic_rank": 1,
"keyword_rank": 2,
"mood": "indicative",
"tenor": 0.5,
"process_type": "material",
"modality_weight": 0.8,
"annotation_source": "llm",
"untrusted": false,
"parent_clause_id": null
}
Routes
Health
GET /health
Purpose: Health check endpoint to verify API availability.
Request: None
Response (200):
{
"status": "ok"
}
Example:
curl -X GET http://localhost:3001/health
Compilation
POST /pipeline/compile
Purpose: Compiles raw text into annotated clauses using the two-pass pipeline.
Request:
| Parameter | Type | Required | Default | Description |
|———–|——|———-|———|————-|
| text | string | Yes | - | The raw text to compile |
| document_id | string | No | api-<uuid> | Document identifier |
| store | boolean | No | false | Whether to persist clauses to Postgres |
| embed | boolean | No | false | Whether to generate vector embeddings |
Response (200): Array of AnnotatedClause (Wire format)
Errors:
| Status | Condition |
|——–|———–|
| 400 | text is missing or empty |
Example:
curl -X POST http://localhost:3001/pipeline/compile \
-H "Content-Type: application/json" \
-d '{"text": "Compile this text.", "store": true}'
Retrieval
POST /retrieve
Purpose: Retrieves clauses using Hybrid RRF (vector + keyword) and scalar filters.
Request:
| Parameter | Type | Required | Default | Description |
|———–|——|———-|———|————-|
| query | string | Yes | - | The search query |
| limit | integer | No | 10 | Maximum results to return |
| filters | object | No | {} | RetrievalFilters (see below) |
RetrievalFilters fields:
-
mood(enum: declarative, interrogative, imperative, exclamative, indicative, minor, fragment) -
process_type(enum: material, mental, relational, behavioral, verbal, existential) -
source_type(string) -
min_modality(float 0.0 - 1.0) -
max_modality(float 0.0 - 1.0) -
min_tenor(float 0.0 - 1.0) -
max_tenor(float 0.0 - 1.0)
Response (200):
{
"query": "search term",
"results": [ /* Array of RetrievalResult (Wire format) */ ],
"count": 1
}
Errors:
| Status | Condition |
|——–|———–|
| 400 | query is missing or empty |
Example:
curl -X POST http://localhost:3001/retrieve \
-H "Content-Type: application/json" \
-d '{"query": "database", "filters": {"mood": "indicative"}}'
Synthesis
POST /synthesize
Purpose: Performs RAG (retrieval-augmented generation) by synthesizing an answer from retrieved clauses.
Request:
| Parameter | Type | Required | Default | Description |
|———–|——|———-|———|————-|
| query | string | Yes | - | The query to answer |
| filters | object | No | {} | Same filter keys as /retrieve (RetrievalFilters), passed as a symbolized hash to the synthesizer |
| limit | integer | No | 10 | Max clauses to retrieve for context |
| include_fallback | boolean | No | false | Fall back to general LLM knowledge if context misses |
| expand_ancestors | boolean | No | false | Expand retrieved child clauses to their parents |
Response (200):
{
"query": "What is the database?",
"answer": "The database is PostgreSQL.",
"cited_clause_ids": ["clause-uuid"],
"clauses": [ /* Array of RetrievalResult hashes (not AnnotatedClause) */ ],
"retrieved_count": 1,
"confidence": 0.95
}
Errors:
| Status | Condition |
|——–|———–|
| 400 | query is missing or empty |
Example:
curl -X POST http://localhost:3001/synthesize \
-H "Content-Type: application/json" \
-d '{"query": "How does the pipeline work?"}'
Clause Management
GET /clauses
Purpose: Lists and filters persisted clauses.
Request:
| Parameter | Type | Required | Default | Description |
|———–|——|———-|———|————-|
| document_id | string | No | - | Filter by document ID |
| annotation_source | string | No | - | Filter by source (e.g., llm, spacy) |
| limit | integer | No | 50 | Pagination limit |
| offset | integer | No | 0 | Pagination offset |
| source_type | string | No | - | Filter by source type |
| mood | string | No | - | Filter by mood |
| process_type| string | No | - | Filter by process type |
| min_modality| float | No | - | Filter minimum modality |
| max_modality| float | No | - | Filter maximum modality |
| min_tenor | float | No | - | Filter minimum tenor |
| max_tenor | float | No | - | Filter maximum tenor |
Response (200):
{
"clauses": [ /* Array of AnnotatedClause (Wire format) */ ],
"total": 100,
"limit": 50,
"offset": 0
}
Example:
curl -X GET "http://localhost:3001/clauses?document_id=doc-uuid&limit=10"
GET /clauses/review-queue
Purpose: Gets the paginated annotation review queue (audit log of accepted/rejected annotations).
Request:
| Parameter | Type | Required | Default | Description |
|———–|——|———-|———|————-|
| limit | integer | No | 50 | Pagination limit |
| offset | integer | No | 0 | Pagination offset |
Response (200):
{
"clauses": [ /* Array of clause review rows */ ],
"total": 5,
"limit": 50,
"offset": 0
}
Example:
curl -X GET "http://localhost:3001/clauses/review-queue"
POST /clauses/:id/review
Purpose: Submit a review decision for a specific annotated clause’s annotation quality.
Request:
| Parameter | Type | Required | Default | Description |
|———–|——|———-|———|————-|
| decision | string | Yes | - | enum: accepted, rejected, re_annotated |
| reviewer | string | No | - | Identifier of the reviewer |
| notes | string | No | - | Optional context for the decision |
Response (200): Review record (Wire format)
Errors:
| Status | Condition |
|——–|———–|
| 400 | decision is invalid |
| 404 | Clause not found |
Example:
curl -X POST http://localhost:3001/clauses/clause-uuid/review \
-H "Content-Type: application/json" \
-d '{"decision": "accepted", "reviewer": "admin"}'
Content Review
GET /review-queue
Purpose: Gets pending content reviews (quarantined generated text pending human approval).
Request:
| Parameter | Type | Required | Default | Description |
|———–|——|———-|———|————-|
| modality | string | No | - | Filter by modality type |
| limit | integer | No | 50 | Pagination limit |
| offset | integer | No | 0 | Pagination offset |
Response (200):
{
"items": [ /* Array of review queue rows */ ],
"total": 12,
"limit": 50,
"offset": 0
}
Example:
curl -X GET "http://localhost:3001/review-queue?limit=10"
POST /review-queue/:id/decide
Purpose: Approves, rejects, or edits a pending content review entry.
Request:
| Parameter | Type | Required | Default | Description |
|———–|——|———-|———|————-|
| decision | string | Yes | - | enum: approve, reject, edit |
| edited_text | string | Cond. | - | Required if decision is edit |
| reviewer | string | No | - | Identifier of the reviewer |
Response (200):
{
"review": { /* Updated review queue row */ },
"clauses": [ /* Output from pipeline compile if decision was edit */ ]
}
Errors:
| Status | Condition |
|——–|———–|
| 400 | decision is invalid, or edit decision lacks edited_text |
| 404 | Review item not found |
Example:
curl -X POST http://localhost:3001/review-queue/item-uuid/decide \
-H "Content-Type: application/json" \
-d '{"decision": "approve"}'
Graph
GET /graph/nodes
Purpose: Fetches clause graph nodes (clauses in the knowledge graph).
Request:
| Parameter | Type | Required | Default | Description |
|———–|——|———-|———|————-|
| document_id | string | No | - | Filter by document ID |
Response (200): Array of Nodes (Wire format)
Example:
curl -X GET "http://localhost:3001/graph/nodes?document_id=doc-uuid"
GET /graph/edges
Purpose: Fetches structural (parent/child) and semantic neighbor edges for clauses.
Request:
| Parameter | Type | Required | Default | Description |
|———–|——|———-|———|————-|
| document_id | string | No | - | Filter by document ID |
Response (200): Array of Edges (Wire format)
Example:
curl -X GET "http://localhost:3001/graph/edges?document_id=doc-uuid"