Standalone Incant exposes a semantic JSON API under /incant. The API resolves discovered service entries, wraps them in Incant.Service.Session, and calls standard Incant operations. It does not expose arbitrary remote module/function calls.
Media Types
Success
application/vnd.incant.admin+jsonSuccessful responses use a typed document envelope:
{
"data": {},
"links": {},
"meta": {}
}Errors
application/problem+jsonErrors use RFC 9457 Problem Details plus a stable code member:
{
"type": "about:blank",
"code": "unknown-service",
"title": "Unknown service",
"status": 404,
"detail": "No Incant service named billing is registered.",
"instance": "/incant/services/billing"
}Discovery Routes
API Root
GET /incantReturns API discovery metadata.
Services
GET /incant/servicesLists discovered service contracts.
Service
GET /incant/services/:serviceReturns one service contract.
Surfaces
GET /incant/services/:service/surfacesLists resources, dashboards, and datasets exposed by a service.
Surface
GET /incant/services/:service/surfaces/:surfaceReturns semantic metadata for one surface.
Resource Routes
Rows
GET /incant/services/:service/surfaces/:surface/rowsLists rows using URL table state.
Query Rows
POST /incant/services/:service/surfaces/:surface/queriesRuns a typed table query.
Request:
{
"table": {
"page": 1,
"page_size": 25,
"search": "invoice",
"sort": "inserted_at:desc",
"filters": {}
},
"context": {}
}Read Row
GET /incant/services/:service/surfaces/:surface/rows/:idReturns one row and its semantic detail document.
Action Routes
Actions
GET /incant/services/:service/surfaces/:surface/actionsLists available action metadata.
Action
GET /incant/services/:service/surfaces/:surface/actions/:actionReturns one action contract.
Run Action
POST /incant/services/:service/surfaces/:surface/actions/:action/runsRequest:
{
"payload": {
"id": "123",
"selected_ids": null,
"assigns": {},
"input": {}
},
"context": {}
}Payload conventions:
- row action — set
id; - bulk action — set
selected_ids; - page action — leave both unset;
- form/page input — put typed input fields under
input.
The owning service authorizes the operation and decides what the payload means.
Request Contracts
Request bodies are decoded once at the HTTP boundary into strict JSONCodec-backed structs such as Incant.Web.API.QueryRequest and Incant.Web.API.ActionRunRequest.
Unknown or mistyped fields fail at the boundary instead of reaching service callbacks as arbitrary maps.
Cache and Negotiation
Admin responses include:
Cache-Control: no-store
Vary: AcceptProtocol errors:
405 Method Not AllowedwithAllowfor method mismatches;406 Not Acceptablefor unsupported response media types;415 Unsupported Media Typefor invalid request content types;application/problem+jsonfor typed errors.
Action Results
Synchronous action runs return 200 OK with an action_run resource in data. The result may represent success, failure, navigation, or a one-time reveal.
Clients should treat reveal payloads as secrets and avoid logging or caching them.
Security
The API shares the standalone Incant endpoint but does not provide operator authentication. Deploy it behind the same authenticated private boundary as the LiveView admin.
Service policies remain authoritative. Do not expose the API publicly, and do not treat browser-supplied context as authenticated identity without a trusted translation layer.