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.
OpenAPI document and Scalar reference
Section titled “OpenAPI document and Scalar reference”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.jsonInvoke-RestMethod http://localhost:5000/openapi/v0.1.jsonVersioning and route shape
Section titled “Versioning and route shape”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"Invoke-RestMethod http://localhost:8080/path/4/to/3 -Method Post -ContentType application/json -Body '{}'Invoke-RestMethod 'http://localhost:8080/vertex/count?api-version=0.1'Conventions
Section titled “Conventions”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. |
Endpoint directory
Section titled “Endpoint directory”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 |
Generating a client
Section titled “Generating a client”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.
See also
Section titled “See also”- 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
waitForCompletiontransaction contract - Observability:
/status,/statistics,/metrics, and the health probes