Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Headers, Content Types, and Request Sizing

This document covers HTTP headers, content type negotiation, request size limits, and related considerations for the Fluree HTTP API.

Request Headers

Content-Type

Specifies the format of the request body.

Supported Values:

JSON-LD Transactions and Queries:

Content-Type: application/json

Default for JSON-LD transactions and JSON-LD queries.

Content-Type: application/ld+json

Explicit JSON-LD content type.

SPARQL Queries:

Content-Type: application/sparql-query

For SPARQL SELECT, ASK, CONSTRUCT queries.

Content-Type: application/sparql-update

For SPARQL UPDATE operations. See SPARQL UPDATE for supported operations.

RDF Formats:

Content-Type: text/turtle

For Turtle RDF format transactions. Supported on /insert (fast direct path), /upsert, /sync and the Graph Store /data endpoint. application/x-turtle is accepted as an alias. On /insert and /upsert, a Turtle body that contains graph blocks is read as TriG.

Content-Type: application/trig

For TriG format transactions with named graphs (GRAPH blocks). Supported on /insert and /upsert, and on /sync and the Graph Store /data endpoint (one graph per request). application/x-trig is accepted as an alias.

Content-Type: application/n-triples

For N-Triples bodies, parsed as Turtle; accepted wherever Turtle is.

Content-Type: application/rdf+xml

RDF/XML is an output format only; it is not accepted as a request body.

Accept

Specifies the desired response format.

Supported Values:

Accept: application/json

Compact JSON format (default).

Accept: application/ld+json

Full JSON-LD with @context.

Accept: application/sparql-results+json

SPARQL JSON Results format (for SPARQL queries).

Accept: application/sparql-results+xml

SPARQL XML Results format (for SPARQL SELECT/ASK queries).

Accept: text/turtle

Turtle (for CONSTRUCT/DESCRIBE queries and Graph Store GET).

Accept: application/n-triples

N-Triples (for CONSTRUCT/DESCRIBE queries and Graph Store GET).

Accept: application/rdf+xml

RDF/XML graph format (for CONSTRUCT/DESCRIBE queries and Graph Store GET).

Accept: application/trig
Accept: application/n-quads

TriG and N-Quads (for CONSTRUCT/DESCRIBE queries). Required, with JSON-LD, for a CONSTRUCT whose template writes into named graphs (GRAPH blocks).

Accept: application/vnd.fluree.agent+json

Agent JSON format — optimized for LLM/agent consumption. Returns a self-describing envelope with schema, compact rows, and pagination support. See Output Formats for details.

Use the Fluree-Max-Bytes header to set a byte budget for response truncation:

Fluree-Max-Bytes: 32768

Multiple Accept Values:

You can specify multiple formats with quality values:

Accept: application/ld+json; q=1.0, application/json; q=0.8

The server will choose the best match based on quality values and support.

Authorization

Authentication credentials. Only required when the server has authentication enabled for the relevant endpoint group (see Configuration).

Bearer Token (Ed25519 JWS or OIDC):

Authorization: Bearer eyJhbGciOiJFZERTQSIsImp3ayI6eyJrdHkiOiJPS1AiLCJjcnYiOiJFZDI1NTE5IiwieCI6Ii4uLiJ9fQ...

The server automatically dispatches to the correct verification path based on the token header:

  • Tokens with an embedded jwk field use the Ed25519 verification path
  • Tokens with a kid field use the OIDC/JWKS verification path (requires oidc feature)

Signed Requests:

For JWS/VC signed request bodies, set Content-Type to application/jose:

Content-Type: application/jose

See Signed Requests for details.

Content-Length

The server requires Content-Length for all POST requests:

Content-Length: 1234

Most HTTP clients set this automatically.

Accept-Encoding

The server does not compress responses and ignores Accept-Encoding. See Compression.

User-Agent

Identify your client application:

User-Agent: MyApp/1.0.0 (https://example.com)

Helpful for server logs and troubleshooting.

X-Request-ID

Client-supplied request ID for tracing:

X-Request-ID: abc-123-def-456

The server includes this in its logs for correlation; it does not echo it in the response. When a request queues background indexing work, the copied X-Request-ID also appears on the background indexer worker logs so you can connect the foreground request and later indexing activity in plain log search.

Fluree-Min-T

Request a hard read-after-write guarantee for query and explain endpoints:

Fluree-Min-T: 42

Before executing the request, the server refreshes the referenced ledger(s) until each has reached at least the requested transaction time. If the target t is not visible before query_min_t_timeout_ms, the server returns a read-after-write timeout error. JSON-LD query bodies may also specify the same requirement as opts.min-t, opts.min_t, or opts.minT; body opts take precedence over the header for that query body.

Numeric time-travel snapshots such as from: "ledger:main@t:42" also wait until that t is visible, then query that pinned snapshot. Fluree-Min-T is useful when the query itself reads current HEAD but must not run until a known transaction has arrived.

The header must resolve to at least one target ledger. On a ledger-scoped endpoint the endpoint’s ledger is used; on the connection-scoped query endpoint the target comes from the query’s FROM clause. Sending Fluree-Min-T to the connection-scoped endpoint with no FROM (and no other resolvable ledger) is rejected with 400 Bad Request rather than silently ignored.

Response Headers

Content-Type

Indicates the format of the response body:

Content-Type: application/json; charset=utf-8

Content-Length

Size of the response body in bytes:

Content-Length: 5678

Tracking Headers

A request that asks for tracking (see Fluree Request Headers) gets its metrics in the response body and in these headers:

HeaderContent
x-fdb-timeExecution time, e.g. 12.34ms
x-fdb-fuelFuel consumed
x-fdb-policyPer-policy statistics, as base64-encoded JSON
x-fdb-policy-enforcementJSON, sent only when policy governed the request
x-fdb-reasoningJSON, sent only when a reasoning mode ran; "capped": true means results may be incomplete

Query responses carry no transaction-time, commit, ETag or Cache-Control headers. Read a ledger’s current t from GET /info/<ledger>.

Rate Limit Headers

The server does not rate-limit requests and sends no X-RateLimit-* headers. If a reverse proxy or API gateway in front of it enforces rate limits, any such headers come from that layer.

Content Type Details

IRI form: absolute vs. abbreviated

Response formats fall into two families, and they treat IRIs differently.

W3C result serializations — application/sparql-results+json, application/sparql-results+xml, text/csv, text/tab-separated-values — always emit absolute IRIs. A query’s PREFIX and BASE declarations do not shorten them. These formats carry no prefix map and no base slot, so an abbreviated IRI in one of them could not be expanded back by the consumer; the specs define the value as the absolute IRI.

JSON-LD-flavored formats — application/ld+json, application/json, application/vnd.fluree.agent+json, typed JSON, NDJSON, and the fluree CLI’s display output — abbreviate IRIs against the query’s @context / PREFIX prologue. That is intentional: the consumer either receives the context alongside the data or is a human reading a terminal.

If you need absolute IRIs from a SPARQL query, request application/sparql-results+json.

JSON-LD (application/json, application/ld+json)

Request Example:

{
  "@context": {
    "ex": "http://example.org/ns/",
    "schema": "http://schema.org/"
  },
  "@graph": [
    {
      "@id": "ex:alice",
      "@type": "schema:Person",
      "schema:name": "Alice"
    }
  ]
}

Compact vs Expanded:

application/json returns compact JSON:

[
  { "name": "Alice" }
]

application/ld+json returns with full context:

{
  "@context": {
    "name": "http://schema.org/name"
  },
  "@graph": [
    { "name": "Alice" }
  ]
}

SPARQL Query (application/sparql-query)

Request Example:

PREFIX ex: <http://example.org/ns/>
PREFIX schema: <http://schema.org/>

SELECT ?name
FROM <mydb:main>
WHERE {
  ?person a schema:Person .
  ?person schema:name ?name .
}

Plain text SPARQL query in the request body.

SPARQL Results JSON (application/sparql-results+json)

Response Example:

{
  "head": {
    "vars": ["name"]
  },
  "results": {
    "bindings": [
      {
        "name": {
          "type": "literal",
          "value": "Alice",
          "datatype": "http://www.w3.org/2001/XMLSchema#string"
        }
      }
    ]
  }
}

Follows W3C SPARQL 1.1 Query Results JSON Format specification. uri values are always absolute IRIs, and a literal carries its datatype unless it is an xsd:string — see IRI form.

Turtle (text/turtle)

Transaction Request:

@prefix ex: <http://example.org/ns/> .
@prefix schema: <http://schema.org/> .

ex:alice a schema:Person ;
  schema:name "Alice" ;
  schema:age 30 .

CONSTRUCT Response:

@prefix ex: <http://example.org/ns/> .
@prefix schema: <http://schema.org/> .

ex:alice a schema:Person .
ex:alice schema:name "Alice" .

Request Size Limits

Default Limits

The server enforces a single request body size limit to prevent resource exhaustion. It applies to every request body — transactions, queries, and history requests alike:

  • Default limit: 50 MB (52428800 bytes)
  • Configurable: --body-limit (env FLUREE_BODY_LIMIT, config file body_limit)

Exceeding Limits

If a request exceeds size limits:

Status Code: 413 Payload Too Large

Response:

{
  "error": "request body exceeds the configured limit",
  "status": 413,
  "@type": "err:db/PayloadTooLarge"
}

Configuration

Set a custom limit when starting the server:

fluree server run -- --body-limit 20971520   # 20 MB

See Configuration for all server options.

Response Size

The server has no configurable response size limit. To keep large result sets manageable, use LIMIT and pagination:

{
  "select": ["?name"],
  "where": [...],
  "limit": 1000,
  "offset": 0
}

Compression

The server neither compresses responses nor decodes compressed request bodies (Content-Encoding: gzip). To compress traffic, put a reverse proxy in front of the server and let it handle compression.

Character Encoding

All text content uses UTF-8 encoding.

Request:

Content-Type: application/json; charset=utf-8

Response:

Content-Type: application/json; charset=utf-8

Unicode characters are supported in:

  • IRIs
  • Literal values
  • Property names
  • Comments

CORS Headers

For web browser access, the server supports Cross-Origin Resource Sharing (CORS).

CORS Request Headers

Preflight Request:

OPTIONS /query HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type

CORS Response Headers

Preflight Response:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: *
Access-Control-Allow-Headers: Content-Type

The requested headers are mirrored back in Access-Control-Allow-Headers.

Actual Response:

Access-Control-Allow-Origin: *

CORS Configuration

CORS is either on or off. It is on by default; disable it with --cors-enabled=false, FLUREE_CORS_ENABLED=false, or cors_enabled = false in the [server] section of the config file. When on, the server allows any origin and any method and does not send Access-Control-Allow-Credentials.

The server has no per-origin, per-method, or per-header allow lists. To restrict CORS to specific origins, disable it on the server and set the CORS headers in a reverse proxy in front of it.

Caching Headers

Query and transaction responses carry no ETag or Cache-Control headers, and the server does not answer conditional requests (If-None-Match) for them. Only the storage proxy’s block endpoints, used for replication, send an ETag and an immutable Cache-Control.

Fluree Request Headers

HeaderValueEffect
fluree-ledgerLedger IDTarget ledger for connection-scoped endpoints; a ledger in the path takes precedence
fluree-identityIdentity IRIIdentity whose policies apply
fluree-policyJSONInline policy for the request
fluree-policy-classIRI(s), comma-separated or repeatedPolicy classes to apply
fluree-policy-valuesJSONValues bound into policy queries
fluree-default-allowtrue / falseAccess when no policy matches; overrides the ledger’s f:defaultAllow
fluree-track-metatrueTrack everything below
fluree-track-fueltrueReport fuel consumed
fluree-track-timetrueReport execution time
fluree-track-policytrueReport per-policy statistics
fluree-max-fuelNumberFail the query once it consumes this much fuel
fluree-min-tTransaction tSee Fluree-Min-T

A SPARQL request can carry these options in its text instead, as # PRAGMA comments (all but fluree-ledger and the inline fluree-policy). A pragma wins over the header that names the same option, except that meta adds to the header’s tracking, max-fuel takes the smaller of the two and, on an authenticated request, a policy pragma may only repeat the policy the headers select (see Request options).

Whether a request may choose its own identity or policy depends on the server’s authorization settings; see Policy in Queries. Tracking and fuel are covered in Tracking and Fuel Limits.

There is no per-request timeout header. Queries are bounded by the server-wide --query-timeout-ms (FLUREE_QUERY_TIMEOUT_MS, default 15 minutes); see Configuration.

Best Practices

1. Always Set Content-Type

Explicitly set Content-Type for all requests:

Content-Type: application/json

2. Use Appropriate Accept Headers

Request the format you need:

Accept: application/json

3. Include User-Agent

Identify your application:

User-Agent: MyApp/1.0.0

4. Monitor Rate Limits

If a proxy or gateway in front of the server enforces rate limits, check its headers and back off when needed:

const remaining = response.headers.get('X-RateLimit-Remaining');
if (remaining < 10) {
  // Slow down requests
}

5. Use Request IDs

Include request IDs for tracing:

X-Request-ID: uuid-v4-here