Skip to content

REST Channel

Query IdentityScribe via HTTP/JSON with OpenAPI documentation, conditional requests, and cursor pagination.

The REST channel provides:

  • Collection and lookup endpoints with filtering, sorting, and Relay-style pagination
  • Change history API — global feed and per-entry history with temporal lookup
  • OpenAPI specification with interactive UI (Scalar)
  • Conditional requests — ETag/If-None-Match for efficient polling
  • Streaming responses — memory-efficient handling of large result sets

Related:

The REST channel is enabled by default. Access points:

URLDescription
/apiOpenAPI UI (HTML) or spec (JSON/YAML via content negotiation)
/api.jsonDownload OpenAPI spec as JSON
/api.yamlDownload OpenAPI spec as YAML
/openapi.jsonWell-known alias for OpenAPI JSON
/openapi.yamlWell-known alias for OpenAPI YAML
/api/entries/{type}Collection search
/api/entries/{type}/{id}Single entry lookup
/api/entries/{type}/{id}/changesPer-entry change history
/api/changesGlobal change feed

Browse the interactive API documentation at /api. The UI provides:

  • Complete endpoint documentation with request/response schemas
  • Code samples for curl, JavaScript, TypeScript, and Go
  • Live API testing (in dev mode)
  • Schema with attribute metadata extensions (x-scribe-*)
  • Documented headers, including conditional requests and Prefer/Preference-Applied

Download the spec: /api?format=json or /api?format=yaml, or use the direct endpoints /api.json and /api.yaml. See API Discovery for programmatic channel and schema discovery.

Filters auto-detect format based on syntax. See Filters Reference for complete syntax.

FormatDetectionExample
JSONStarts with { or [{"cn":"john"}
LDAPStarts with ((cn=john*)
FleXDefaultcn = john
SCIMFallbackcn eq "john"
Terminal window
# FleX (recommended)
?filter=department=Engineering AND active=true
# JSON (programmatic)
?filter={"cn":"john","status":"active"}

See Filters Reference for complete syntax.

Select attributes to return:

ValueMeaning
cn,mail,snSpecific attributes
*All user attributes
+All operational attributes
1.1No attributes (IDs only)

Sort by one or more attributes:

Terminal window
?sort=cn # Ascending
?sort=-cn # Descending
?sort=sn,-cn # Multiple keys

Relay-style cursor pagination:

ParameterDescription
first / afterForward pagination
last / beforeBackward pagination
limitAlias for first/last
Terminal window
# First page
?first=25
# Next page
?first=25&after=eyJjbiI6Impv...

Control response content with include:

PartDefaultDescription
nodesEntry objects
edges{cursor, node} objects
pageInfoPagination metadata
countTotal count

Notes:

  • Use ?include=count for count-only responses (skips entry hydration)
  • Use ?include=edges,pageInfo for Relay-style responses
Terminal window
?include=count # Count only
?include=edges,pageInfo # Relay format

Lookup endpoints accept GlobalId, UUID, UOID, or DN. See Entry identifiers for the full format reference.

DN values must be URL-encoded in paths.

Lookup endpoints support efficient polling with ETag validation:

Terminal window
# First request — get entry and ETag
curl -I "/api/entries/users/$UUID"
# ETag: W/"abc123..."
# Subsequent requests — 304 when unchanged
curl -H 'If-None-Match: W/"abc123..."' "/api/entries/users/$UUID"
# HTTP/1.1 304 Not Modified

If-Modified-Since is also supported as a fallback.

Cache headers:

  • Lookup responses include Cache-Control: private, max-age=0, must-revalidate
  • Search responses include Cache-Control: no-store
  • Lookup responses include Last-Modified when available

Control how the API handles unknown attributes referenced in fields, sort, or filter:

  • Prefer: handling=lenient (default) — unknown attributes are ignored
  • Prefer: handling=strict — unknown attributes return 400 INVALID_ARGUMENT with the list of unknowns
  • When explicitly set, responses include Preference-Applied: handling=lenient|strict
Terminal window
# Strict attribute validation
curl -H 'Prefer: handling=strict' "/api/entries/users?fields=cn,unknownAttr"

Query change history via the global feed or per-entry endpoint.

Terminal window
# Duration
?range=24h
# ISO 8601 interval
?range=2024-01-01/2024-01-31
# Natural language
?range=yesterday
?since=this week
?since=last 3 days
# Since/until
?since=2024-01-01&until=2024-01-07
ParameterDescription
typeEvent types: add, modify, move, delete
affectsMODIFY events by changed attributes
entryTypeFilter by entry type (global endpoint only)
PartDescription
nodesChange events (no cursor)
edges{cursor, node} change events (Relay-style)
pageInfoPagination metadata
countTotal count
dataRaw event data
patchJSON Patch-inspired format (delta semantics)
mergeJSON Merge Patch-inspired format (delta semantics)
metaEvent metadata

Notes:

  • Use ?include=count for count-only responses
  • Use ?include=edges,pageInfo for Relay-style responses
Terminal window
# Get changes with patch format
curl "/api/changes?include=nodes,patch,pageInfo&first=50"

View an entry at any point in time:

Terminal window
# At specific timestamp
?at=2024-04-22T08:43:50Z
# Relative duration
?at=1h
# At specific event (cursor from change history)
?at=AAFntW9XAAAAAAApQwAA

REST errors return HTTP status codes with JSON error bodies:

StatusKindMeaning
400INVALID_ARGUMENTInvalid request
404NOT_FOUNDEntry not found
429RESOURCE_EXHAUSTEDRate limited
503UNAVAILABLEService busy
{
"error": {
"id": "550e8400-...",
"code": "ARGUMENT_INVALID_JSON",
"kind": "INVALID_ARGUMENT",
"message": "Invalid JSON format for 'filter'."
}
}

See Failures for complete error documentation.

REST operations emit OpenTelemetry traces:

SpanDescription
REST.SearchCollection search
REST.LookupSingle entry lookup
REST.HistoryChange history queries

Spans include entry type, response shape, and error details.

Related: