Install
openclaw skills install @wiroai/wiro-aiGenerate images, video, speech, music, 3D and LLM output with Wiro AI models through the Wiro MCP server or REST API, including finding a model, checking its price, running it and collecting the result. Use when the user wants generative media or LLM calls through an API, or mentions Wiro, wiro.ai or a Wiro API key.
openclaw skills install @wiroai/wiro-aiWiro runs AI models for images, video, audio and speech, LLMs, 3D and more through one API. Each run creates a task. A task is billed to the project's prepaid wallet only if it succeeds.
search_models, get_model_schema, run_model and others): use them, they call the API below for you. Call get_account first to check the connection and the balance, and read get_playbook (topics such as models, workflows, agents, billing) before a multi-step job.https://api.wiro.ai/v1. The HTTP endpoints in steps 1 to 4 are all POST.Connecting the MCP server, if the user wants it:
https://mcp.wiro.ai/v1 (Streamable HTTP). The user signs in with the browser, or the client sends Authorization: Bearer YOUR_API_KEY (API Key Only project) or Bearer YOUR_API_KEY:YOUR_API_SECRET (Signature project). Claude Code: claude mcp add --transport http wiro https://mcp.wiro.ai/v1, then /mcp to sign in. If the Wiro plugin (wiroai/Wiro-Plugin) is installed, the server is already there: open /mcp, pick it and choose Authenticate.npx -y @wiro-ai/wiro-mcp (stdio, Node.js 20+) with WIRO_API_KEY, plus WIRO_API_SECRET for a Signature project, in the server's environment.owner/model in lowercase. run_model takes model and params (the fields from get_model_schema).WIRO_API_KEY, plus WIRO_API_SECRET for a Signature project. Never print, log or echo them. Never hard-code or commit them (keep .env files out of git). Never put them in browser or mobile app code: call Wiro from a server.x-api-key.x-api-key, x-nonce (a Unix timestamp or random integer) and x-signature, the hex HMAC-SHA256 of API_SECRET + NONCE keyed with API_KEY. Sign every request: compute the pair right before each call.NONCE=$(date +%s)
SIGNATURE=$(printf '%s' "${WIRO_API_SECRET}${NONCE}" \
| openssl dgst -sha256 -hmac "${WIRO_API_KEY}" | awk '{print $NF}')
# add to the curl call: -H "x-nonce: ${NONCE}" -H "x-signature: ${SIGNATURE}"
Authorization: Bearer YOUR_API_KEY, or Bearer YOUR_API_KEY:YOUR_API_SECRET for a Signature project.The examples below use API Key Only. For a Signature project, add the two headers.
curl -s -X POST "https://api.wiro.ai/v1/Tool/List" \
-H "Content-Type: application/json" -H "x-api-key: ${WIRO_API_KEY}" \
-d '{"search": "flux", "limit": "20", "summary": true, "hideworkflows": true}'
categories (such as ["text-to-video"]), slugowner, and start for paging. Or browse https://wiro.ai/models.cleanslugowner and cleanslugproject in each result are the {owner-slug}/{model-slug} you run.curl -s -X POST "https://api.wiro.ai/v1/Tool/Detail" \
-H "Content-Type: application/json" -H "x-api-key: ${WIRO_API_KEY}" \
-d '{"slugowner": "OWNER_SLUG", "slugproject": "MODEL_SLUG"}'
tool[0].parameters[].items[] lists the inputs: id (the field name to send), type and required, plus allowed options and defaults where the model sets them. Build the request from these ids.dynamicprice (in Tool/List and Tool/Detail) is an array of {inputs, price, priceMethod}, with price in USD. Use the entry whose inputs match the settings you will send; {} means one price for every setting. Parse it first if it arrives as a string.priceMethod: cpr per run, cpo per output file, cps per second of run time, cpt per token, cp-pixel per 1024x1024 tier of output, cp-audiosecondslength per second of input audio, cp-promptlength per prompt character, cp-outputVideoLength per second of output video, cp-realtimeturn per realtime turn, cp-readoutput reported by the model when it ends.dynamicprice: the model bills per second, and approximatelycost (from its average run time) is a rough estimate.pexit: "0") are billed. Failed runs, server errors, queue time and tasks cancelled before processing completes are not.curl -s -X POST "https://api.wiro.ai/v1/Run/{owner-slug}/{model-slug}" \
-H "Content-Type: application/json" -H "x-api-key: ${WIRO_API_KEY}" \
-d '{"prompt": "A futuristic city at sunset"}'
# {"result": true, "errors": [], "taskid": "...", "socketaccesstoken": "..."}
taskid and socketaccesstoken (the task token) right away. They are how you find the task again.multipart/form-data, for example -F "inputImage=@photo.jpg" -F "scale=4".fileinput takes it in {id}Url (inputImageUrl), and in multipart you send both fields with one left empty. A multifileinput takes comma-separated URLs in the field with Url before Multiple (inputDocumentUrlMultiple). A combinefileinput takes URLs in the field itself. URLs must be public http(s), redirects included.POST /File/Upload (multipart field file, up to 100 MB) and pass the returned url.callbackUrl gets a webhook when the task ends (see below).Poll Task/Detail with the task token or the task id:
curl -s -X POST "https://api.wiro.ai/v1/Task/Detail" \
-H "Content-Type: application/json" -H "x-api-key: ${WIRO_API_KEY}" \
-d '{"tasktoken": "TASK_TOKEN"}' # or -d '{"taskid": "TASK_ID"}'
tasklist[0]. Check every 3 seconds or so, less often for long jobs, until status is task_postprocess_end or task_cancel. Nothing else ends a task.task_queue, task_accept, task_preprocess_start, task_preprocess_end, task_assign, task_start, task_output (repeats), task_output_full, task_end, task_postprocess_start, task_postprocess_end. task_error is not terminal, and task_end comes before the outputs are ready.task_postprocess_end: pexit: "0" means success, anything else is a failure (and not billed).outputs[].url (with name and contenttype). LLM text is in debugoutput, or ordered in outputs[0].content.segments. The charge is totalcost, in USD.WebSocket: connect to wss://socket.wiro.ai/v1, send {"type": "task_info", "tasktoken": "TASK_TOKEN"} and read events until task_postprocess_end. Its success and exitCode (0 = success) give the outcome, and message holds the outputs. Realtime voice, text-to-speech and speech-to-text models also work over this socket: see https://wiro.ai/docs/websocket.
Webhook: with callbackUrl, Wiro POSTs the task as JSON when it ends, success or failure, so check pexit. Answer with a 2xx at once. It tries up to 3 times, 2 seconds apart, and does not follow redirects. Match the task id against your own records before you act on the payload. Webhooks go to public URLs; on a local machine, poll instead.
Sync: POST /Run/{owner-slug}/{model-slug}/sync starts the same billed task and holds the request for up to 40 minutes, then returns Task Detail JSON (check tasklist[0].pexit). Add ?stream=true for SSE events. A timeout returns HTTP 504 with taskid and socketaccesstoken, and the task keeps running. Training and realtime models use the other routes, not /sync.
wait_for_task, get_task, list_tasks). With no task id at all, check MCP list_tasks or get_account with recent_transactions, or ask the user to check their usage at https://wiro.ai/panel/billing, before you resend.run_model waits up to 45 seconds by default, then returns the running task with a nextAction (usually wait_for_task). Call that. Never call run_model again for the same job.POST /Task/Cancel with {"taskid": "TASK_ID"} while it is queued, POST /Task/Kill with {"taskid": "TASK_ID"} or {"socketaccesstoken": "TASK_TOKEN"} once it is running. It ends as task_cancel. MCP: cancel_task, kill_task.debugoutput and outputs[0].content. A chat model keeps context when you send the same session_id on every turn, if its parameters list session_id.https://llm.wiro.ai/v1: POST /chat/completions and POST /responses. Anthropic SDKs use the origin https://llm.wiro.ai (/v1/messages).Authorization: Bearer YOUR_API_KEY for API Key Only, Bearer YOUR_API_KEY:YOUR_API_SECRET for Signature.owner/model. GET /v1/models lists the gateway models; check capabilities.endpoints and supported_parameters before you rely on a feature. LLMs missing from that list still run through Run.messages on every request. Output is text only; make images, video and audio through Run.max_completion_tokens also covers reasoning tokens, so keep it at 512 or more.usage.cost.curl -s -X POST "https://llm.wiro.ai/v1/chat/completions" \
-H "Authorization: Bearer ${WIRO_API_KEY}" -H "Content-Type: application/json" \
-d '{"model": "owner/model", "max_completion_tokens": 512,
"messages": [{"role": "user", "content": "What is SSE?"}]}'
import OpenAI from "openai";
const { WIRO_API_KEY, WIRO_API_SECRET } = process.env;
const client = new OpenAI({
baseURL: "https://llm.wiro.ai/v1",
apiKey: WIRO_API_SECRET ? `${WIRO_API_KEY}:${WIRO_API_SECRET}` : WIRO_API_KEY,
});
const completion = await client.chat.completions.create({
model: "owner/model", // an id from GET /v1/models
max_completion_tokens: 512,
messages: [{ role: "user", content: "Hello" }],
});
console.log(completion.choices[0].message.content);
A workflow is a saved chain of model steps and built-in utility steps, with its own inputs and outputs. Start one with POST /Workflow/Run (slug is its full slug, input the input values); it returns a workflowtoken. Poll POST /Workflow/RunDetail with that token until status is completed, failed, stopped or cancelled. Each model step is billed like a normal run when it succeeds, and utility steps are not billed. The wallet must hold 0.50 USD per model step to start, and the expected cost is the sum of the step models' prices. A failed run can be resumed without paying again for finished steps. MCP: list_workflows, run_workflow, wait_for_workflow_run, resume_workflow_run. See https://wiro.ai/docs/workflows.
Wiro Agents are assistants that keep running on Wiro: they keep conversation memory, connect to outside services and use tools. You deploy one from a template (browse https://wiro.ai/agents) or build one from skills. Each agent runs on one of three monthly plans (Starter, Pro or Max) with a pool of credits, and every turn uses credits by the tokens its model consumes. Deploying through the API takes the plan price from the wallet at once, so quote it and get a clear yes first. MCP: list_agent_templates, deploy_agent (quotes first, and charges only when called again with confirm: true), send_agent_message. See https://wiro.ai/docs/agent-overview.
Check result first, then errors[].code. Do not rely on the HTTP status alone.
| Code | Meaning | What to do |
|---|---|---|
0 | Validation, missing parameter or server error | Fix the request; retry a server error with backoff |
1 | Model or task not found or not accessible | Check the slug, task id or token |
96 | Concurrency limit reached | No task was created and nothing was charged; retry after 2, 4, 8 s (up to 60 s, at most 8 tries) or queue |
97 | Insufficient balance | The user adds funds; a run needs at least 0.50 USD (10 USD for training models) |
98 | The model needs a signed-in account | Use authenticated credentials |
99 | Bearer token missing, invalid or expired | Check the credentials |
task_queue until task_postprocess_end or task_cancel, and tasks started on the website, by agents or by workflows count too.retry-after.