This section as Markdown: View Download

Studio

Ask Wiro's creative agent for images, video, audio and more through the API, then collect every result it made.

Overview

Studio is Wiro's creative agent. You describe what you want, such as a product shot, a short video, a voice-over or a set of ad banners, and Studio picks suitable models from the Wiro catalog, runs them and replies with the results. It is the same Studio you use on wiro.ai.

The Studio API uses the message protocol of Agent Messaging on its own routes under /Studio/:

  1. Send a message with Message/Send and get its messageguid and agenttoken back at once.
  2. Follow the turn on the Agent WebSocket with the agenttoken, or poll Message/Detail until the turn ends.
  3. Collect the files. The reply lists them, and Studio/Tasks returns every model run Studio started for you, with its outputs and cost.

There is no agent guid to pass: every route talks to Studio. Studio is paid from your Wiro wallet, as described under Costs.

Authentication

Every /Studio/* route takes a project API key: x-api-key, plus x-nonce and x-signature for a project that uses signature authentication (see Authentication). A key acts as the person who created its project, in that project's workspace: a personal project works in the personal workspace and pays from the personal wallet, a team project works in the team and pays from the team wallet. For a team project, that person must still be a member of the team; otherwise every route answers HTTP 403 with You must be a member of this team to perform this action.

Sessions

A session is one conversation with its own memory. sessionkey names it, and "default" is used when you leave it out.

  • Studio conversations belong to the person who created the key's project. "default" is their main Studio chat on wiro.ai, and sessions started with a key appear in their Studio on wiro.ai, in the same workspace. Everyone who uses the same key shares these sessions.
  • Use a new session name for each piece of work, such as "bakery-banners", and keep using it for follow-ups such as "make it brighter": Studio remembers the conversation.
  • A name uses letters, digits, ., _, : and -, up to 128 characters, and can't end in -r followed by a number, such as -r2. Names that contain :cron: are reserved.
  • Capitals are fine and are kept, but a new name that differs only in capitals from one of your sessions is refused: use its exact name, or another name.
  • Message/Send and Message/SendForm check the name first, so a refused message runs nothing and costs nothing. Reading, renaming and deleting a session work with whatever name it already has.
  • The turns of one session run one at a time, in order: a second message waits in agent_queue until the turn before it ends. Different sessions run in parallel.

Costs

  • $10 to start a turn. Message/Send and Message/SendForm need at least $10 spendable in the wallet of the key's workspace. Below that, the message is refused with code 97 (Insufficient balance), and the response carries walletUsd, the balance, and minTopup, the minimum. Nothing is charged for a refused message. Reading messages, sessions and results is free.
  • What a turn costs. A turn's cost depends on the models Studio runs for it, and can be more than $10.
  • Chat. Each turn is charged for the tokens it used, at the chat model's rates in Studio/Status (credits per 1M tokens; 1 credit is $0.01). The reply shows the chat charge in tokencost, in credits: tokencost / 100 is the amount in USD.
  • Model runs. Each model run Studio starts is charged at that model's price when it succeeds. Failed and cancelled runs are not charged. Studio/Tasks shows each run's totalcost.
  • Charges are made within about a minute of the work finishing. Studio/Transactions lists them, and they also appear in the wallet's transactions.

POST /Studio/Status

Returns the wallet check and the chat models Studio can use. It settles your pending Studio charges first, so walletUsd is current. It takes no request fields.

Field Type Description
walletUsd number Spendable balance of the workspace wallet in USD.
needsTopup boolean true when walletUsd is below minTopup.
minTopup number The balance a turn needs to start: 10.
tokenRates object Chat model rates. default_model is the default chat model, and models is keyed by model slug: each entry has input_per_1m and output_per_1m (credits per 1M tokens), optional cached-input, cache-write and long-context rates, a label, and selectable: true when you can pick it with model.
agentModel.chatModel string The chat model a turn uses when you leave model out.
title string The agent's name.
status number Always 4.

The response also carries fields that Wiro's own apps use. Ignore the ones not listed here.

Response

{
  "result": true,
  "errors": [],
  "title": "Generative Media Agent",
  "status": 4,
  "walletUsd": 42.5,
  "needsTopup": false,
  "minTopup": 10,
  "tokenRates": {
    "default_model": "openai/gpt-5.6-sol",
    "models": {
      "openai/gpt-5.6-sol": {
        "input_per_1m": 625,
        "output_per_1m": 3750,
        "cached_input_per_1m": 62.5,
        "selectable": true,
        "label": "GPT-5.6 Sol"
      },
      "openai/gpt-5.4-mini": {
        "input_per_1m": 93.75,
        "output_per_1m": 562.5,
        "cached_input_per_1m": 9.375,
        "selectable": true,
        "label": "GPT-5.4 Mini"
      }
    }
  },
  "agentModel": {
    "chatModel": "openai/gpt-5.6-sol"
  }
}

POST /Studio/Message/Send

Sends a message to Studio. It returns at once with the turn's messageguid and agenttoken; the reply arrives on the WebSocket and in Message/Detail.

Parameter Type Required Description
message string Yes Your request, as you would type it in Studio. Say what the result is for, the look (subject, style, format or aspect ratio, length for video and audio) and how many results you want. Quote any exact text that must appear in an image or be spoken.
sessionkey string No The session to send to. Defaults to "default", the main Studio chat.
model string No The chat model for this turn: a slug whose selectable is true in Studio/Status. Leave it out to use Studio's default. Use the same model on every turn of a session; when it differs from the previous turn, the response includes modelChangeMarker, as in Agent Messaging.

To attach files, use Message/SendForm.

Response

{
  "result": true,
  "errors": [],
  "messageguid": "c3d4e5f6-a7b8-9012-cdef-345678901234",
  "agenttoken": "aB3xK9mR2pLqWzVn7tYhCd5sFgJkNb",
  "status": "agent_queue"
}

A wallet below the minimum gets:

{
  "result": false,
  "errors": [{ "code": 97, "message": "Insufficient balance", "time": 1761902400 }],
  "walletUsd": 6.4,
  "minTopup": 10
}

If a request times out, check Message/History before you send it again: each accepted message starts a paid turn.

POST /Studio/Message/SendForm

The same as Message/Send, as multipart/form-data, so you can attach files such as a product photo or a logo.

Parameter Type Required Description
message string Conditional Your request. Required unless at least one file is attached.
sessionkey string No The session to send to. Defaults to "default".
model string No As in Send.
attachments file No The files. Repeat the attachments field once per file; a single file can also be sent as attachment.
  • Up to 8 files per message, each up to about 100 MB. A larger file is refused with HTTP 413.
  • Accepted: images (jpg, jpeg, png, gif, webp, heic, svg), video (mp4, webm, mov), audio (mp3, wav, m4a, webm) and documents (pdf, txt, md, csv, doc, docx, xls, xlsx, ppt, pptx, epub). The file name needs its extension. Other files are refused with Uploaded file format invalid. Supported: ....
  • The message's attachments then lists each file with ordinal, mentionLabel, url, name, type and size.

The response is the same as Send's.

POST /Studio/Message/Detail

Returns one message and its reply. Poll it until status is agent_end, agent_error or agent_cancel, or follow the turn on the Agent WebSocket.

Parameter Type Required Description
messageguid string Conditional The message id from Send. Required unless agenttoken is given.
agenttoken string Conditional The turn token from Send.
sessionkey string No The message's session. Defaults to "default". A message from another session is Message not found.

Reply fields

Field Description
status agent_queue, agent_start, agent_output, then agent_end; or agent_error or agent_cancel.
content Your message.
response The final reply, set when the turn ends. Each file Studio made is on its own line as a public URL. After agent_error it reads Agent is temporarily unavailable. Please try again shortly., and after agent_cancel Request cancelled.
debugoutput The reply text so far while the turn runs, the final text after.
timeline The ordered reasoning, answer and tool blocks of the turn, as described in Agent Messaging. Tool labels are display names: show them, but do not parse them.
attachments The files you attached.
model The chat model that ran the turn.
inputtokens, outputtokens, cachereadtokens, cachewritetokens, totaltokens The turn's token use.
tokencost The chat charge in credits; tokencost / 100 is the amount in USD. Model runs are charged separately (see Studio/Tasks).
createdat, startedat, endedat Unix seconds.

Response

{
  "result": true,
  "errors": [],
  "data": {
    "guid": "c3d4e5f6-a7b8-9012-cdef-345678901234",
    "agenttoken": "aB3xK9mR2pLqWzVn7tYhCd5sFgJkNb",
    "content": "Two square banner images for my bakery's weekend sale, warm colors",
    "response": "Here are your two banners.\nhttps://cdn1.wiro.ai/7f3a9c2e/banner-1.png\nhttps://cdn1.wiro.ai/7f3a9c2e/banner-2.png",
    "debugoutput": "Here are your two banners.\nhttps://cdn1.wiro.ai/7f3a9c2e/banner-1.png\nhttps://cdn1.wiro.ai/7f3a9c2e/banner-2.png",
    "status": "agent_end",
    "metadata": {},
    "createdat": "1761902400",
    "startedat": "1761902401",
    "endedat": "1761902466",
    "attachments": [],
    "timeline": [],
    "model": "openai/gpt-5.6-sol",
    "inputtokens": 6400,
    "outputtokens": 610,
    "cachereadtokens": 0,
    "cachewritetokens": 0,
    "totaltokens": 7010,
    "tokencost": 7
  }
}

In this example the chat part cost 7 credits ($0.07). The two images are charged separately, as the model runs Studio started.

POST /Studio/Message/History

Returns the messages of one session, newest first.

Parameter Type Required Description
sessionkey string No The session. Defaults to "default".
limit number No Messages per page. Default 50, maximum 200.
before string No A message guid: returns the messages older than it, for the next page.

The response is { "result": true, "errors": [], "data": { "messages": [...], "count": 2, "hasmore": false } }. Each message has the reply fields of Message/Detail except startedat and endedat.

When a turn hands work to the background, its reply says so and ends early. The result arrives later as a new message in the same session, already finished: status is agent_end, content is empty and the text is in response. Read it with History, and find the files in Studio/Tasks.

POST /Studio/Message/Sessions

Lists your Studio sessions in the key's workspace, most recent first, including those started on wiro.ai. It takes no request fields.

{
  "result": true,
  "errors": [],
  "data": {
    "sessions": [
      {
        "sessionkey": "bakery-banners",
        "messagecount": 3,
        "updatedat": 1761902466,
        "lastmessage": "Make the second one brighter",
        "name": "Bakery banners"
      },
      {
        "sessionkey": "default",
        "messagecount": 0,
        "updatedat": null,
        "lastmessage": ""
      }
    ]
  }
}

messagecount counts turns, lastmessage is the last message (up to 500 characters), and name is the display name set with Message/RenameSession. "default" is always listed.

POST /Studio/Message/Cancel

Stops a turn that is queued or running.

Parameter Type Required Description
messageguid string Conditional The message id. Required unless agenttoken is given.
agenttoken string Conditional The turn token.
sessionkey string No The message's session. Defaults to "default".

Only a message in agent_queue, agent_start or agent_output can be cancelled; any other is refused with Message cannot be cancelled (status: <status>). Cancelling stops the reply, and the message moves to agent_cancel. Tokens already used are charged, and model runs that already started are billed when they succeed.

POST /Studio/Message/ClearSession

Deletes your messages in a session and starts Studio's memory of it fresh. The session keeps its display name.

Parameter Type Required Description
sessionkey string No The session. Defaults to "default", the main Studio chat.

Pending charges are settled first. Deleted messages cannot be restored, and they disappear from Studio on wiro.ai too. Files Studio made are not deleted.

POST /Studio/Message/DeleteSession

Deletes a session's messages and its display name.

Parameter Type Required Description
sessionkey string No The session. Defaults to "default".

To start a session over with a fresh memory, use Message/ClearSession.

POST /Studio/Message/RenameSession

Sets a session's display name, the name shown in the session list on wiro.ai.

Parameter Type Required Description
name string Yes The display name, up to 40 characters.
sessionkey string No The session. Defaults to "default".

POST /Studio/Tasks

Lists the model runs Studio started for you in the key's workspace, newest first, across all your Studio sessions, including those on wiro.ai.

Parameter Type Required Description
limit number No How many recent runs to return. Default 30, maximum 100.
Field Description
id The run's id.
status The task status, such as task_queue, task_start, task_postprocess_end or task_cancel (see Tasks).
success true for a run that finished successfully, false for a failed or cancelled run, null while it runs.
terminal true once the run has finished.
model { title, slugowner, slugproject }.
categories The model's categories. llm marks a text run.
parameters The inputs the run used, such as its prompt.
outputs The result files, each with name, contenttype, size and url. An LLM run returns its text as { "contenttype": "raw", "content": { "answer": [...] } }.
totalcost The run's price in USD, charged when it succeeds.
socketaccesstoken While the run is active, a token for the task WebSocket; empty once it finished.
createtime, starttime, endtime Unix seconds.
elapsedseconds How long the run took.

Response

{
  "result": true,
  "errors": [],
  "tasks": [
    {
      "id": "48211907",
      "status": "task_postprocess_end",
      "success": true,
      "terminal": true,
      "model": {
        "title": "Nano Banana Pro API: Create Mobile & Web Apps with Nano Banana",
        "slugowner": "google",
        "slugproject": "nano-banana-pro"
      },
      "categories": ["text-to-image", "image-to-image", "image-editing"],
      "parameters": { "prompt": "Square banner for a bakery weekend sale, warm colors", "resolution": "2K" },
      "outputs": [
        {
          "name": "banner-1.png",
          "contenttype": "image/png",
          "size": "1843212",
          "url": "https://cdn1.wiro.ai/7f3a9c2e/banner-1.png"
        }
      ],
      "totalcost": 0.14,
      "socketaccesstoken": "",
      "createtime": "1761902420",
      "starttime": "1761902421",
      "endtime": "1761902452",
      "elapsedseconds": 31
    }
  ]
}

Delete a finished run's files with Studio/Task/DeleteOutput.

POST /Studio/Transactions

Lists the wallet charges for your Studio use in the key's workspace, newest first.

Parameter Type Required Description
limit number No Default 50, maximum 200.

Each row has guid, type, amount, description, modelid, taskid, confirmed and time. A chat charge is described as Generative Media Agent LLM <model> (...) with its token counts, and a model run as Generative Media Agent media run.

POST /Studio/Task/DeleteOutput

Deletes the output and input files of one of your Studio runs once it has finished or was cancelled.

Parameter Type Required Description
id string Yes The run's id from Studio/Tasks.

A run that is not yours answers There is no task yet., and a run that has not finished answers Task must be completed or cancelled before deleting files.

Errors

Business errors come back with HTTP 200, result: false and an errors array, as everywhere in the Wiro API. These are the ones specific to Studio:

Message Code When
Insufficient balance 97 Send or SendForm with less than $10 spendable. The response adds walletUsd and minTopup.
Request parameter [message] required 0 Send without a message, or SendForm with neither a message nor a file.
Invalid model: <model> is not in the selectable model allowlist. 0 model is not a selectable slug in Studio/Status.
A Studio session name may contain only letters, digits, ".", "_", ":" and "-", at most 128 characters, and cannot end in "-r" followed by a number. Nothing was sent or charged. 0 Send or SendForm with a session name outside that rule.
You already have a Studio session with this name in different capitals. Use its exact name, or another name. Nothing was sent or charged. 0 Send or SendForm with a new session name that differs only in capitals from one of your sessions.
Reserved sessionkey 0 The session name contains :cron:.
Too many files (max 8) 0 SendForm with more than 8 files.
Uploaded file format invalid. Supported: ... 0 An attachment type that is not accepted.
Message not found 0 Detail or Cancel with an unknown message, or one from another session.
Message cannot be cancelled (status: <status>) 0 Cancel on a turn that has already ended.
Agent is temporarily unavailable. Please try again shortly. 0 Try again shortly.
You must be a member of this team to perform this action HTTP 403 A team project's key whose creator is no longer a member of the team.

Authentication errors are listed in the Error Reference.