Quickstart — Python SDK
The Python SDK is a thin, dependency-free client over the same tools the REST API exposes. It adds three things worth having: it discovers the gateway's base URL for you, it raises a typed exception per failure class instead of handing you a status code, and it refuses some mistakes before a request leaves your process.
Before you start
You need Python 3.9 or newer, a Wexa project, and an administrator role on that project so you can mint a credential.
Step 1 — Install
pip install wexaThe package is wexa and the module is a single file, with no third-party dependencies.
Step 2 — Get a credential
The SDK does not mint credentials; you mint one once and give 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 two things: the workspace it is talking to, and the credential. Pass them
explicitly, or leave both out 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_..."
from wexa import Fabric
fabric = Fabric()
print(fabric.base)
https://fabric.wexa.ai/v1
Constructing the client performs one unauthenticated request to the gateway's connection-info endpoint to discover that base URL, so a client that constructs successfully has already proved the workspace is reachable.
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.
governance = fabric.docs(topic="governance")
print(governance["mode"])
print(governance["quota"])
auto
{'org_window_max': 600, 'org_window_used': 1, 'project_window_max': 120, 'project_window_used': 1}
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
save_context writes nodes. Each node needs a label, a merge key naming the property that
identifies it, and the properties themselves.
result = fabric.save_context(
nodes=[
{
"label": "Customer",
"key": "name",
"properties": {"name": "Acme Corp", "tier": "enterprise"},
}
]
)
print(result)
{'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:
rows = fabric.query_context(
query="MATCH (c:Customer) WHERE c.project_id = $project_id RETURN c.name AS name",
)
print(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:
fabric.query_context(
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 type error: the argument is accepted by the signature and
rejected when the call runs. 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.
Where to go next
Why four arguments are never yours to send, and what the platform does with them.
Every tool, with the Python method name beside the three other surfaces.
The version of the package you just installed.
The four stores a project holds, and which one save_context writes to.