Part 2 — Call it from your code
In Part 1 we built and published a support-ticket classifier. Now we call it from code, so your ticketing system can route tickets automatically.
Get your credentials
- Mint an API key
At accounts.zerowidth.ai → Workspace → API keys, create a key with the
workbench:flows:runscope. Copy the secret when it's shown — that's the only time you'll see it. (API keys) - Grab the Flow ID
Open your classifier in Workbench, open the dev drawer → Quickstart, and copy the Flow ID — a UUID. It's not the id in the editor URL; the API addresses flows by this stable id. (Why the two ids)
Run it
Feed the ticket text in as the data input and pin the published version. The response comes back with the flow's outputs — for our classifier, the chosen queue.
curl -X POST https://api.zerowidth.ai/1.0/flows/$ZW_FLOW/runs \
-H "Authorization: Bearer $ZW_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": { "kind": "form", "values": { "data": "Card declined twice but I was still charged." } },
"source": { "kind": "published" }
}'const res = await fetch(
`https://api.zerowidth.ai/1.0/flows/${process.env.ZW_FLOW}/runs`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ZW_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
input: { kind: "form", values: { data: ticketText } },
source: { kind: "published" },
}),
},
)
const { outputs } = await res.json()
const queue = outputs.data // "billing"import os, requests
res = requests.post(
f"https://api.zerowidth.ai/1.0/flows/{os.environ['ZW_FLOW']}/runs",
headers={"Authorization": f"Bearer {os.environ['ZW_API_KEY']}"},
json={
"input": {"kind": "form", "values": {"data": ticket_text}},
"source": {"kind": "published"},
},
)
queue = res.json()["outputs"]["data"] # "billing"The response:
{
"executionId": "exec_8a2c91...",
"status": "ok",
"outputs": { "data": "billing" },
"costSummary": { "total": 0.000098 },
"durationMs": 210
}
outputs.data is the queue — route the ticket on it, no parsing required. That's the payoff of building a classifier: the shape is guaranteed.
Make it production-ready
Pin an explicit version
"source": { "kind": "published" } runs the latest published version — convenient, but it changes the moment anyone publishes. For production, pin the exact version so a rollout is deliberate: "source": { "kind": "published", "version": "1.0.0" }. See ship to production.
Retry safely
If a request fails mid-flight, retry with the same Idempotency-Key header and you'll replay the original result instead of running (and paying for) the classification twice.
Handle the errors you'll actually see
Branch on the response code, not the message (errors). The ones to expect here: 404 not_found (wrong Flow ID — usually the editor-URL id instead of the Flow ID), 402 plan_limit (key cost cap or workspace balance), and 401 auth_invalid (bad or revoked key). The run-flow troubleshooting section walks each.
It works. But does it work well? A classifier that's right in the demo and wrong on the long tail is worse than none. Next, we measure it.