Skip to content

REST API

The fallen-8-core-apiApp exposes the engine as an ASP.NET Core REST API. This page is the map of that surface: where the machine-readable contract lives, how routes and versioning are shaped, the conventions that hold across every endpoint, and a directory pointing each endpoint group at its deep-dive doc. It does not re-document individual endpoints: the OpenAPI document and the per-topic pages own those.

The machine-readable contract is an OpenAPI 3.1 document named v0.1 (the .NET 10 default; nothing overrides OpenApiVersion), rendered interactively by the Scalar reference.

This site publishes both, exported from the app while the site is built:

  • Rendered reference: API Reference
  • Raw document: https://docs.fallen-8.com/openapi/v0.1.json

The app serves both itself too, but only in the Development environment (Program.cs maps them behind app.Environment.IsDevelopment()). A local dotnet run --project fallen-8-core-apiApp runs in Development, and the bundled launch profile binds http://localhost:5000:

  • OpenAPI document: http://localhost:5000/openapi/v0.1.json
  • Scalar reference: http://localhost:5000/scalar/v0.1

The Docker/compose image runs in Production (its Dockerfile sets no ASPNETCORE_ENVIRONMENT and binds :8080) so neither endpoint is served at http://localhost:8080. Use a local dotnet run, or the published copies above.

Neither endpoint opts out of authorization, so on an instance with Fallen8:Security:ApiKey set both the document and the Scalar UI answer 401 without the key (-H "X-Api-Key: …"). Only the health probes, and /metrics by default, opt out.

curl http://localhost:5000/openapi/v0.1.json

The API is versioned at 0.1, the default. AssumeDefaultVersionWhenUnspecified is on, so you never have to name a version. To pin one, use any of the configured readers: the query string api-version, the X-Version header, or the media-type ver parameter. Responses carry api-supported-versions (ReportApiVersions).

Controllers declare [Route("api/v{version:apiVersion}/[controller]")], but every action overrides it with an absolute route (a template starting with /), so the version segment never reaches the URL. The routes are the bare paths (/path/{from}/to/{to}, /vertex, /status, …) exactly as the samples use them. /path/4/to/3 is a real route; /api/v0.1/path/4/to/3 is not.

# The bare path is the route; the version defaults to 0.1.
curl -X POST http://localhost:8080/path/4/to/3 -H 'Content-Type: application/json' -d '{}'
# Optionally pin the version (query string shown; the X-Version header works too):
curl "http://localhost:8080/vertex/count?api-version=0.1"

These hold across the whole surface; each topic’s own page carries the detail.

Convention Rule
JSON casing camelCase in both directions (Web defaults, source-generated).
Errors Every error response is RFC 7807 application/problem+json, a consistent title/status/detail shape for a validation 400, a 404, a 409, and a server fault alike. The status codes are unchanged; only the body is uniform.
Not found / invalid The engine follows Try*(out …) : bool, so an expected miss is a status code, never an exception/500. Which code depends on the shape: reads of one element by id (GET /vertex/{id}, /edge/{id}, /graphelement/{id}, /savegames/{id}) answer 204 No Content with no body, while named-resource routes (/subgraph/{name}, /storedquery/{name}, /plugins/{name}, an unknown namespace) answer 404 with a problem body.
Boolean results Two families report the outcome as a bare true/false body with 200 instead of a status code: the /index… routes and POST /service / DELETE /service/{key}. There, false means it did not happen (unknown index, element, or plugin) and is never signalled as an HTTP error. See indexes and plugins.
Mutations Element writes are enqueued on the single writer thread and answer 202 Accepted; pass ?waitForCompletion=true to block until the commit lands. Not every mutating route is waitable: POST /index and the HEAD maintenance routes take no such parameter. See graph model.
Status codes Each action is annotated with [ProducesResponseType], so the exact codes and DTOs live in the OpenAPI document / Scalar, not here.
Namespaces Every namespace-scoped route also answers under /ns/{name}/…; bare URLs address the reserved default namespace, except GET /generate and GET /benchmark, which have no bare alias and answer 400 naming the scoped URL. A namespace that exists but was not loaded by this process refuses every one of them with 503 before the action runs (namespaceState: "notLoaded"); GET /status is the single exception and reports that state instead. See namespaces.
Authentication When configured, the API key travels in the X-Api-Key header (name configurable), the header name and key configuration are owned by security.

Every endpoint group and the page that documents it. Routes shown bare; each also exists under /ns/{name}/… unless noted (Fallen-8-level). One group is noted (namespace required): it is scoped like the rest, but its bare form is refused instead of aliasing default.

Group Routes Doc
Vertices, edges, elements & property scans PUT /vertex, PUT /vertices (batch), GET /vertex/{id}, /vertex/{id}/edges/…, PUT /edge, PUT /edges (batch), GET /edge/{id}, /edge/{id}/{source,target}, GET/DELETE /graphelement/{id}, PUT/DELETE /graphelement/{id}/{propertyId}, POST /graphelements/get (batch read), PUT /graphelements/properties (atomic multi-element property replace), DELETE /graphelements, GET /graph, GET /vertex/count, /edge/count, POST /scan/graph/property/{id}, POST /scan/graph/properties graph-model.md
Indexes & index scans POST /index, PUT/DELETE /index/{id}, DELETE /index/{id}/propertyValue, DELETE /index/{id}/{elementId}, POST /index/backfill/{id} (rebuild from element state), POST /scan/index/{all,range,fulltext,spatial} indexes.md
Vector search PUT /index/vector/{id}, POST /scan/index/vector vector-search.md
Path finding POST /path/{from}/to/{to} path-finding.md
Subgraphs PUT/GET /subgraph, GET/DELETE /subgraph/{name}, GET /subgraph/{name}/graph, POST /subgraph/{name}/recalculate subgraphs.md
Stored queries POST/GET /storedquery, GET/DELETE /storedquery/{name} stored-queries.md
Graph analytics GET /analytics/algorithms, POST /analytics/{name}, /analytics/{name}/partition/{id} graph-analytics.md
Embeddings & semantics PUT/GET/DELETE /graphelement/{id}/embedding/{name}, POST /embedding/{element,elements,search,text} semantic-traversal.md
Semantic layer (documents) POST/GET /document, POST /document/text, GET/DELETE /document/{id}, POST /document/search, GET /document/binding, POST /document/binding/ensure, GET /document/entities. The whole group answers 403 while Fallen8:Ingestion:Enabled is off. unstructured-ingestion.md
Chat gateway (Fallen-8-level) POST /chat (403 while Fallen8:Chat:Enabled is off) semantic-traversal.md
Namespaces (Fallen-8-level) GET /ns, GET/PUT/PATCH/DELETE /ns/{name}, POST /ns/{name}/activate namespaces.md
Bulk import/export GET /bulk/export, POST /bulk/import bulk-import-export.md
Change feed GET /changefeed (Server-Sent Events) change-feed.md
Save games PUT /save, PUT /load; then, all (Fallen-8-level): PUT /save/all, GET /savegames, GET/DELETE /savegames/{id}, PUT /savegames/{id}/load save-games.md
Delegate validation (Fallen-8-level) POST /delegates/validate delegates.md
Plugin registration POST /plugins/{algorithm,function}, POST /plugins/{algorithm,function}/validate, POST /plugins/function/{name}/invoke, GET /plugins, GET/DELETE /plugins/{name} plugin-registration.md
Services POST /service, DELETE /service/{key} plugins.md
Observability GET /status, GET /statistics, GET /config (Fallen-8-level); plus /healthz, /readyz and /metrics, which are mapped outside MVC (no /ns twin, absent from the OpenAPI document, and /metrics only when the Prometheus exporter is on) observability.md
Sample graph PUT /unittest (the canned test graph; for real datasets use the sample gallery) path-finding.md
Benchmark (namespace required) GET /ns/{name}/generate, GET /ns/{name}/benchmark - the only two scoped routes whose bare form is refused with 400 instead of aliasing default benchmark.md
Maintenance HEAD /trim, HEAD /tabularasa (clear graph), HEAD /tabularasa/all (Fallen-8-level) graph-model.md

The document is OpenAPI 3.1 (so, JSON Schema 2020-12), which the generator has to support: check that first for openapi-generator, NSwag or Kiota. A tool stuck on 3.0 needs the document emitted as 3.0 instead (AddOpenApi’s OpenApiVersion option, in Program.cs).

Point the tool at the published https://docs.fallen-8.com/openapi/v0.1.json, or at http://localhost:5000/openapi/v0.1.json from a Development dotnet run, or save either and generate offline in CI. The document declares an ApiKey security scheme (the X-Api-Key header) and requires it document-wide except on the handful of anonymous operations, so a generated client gets a credential field wired up; whether an instance actually enforces it depends on Fallen8:Security:ApiKey. One thing a generated client still needs by hand: its servers entry records the host the document was exported from, not your instance.

  • API Reference: every operation, rendered from the exported OpenAPI document
  • Running Fallen-8: launching the server for dotnet run (Development) vs. Docker (Production)
  • Namespaces: the /ns/{name}/… routing scheme and management API
  • Security: the API key header and key configuration (dynamic code is always on)
  • Graph model: elements, properties, and the waitForCompletion transaction contract
  • Observability: /status, /statistics, /metrics, and the health probes