REST API overview
The REST API is the surface with nothing to install: if you can make an HTTP request, you can call every Wexa tool. The two SDKs are thin clients over exactly these routes. Authentication explains the four credentials; for a first call, start at the Quickstart.
-
Read
GET /v1/connection-info, which needs no credential, to learn the API base and the registered tools.curl -s "https://fabric.wexa.ai/v1/connection-info" -
Send
Authorization: Bearer <credential>with every other request. -
Call a tool with
POST /v1/<tool-name>, kebab-cased, and a JSON body of arguments.curl -s -X POST "https://fabric.wexa.ai/v1/query-context" \ -H "Authorization: Bearer $WEXA_API_KEY" \ -H 'Content-Type: application/json' \ -d '{"query":"MATCH (c:Customer) WHERE c.project_id = $project_id RETURN c.name AS name LIMIT 5"}' -
Read
lifecycle_idandresultfrom the response. -
Pass the
lifecycle_idtoGET /v1/lifecycles/{id}to see how the call was governed.
Limits
| Behavior | What happens |
|---|---|
GET on a tool route | 405 with Allow: POST. |
| Unknown path | A JSON 404 with content-type: application/json, {"error":"not_found","error_description":"no route for POST /v1/<tool>"}. Both SDKs map it to NotFound. |
| Tool not configured on the deployment | The route exists and the call fails with an error naming what is missing: <tool> is not configured (no data-service URL), (no harness URL) or (needs the harness and data-service URLs). |
| Registered tools | GET /v1/connection-info lists them in a tools array. |
| Server-bound arguments | project_id, projectID, organization_id and executed_by come from your credential. Both SDKs refuse them before a request is built. |
POST /v1/docs | Not a machine-readable specification. |
Call a tool, and read the envelope
Call a tool
Every tool is POST /v1/<tool-name>, kebab-cased, with a JSON body. There are no path parameters, no query strings and no verb other than POST. GET on a tool route answers 405 with an Allow: POST header.
curl -s -X POST "https://fabric.wexa.ai/v1/query-context" \
-H "Authorization: Bearer $WEXA_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"query":"MATCH (c:Customer) WHERE c.project_id = $project_id RETURN c.name AS name LIMIT 5"}'Per-tool arguments, returns and errors are on each tool's page, and how every tool call works covers what every call shares. A tool page's arguments are checked against the gateway's own registration and its responses are captured from real calls.
Read the envelope
Every successful tool call returns the same two-key object, so there is no per-tool wrapper to learn.
{
"lifecycle_id": "qlc_000007",
"result": { "nodes_merged": 1, "relationships_merged": 0, "ontology_extended": true, "new_labels": ["Customer"] }
}lifecycle_id identifies the governed lifecycle the call ran as. GET /v1/lifecycles/{id} returns the stage-by-stage record: which stage passed, which refused and why. A refusal carries the same lifecycle_id in its error body, so a failure is traceable the same way a success is. result is the tool's own payload.
Call a non-tool route
Call a non-tool route
Everything that is not a tool is conventional REST: GET for reads, plural collections, and sub-paths for actions.
curl -s "https://fabric.wexa.ai/v1/whoami" -H "Authorization: Bearer $WEXA_API_KEY"
curl -s "https://fabric.wexa.ai/v1/approvals" -H "Authorization: Bearer $WEXA_API_KEY"
curl -s "https://fabric.wexa.ai/v1/lifecycles/qlc_000002" -H "Authorization: Bearer $WEXA_API_KEY"The gateway states the rule about itself. Calling the documentation tool and reading the rules array returns, verbatim:
REST shape: every TOOL is `POST /v1/<tool-name>` in kebab-case; everything else (whoami, approvals,
audit, lifecycles, catalog) is conventional REST — GET for reads, plural collections, sub-paths for
actionsThe non-tool routes:
| Route | What it is for |
|---|---|
GET /healthz | Liveness. Unauthenticated. |
GET /v1/connection-info | Discovery: the API base URL, the issuer, the registered tool list. Unauthenticated. |
GET /v1/whoami | Who your credential says you are: user, role, organization, department, project, grants. |
POST /v1/apikeys, GET /v1/apikeys, DELETE /v1/apikeys/{id} | Credential management. Requires a user token, not an API key. |
GET /v1/approvals, POST /v1/approvals/{id}/approve, POST /v1/approvals/{id}/reject | The approval queue and its decisions. |
GET /v1/lifecycles/{id} | The stage-by-stage record of one governed call. |
GET /v1/audit, GET /v1/audit/verify | The audit record and its hash-chain verification. |
GET /v1/policy-decisions | What the policy engine ruled, and when. |
GET and PUT /v1/projects/{projectId}/mode | Read or change a project's mode. |
GET /v1/catalog/* | The data catalog: assets, lineage, scorecards, connector status, sync statistics. |
/v1/codesync/* | Repository registration, ingestion and job status for code sync. |
POST /v1/agents/{agentflowId}/chat/completions | An OpenAI-compatible proxy onto a promoted agent version. |
/oauth/* and /.well-known/* | OAuth 2.1 registration, authorization, token, and the two discovery documents. |
Find your address, and check what your credential holds
Find your address with discovery
The only address you should hard-code is your workspace URL. GET /v1/connection-info is unauthenticated and tells you the rest, so the gateway decides its own address and moving it needs no client change.
curl -s "https://fabric.wexa.ai/v1/connection-info"{
"api": { "base_url": "https://fabric.wexa.ai/v1" },
"issuer": "https://fabric.wexa.ai",
"workspace_header": "X-Wexa-Workspace",
"tools": ["query-context", "create-ontology", "save-context", "docs", "search-code", "fetch-code"]
}Both SDKs do this for you before their first call.
Check what your credential holds
POST /v1/docs is a tool like any other. It takes a topic and returns prose and structured facts about your own scope. It is not an API specification: it serves no OpenAPI or Swagger document and returns no schema.
It is the fastest answer to "why did that call fail", because it tells you what your credential holds rather than what you meant it to hold.
curl -s -X POST "https://fabric.wexa.ai/v1/docs" \
-H "Authorization: Bearer $WEXA_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"topic":"governance"}'The result contains your effective grants, your project's mode, your live quota headroom, the gateway's operating rules and your scope.
{
"grants": ["fabric:query.read", "fabric:docs.read", "fabric:ontology.write", "fabric:orchestrate.read",
"fabric:orchestrate.write", "fabric:agent.run", "fabric:skill.write", "fabric:model.write"],
"mode": "auto",
"quota": { "org_window_max": 600, "org_window_used": 1, "project_window_max": 120, "project_window_used": 1 },
"rules": ["..."],
"scope": { "org_id": "org_c10", "project_id": "proj_c10", "role": "OWNER", "auth_kind": "api_key" }
}What's next
- Authentication to pick the credential for your caller.
- Errors and retries for status codes, error bodies and what is worth retrying.
- Server-bound arguments for why four argument names are never yours to send.