https://wrench.example.com · Auth:
Authorization: Bearer <key> · Response: text/event-stream (SSE).
Create API keys under Settings → Developer.
Send a reported problem plus whatever context you have and receive the same streamed diagnostic guidance the Wrench apps produce — safety warnings, ranked likely causes, an ordered diagnostic sequence and a parts/tools list. Guidance streams back token by token as Server-Sent Events so you can render it live.
Every request needs a Bearer API key in the Authorization header:
Authorization: Bearer wr_live_xxxxxxxxxxxxxxxxxxxxxxxx
Keys are created and revoked under Settings → Developer. Keys are
hashed at rest — copy a key when it's shown; it can't be retrieved later. A missing
or invalid key returns 401.
Send a JSON body. Provide context, messages, or both —
at least one is required (an empty body returns 400).
| Field | Type | Notes |
|---|---|---|
context | object | Freeform. All fields optional — send what you have. |
context.title | string | Short summary of the problem. |
context.description | string | The reported problem in the technician's words. |
context.equipmentType | string | Equipment class / type, e.g. "commercial refrigeration". |
context.priorNotes | string | Prior history, recent fixes, or anything else relevant. |
messages | array | Conversation history for follow-ups. Each item is { "role": "user" | "assistant", "content": string }. The server prepends your context as the first turn. |
There is no fixed equipment schema — context is intentionally
freeform. Send a single problem for a first answer, or replay the visible
conversation in messages to ask a follow-up.
On success the response is text/event-stream. Each frame is a
data: line carrying a small JSON object:
| Frame | Meaning |
|---|---|
data: {"text":"…"} | A chunk of guidance. Concatenate text across frames to build the full answer. |
data: {"done":true,"requestId":N} | Terminal frame. The stream is complete; requestId is the logged request's id. |
data: {"error":"…"} | The generation failed mid-stream. No further frames follow. |
Errors that occur before streaming starts return a JSON error envelope with the matching HTTP status:
| Status | When |
|---|---|
401 | Missing or invalid API key. |
400 | Bad body — neither context nor messages provided. |
402 | Your plan doesn't include Wrench troubleshooting, or your monthly call quota is exhausted. |
429 | Rate limited — you hit the per-hour cap or a short-window burst guard. Slow down and retry. |
Monthly and hourly caps are per account and scale with your plan — see
pricing. A failure after the stream has started
arrives as an error SSE frame (above) rather than an HTTP status,
because headers are already sent.
curl -N https://wrench.example.com/api/v1/troubleshoot/stream \
-H "Authorization: Bearer $WRENCH_KEY" \
-H "Content-Type: application/json" \
-d '{
"context": {
"title": "Walk-in freezer warm",
"equipmentType": "commercial refrigeration",
"description": "Not holding temp; compressor short-cycles.",
"priorNotes": "Condenser cleaned last month."
}
}'
# → text/event-stream
data: {"text":"SAFETY: LOTO before opening the electrical panel.\n"}
data: {"text":"LIKELY CAUSES: 1) Low refrigerant charge..."}
data: {"done":true,"requestId":8412}
const res = await fetch(
"https://wrench.example.com/api/v1/troubleshoot/stream", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.WRENCH_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
context: { description: "Pump losing prime on startup" },
}),
});
let answer = "";
for await (const chunk of res.body) {
for (const line of chunk.toString().split("\n")) {
if (!line.startsWith("data:")) continue;
const evt = JSON.parse(line.slice(5).trim());
if (evt.text) answer += evt.text;
if (evt.error) throw new Error(evt.error);
if (evt.done) console.log("done", evt.requestId);
}
}
console.log(answer);
To ask a follow-up, replay the conversation in messages. Keep the
original context so the guidance stays grounded:
{
"context": { "description": "Walk-in freezer warm; compressor short-cycles." },
"messages": [
{ "role": "assistant", "content": "LIKELY CAUSES: 1) Low refrigerant charge..." },
{ "role": "user", "content": "Charge is good. What next?" }
]
}