Skip to content

Read an RDF record

View Markdown

GET /v1/graph/entity?version=records/1 returns one record from the same RDF snapshot used by SPARQL. It accepts a caller’s full IRI, an existing native entity id, or a stable key bound by explicitly activated schema. Omitting version preserves the existing native entity response. The new version is an additive read interface; JSON record writes are a later unification stage.

Release status: this reader and the SDK retrieve helpers are unreleased. Hosted availability requires the matching server rollout and SDK publication. The helpers refuse a legacy or incomplete successful response with LbbCapabilityError, so an older server cannot silently return the wrong shape.

For an RDF subject already stored in the graph:

Terminal window
curl --get "$LBB_URL/v1/graph/entity" \
-H "Authorization: Bearer $LBB_API_KEY" \
--data-urlencode 'graph=main' \
--data-urlencode 'version=records/1' \
--data-urlencode 'iri=https://example.org/people/alice' \
--data-urlencode 'consistency=strong'

TypeScript and Python use the same entity resource:

const record = await client.entities.retrieve({
iri: "https://example.org/people/alice",
consistency: "strong",
});
record = client.entities.retrieve(
iri="https://example.org/people/alice", consistency="strong"
)
typed = client.entities.retrieve_model(iri="https://example.org/people/alice")
# AsyncLbbClient supports the same methods with await.

MCP extends lbb_inspect, with no new tool:

{"action":"entity","iri":"https://example.org/people/alice","consistency":"strong"}

For native ids, use id in HTTP/SDK, or entity_id with version: "records/1" in MCP. For a schema-bound key, use type and key (entity_type and key in MCP). Supply exactly one selector. A display name is not a records/1 selector; the existing entities.detail remains available.

The result has object: "record", version: "records/1", authoritative id, snapshot, schema_revision, schema_binding, types, properties, outgoing, incoming, assertions, and complete: true. native_entity_id is present only when the subject has an actual native entity id. No synthetic id is assigned to a custom IRI. No creation time is invented for RDF that has none.

Each statement has subject, predicate and object. References use {"@id":"https://example.org/acme"}; a string with the same spelling uses {"@value":"https://example.org/acme"}. Exact numeric values use a lexical string and datatype, for example {"@value":"9007199254740993","@type":"http://www.w3.org/2001/XMLSchema#integer"}. Language literals retain @language. Unknown predicates and datatype IRIs remain visible.

This preserves terms observed in the selected RDF view. RDF 1.2 text direction is not yet qualified for durable storage: the existing dictionary codec omits it, and a read cannot recover direction already lost during ingestion. The JSON envelope can represent direction in memory; that is not an end-to-end ingest guarantee. The unification plan tracks the required codec transition.

Properties contain literal and quoted-term objects; outgoing contains IRI and blank-node objects, including types. Together they preserve all direct statements about the subject. Incoming statements point to the subject. Linked evidence resources remain references; this read does not recursively expand them.

Assertions retain their own identities and all statement-node metadata. described_triple_present reports whether a uniquely described relationship is present in this snapshot; it does not attribute support to that source. Two contested claims remain separate even when the direct relationship is absent. Reification alone does not assert the relationship.

Use consistency=strong for read-after-write. Pin a retained commit with as_of_commit_seq (TypeScript: asOfCommitSeq). The result’s snapshot names what was read. Valid-time as_of is unsupported.

A current exact-head read can report an opaque schema_revision. A caller can require that revision with HTTP/Python schema_revision or TypeScript schemaRevision; a mismatch returns 409 schema_revision_conflict. Alias/key resolution uses only the explicitly activated schema on the same pin as the data. Importing vocabulary as ordinary graph data cannot activate it.

Retained historical and lagged snapshots cannot yet prove the full activated schema identity. Raw IRI/native-id reads still return exact RDF terms, with schema_revision: null and schema_binding: "snapshot_unavailable". Activated ontology or shapes objects above the 1 MiB binding budget have the same explicit unavailable-schema behavior. Schema-key selection or a revision guard then returns 400 record_schema_snapshot_unavailable. This is an explicit remaining U4 capability, not permission to substitute today’s schema.

Successful reads are complete within the selected scope. Exceeding a bound refuses the whole request; no shortened literal, dropped claim or incomplete response is presented as a round trip.

HTTP bound SDK limits field Default Maximum
max_properties properties 256 10,000
max_outgoing outgoing 100 10,000
max_incoming incoming 100 10,000
max_assertions assertions 50 100
max_assertion_statements assertion_statements 256 10,000

Unknown query parameters return record_parameter_unknown, so misspelled guards and limits cannot silently fall back to defaults. Bounds must be positive. The read also caps the predicate directory at 1,024, point probes at 65,536, lexical term work at 8 MiB, and quoted-term nesting at eight. MCP additionally refuses a complete result over its 80,000-byte output budget; detail: "compact" does not truncate record values. Use the HTTP API for a larger complete record or a bounded SPARQL query for selected facts. Paginated record reads remain a later stage.