Quickstart — TypeScript SDK
The TypeScript SDK is a typed client over the same tools the REST API exposes. It gives you typed arguments, typed results and a distinct error class per failure, and it refuses some mistakes before a request leaves your process.
Before you start
You need Node 18 or newer, a Wexa project, and an administrator role on that project so you can mint a credential.
Step 1 — Install
npm install @wexa-fabric/sdkThe package ships both ESM and CommonJS builds with type declarations for each, so it works from
import and from require without a shim.
Step 2 — Get a credential
The SDK does not mint credentials; you mint one once and hand it to the client. An API key is pinned to exactly one project when it is created, and that scope never widens — which is why the client takes no project argument anywhere.
$FABRIC_USER_TOKEN below is your own Wexa sign-in token, the session token the console holds
once you have signed in. The console mints keys from this same endpoint under
Simple mode → Generate API key if you would rather not handle it yourself.
curl -sS -X POST https://fabric.wexa.ai/v1/apikeys \
-H "Authorization: Bearer $FABRIC_USER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"org_id":"org_...","dept_id":"dept_...","project_id":"proj_...","name":"quickstart"}'
The response carries the secret exactly once:
{
"id": "key_...",
"name": "quickstart",
"note": "store this secret now; it is not retrievable again",
"secret": "fab_sk_..."
}
Minting a key requires an owner, organization-administrator or project-administrator role; any other
role is refused with API key creation requires an admin role on this project.
Step 3 — Construct a client
The client needs the workspace and the credential. Pass them explicitly, or leave the options out
entirely and let it read WEXA_WORKSPACE and WEXA_API_KEY from the environment.
export WEXA_WORKSPACE="https://fabric.wexa.ai"
export WEXA_API_KEY="fab_sk_..."
import { Fabric } from '@wexa-fabric/sdk'
const fabric = new Fabric()
Step 4 — Make your first call
The documentation tool is the best first call: it is registered in every deployment, needs no data in your project, and returns your own scope and limits, so a successful response proves the credential and the scope together.
const governance = await fabric.docs({ topic: 'governance' })
console.log(governance.mode)
console.log(JSON.stringify(governance.quota))
auto
{"org_window_max":600,"org_window_used":4,"project_window_max":120,"project_window_used":4}
The SDK returns the result of the envelope directly, so you get the tool's own output rather than a
wrapper to unpack. mode is the project mode — auto is Simple mode — and quota is your rolling
call budget at both the project and the organization level.
Step 5 — Write and read the context graph
saveContext writes nodes. Each node needs a label, a merge key naming the property that identifies
it, and the properties themselves.
const written = await fabric.saveContext({
nodes: [
{
label: 'Customer',
key: 'name',
properties: { name: 'Acme Corp', tier: 'enterprise' },
},
],
})
console.log(JSON.stringify(written))
{"nodes_merged":1,"relationships_merged":0,"ontology_extended":false}
ontology_extended reports whether writing that node taught the project a type it did not have. The
first time a Customer is written it is true and new_labels names it; afterwards it is false,
because there was nothing new to register.
Reading takes read-only Cypher, and the query must filter on the project:
const rows = await fabric.queryContext({
query: 'MATCH (c:Customer) WHERE c.project_id = $project_id RETURN c.name AS name',
})
console.log(rows.row_count)
Step 6 — See a refusal
$project_id above is bound by Wexa from your credential. Try to supply it yourself and the SDK
stops the call at the call site, before any request is built:
await fabric.queryContext({
query: 'MATCH (n) WHERE n.project_id = $project_id RETURN n',
project_id: 'someone_elses',
})
ValidationError: ['project_id'] are bound server-side from your token scope; sending them is rejected
This is a run-time refusal rather than a compile-time one: the argument is rejected when the call
runs, not by the type checker. That is deliberate — the same check has to hold for arguments
assembled at run time, which no type system sees. The four arguments treated this way are
project_id, projectID, organization_id and executed_by.
Step 7 — Release the client
The client holds an abort controller so that an in-flight request and any approval poll can be cancelled together. In a long-lived process, close it when you are done:
fabric.close()
Calling it twice is a no-op, and the client cannot be reused afterwards.
Where to go next
Why four arguments are never yours to send, and what the platform does with them.
Every tool, with the TypeScript method name beside the three other surfaces.
The version of the package you just installed.
The four stores a project holds, and which one saveContext writes to.