Why is my Wireflow API request failing?
A Wireflow API request fails for the reason its status code names, such as 401 for the key, 402 for credits or 429 for too many requests. Fix each one here.
Your Wireflow API request is failing for the reason its status code and error message name: a missing or wrong key (401), too few credits (402), no permission (403), an id that doesn't exist (404), a malformed request (400), too many requests (429) or a failure on Wireflow's side (500). Find your status below. Each section gives the cause, the fix and a check that the fix worked.
| Status | Meaning |
|---|---|
400 |
Missing required fields, invalid node structure, empty workflow |
401 |
Missing or invalid API key, expired key |
402 |
Insufficient credits to run the workflow |
403 |
No permission to access the resource |
404 |
Workflow or execution does not exist |
429 |
Rate limit exceeded |
500 |
Unexpected server-side failure |
How do I see the full error the API sent back?
Read three things from the response: the HTTP status, the error field in the body and the X-Request-Id header. The error field comes in two shapes, so handle both: a flat { "error": "message" }, sometimes with extra fields, or an object with type, message and code.
{
"error": {
"type": "invalid_request_error",
"message": "Workflow not found",
"code": "not_found"
}
}
curl -i prints the status line and the headers, X-Request-Id included, above the body:
curl -i https://www.wireflow.ai/api/v1/me \
-H "Authorization: Bearer $WIREFLOW_API_KEY"
const res = await fetch('https://www.wireflow.ai/api/v1/me', {
headers: { Authorization: `Bearer ${process.env.WIREFLOW_API_KEY}` },
});
if (!res.ok) {
const body = await res.json().catch(() => ({}));
const message = typeof body.error === 'string' ? body.error : body.error?.message;
console.error(res.status, message, res.headers.get('X-Request-Id'));
}
import os
import requests
res = requests.get(
"https://www.wireflow.ai/api/v1/me",
headers={"Authorization": f"Bearer {os.environ['WIREFLOW_API_KEY']}"},
)
if not res.ok:
try:
error = res.json().get("error")
except ValueError:
error = None
message = error.get("message") if isinstance(error, dict) else error
print(res.status_code, message, res.headers.get("X-Request-Id"))
If an error persists, contact support with the X-Request-Id value from the response.
Why do I get 401 "Invalid API key" or "Missing Authorization header"?
- Cause: Wireflow couldn't match the request to a valid key. The message says which part failed:
| Message | Cause | Fix |
|---|---|---|
| "Missing Authorization header" | The request has no Authorization header |
Send Authorization: Bearer YOUR_API_KEY on every request |
| "Invalid API key format. Expected: Bearer sk-..." | The header isn't Bearer, a space, then a key that starts with sk- |
Send the full key after Bearer and a space |
| "Invalid API key" | The value is not a valid key | Create a new key in Settings > API Keys and copy all of it. A key is shown only once |
| "API key has expired" | The key had an expiration date, and it has passed | Create a new key, with a later expiration date or none |
| "API key missing required scope: apps:execute" | The key lacks the scope the route needs (this message is listed for running a published app) | Create a key with the scope the route needs: workflows:execute or Full access to start runs, workflows:write to upload files, apps:execute to run published apps. A new key starts read-only |
- Fix: Follow the row for your message.
- Check:
GET /api/v1/mewith the same header returns your account. It works with any valid key and needs no extra scope.
Why does a run fail with 402 "Insufficient credits"?
- Cause: Your credit balance is lower than the run needs. The reply says how many credits the run needs, how many you have, and what each node costs:
{
"error": "Insufficient credits. Required: 10, Available: 3",
"insufficientCredits": true,
"requiredCredits": 10,
"availableCredits": 3,
"breakdown": [
{ "nodeId": "node-1", "nodeLabel": "Text to Image", "credits": 10 }
]
}
- Fix: Add credits, or move to a plan with more credits (see the pricing page), or lower the cost of the most expensive node in
breakdown, for example with a lower resolution or a shorter length. Runs started with an API key are paid by the key owner. - Check:
GET /api/v1/meshows the key's account and itscredits. Start the run again oncecreditscoversrequiredCredits.
Why do I get 403 "Forbidden"?
- Cause: The key has no permission for the resource it asked for. "Forbidden: Cannot resume execution you do not own" means the execution belongs to another account.
- Fix: Use a key from the account that owns the workflow or the execution.
/runworks on workflows you own. - Check:
GET /api/v1/meshows which account the key acts as.
Why do I get 404 "Workflow not found" or "Execution not found"?
- Cause: No workflow or execution exists with the id in the request.
- Fix: Copy the workflow id from
GET /api/v1/workflows, which lists your workflows with their ids, and the execution id from theexecutionIdin the202reply. To poll, puthttps://www.wireflow.aiin front of thepollpath: the path already starts with/api/v1, so joining it to the base URL repeats that part. - Check:
GET /api/v1/workflows/{id}/runreturns the workflow's inputs.
Why do I get 400 when I save or run a workflow?
- Cause: The request body is missing something or has the wrong structure. The message names it:
| Message or code | Cause | Fix |
|---|---|---|
| "Missing required fields: name, nodes, edges" | The workflow in the request lacks a name, nodes or edges |
Send all three |
| "At least one node must be provided" | nodes is empty |
Send at least one node |
| "All nodes must have an id" | A node has no id |
Give every node an id |
| "Node node-1 is missing model.name" | That node has no model.name |
Add model.name to the node the message names |
| "Workflow is not active" | The errors reference lists this message without more detail | Contact support with the X-Request-Id |
invalid_webhook |
The webhook block on a run is invalid. Its url must be https, with plain http only for localhost, 127.0.0.1 and *.localhost, and at most 2048 characters |
Fix the URL and run again. Nothing ran |
- Fix: Follow the row for your message.
- Check: Send the request again. A valid run request returns
202 Acceptedwith anexecutionId.
Why do I get 429 "Too many workflow executions. Please try again later."?
- Cause: You went over a rate limit. The
Retry-Afterheader says how many seconds to wait, and theretryAfterfield in the body is a Unix timestamp that matches theX-RateLimit-Resetheader. - Fix: Wait the number of seconds in
Retry-After, then retry with backoff. Some routes have their own caps, such as 20 requests per minute per API key for running a published app. The numbers are in limits for uploads, runs and the API. - Check:
X-RateLimit-Remainingon each response shows how many requests are left in the current window.
{
"error": "Too many workflow executions. Please try again later.",
"retryAfter": 1711036800
}
Why do I get 500 "An unexpected error occurred"?
- Cause: Something failed on Wireflow's side. A run can start even when the call that started it returns
500. - Fix: Before you retry a call that starts a run, check
GET /api/v1/workflows/{id}/executionsfor that run. Retry/runwith the sameIdempotency-Keyand it replays the original run, while a retry of/execute, or of/runwithout the same key, bills a second run. Other calls can be retried after a short delay. - Check: If the error persists, contact support with the
X-Request-Idfrom the response.
How do I retry a failed request without paying for the run twice?
Send an Idempotency-Key header with every /run request and reuse the same key on each retry: /run then replays the original run instead of billing a new one. Wait the Retry-After seconds on a 429, and back off between retries on a 500.
curl -X POST https://www.wireflow.ai/api/v1/workflows/YOUR_WORKFLOW_ID/run \
-H "Authorization: Bearer $WIREFLOW_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1042" \
-d '{"inputs": {"node-prompt": "A cat wearing a top hat"}}'
Send the same command, with the same key, to retry.
import { randomUUID } from 'node:crypto';
const url = 'https://www.wireflow.ai/api/v1/workflows/YOUR_WORKFLOW_ID/run';
const headers = {
Authorization: `Bearer ${process.env.WIREFLOW_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': randomUUID(), // one key per run, reused on every retry
};
const body = JSON.stringify({ inputs: { 'node-prompt': 'A cat wearing a top hat' } });
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
let res;
for (let attempt = 0; attempt < 4; attempt++) {
res = await fetch(url, { method: 'POST', headers, body });
if (res.status === 429) await sleep(Number(res.headers.get('Retry-After') || 5) * 1000);
else if (res.status >= 500) await sleep(2 ** attempt * 1000);
else break;
}
if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
const { data } = await res.json();
console.log(data.executionId);
import os
import time
import uuid
import requests
URL = "https://www.wireflow.ai/api/v1/workflows/YOUR_WORKFLOW_ID/run"
HEADERS = {
"Authorization": f"Bearer {os.environ['WIREFLOW_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()), # one key per run, reused on every retry
}
BODY = {"inputs": {"node-prompt": "A cat wearing a top hat"}}
for attempt in range(4):
res = requests.post(URL, headers=HEADERS, json=BODY)
if res.status_code == 429:
time.sleep(int(res.headers.get("Retry-After", "5")))
elif res.status_code >= 500:
time.sleep(2 ** attempt)
else:
break
res.raise_for_status()
print(res.json()["data"]["executionId"])
Why is my file upload refused?
- Cause: Uploads return their own codes. The common ones are
file_too_large(over the limit for the upload method),unsupported_type(not an accepted file type),SignatureDoesNotMatch(the PUT headers differ from the signed ones) andupload_not_found(unknownmediaId, the PUT never happened, or its 24 hours ran out). - Fix: Follow the row for your code in the upload error codes table. Uploads also need a key with the
workflows:writescope. - Check: A finished upload appears in
GET /api/v1/media.
Why did my run end as FAILED, CANCELLED or TIMEOUT?
- Cause: The request worked and returned
202, but the run itself stopped.FAILEDcomes with anerrormessage for a person to read.CANCELLEDandTIMEOUTmean the run stopped before it finished. - Fix: Read
error, correct the input or the workflow, and start a new run. Branch your code onstatus, never on the wording oferror, which can change. Files that finished generating before a run stopped are still charged. - Check: Poll the new run until its
statusisCOMPLETED. How to poll, or get a webhook instead, is in check when a run is finished.