Content apps
Content apps are the focused jobs in the image and video Studios' Add menu — product photography, ad creative, remove background, UGC ads, avatars, motion graphics. Where a Studio turn is a conversation, a content app is one precise operation with exact inputs.
#Find an app and its inputs
The catalog is the Studio's own, and each app takes different inputs, so start by listing it. Every app comes with inputs — a JSON Schema of exactly what its body accepts — whether it's runnable over the API, what it returns, and its typical timing. Listing is free and instant.
curl "https://app.attria.io/api/v1/studio/apps?studio=image" \
-H "Authorization: Bearer $ATTRIA_API_KEY"const res = await fetch("https://app.attria.io/api/v1/studio/apps?studio=image", {
headers: {
Authorization: `Bearer ${process.env.ATTRIA_API_KEY}`,
},
});
const catalog = await res.json();import os, requests
res = requests.get(
"https://app.attria.io/api/v1/studio/apps?studio=image",
headers={
"Authorization": f"Bearer {os.environ['ATTRIA_API_KEY']}",
},
timeout=30,
)
catalog = res.json(){
"apps": [
{
"studio": "image",
"id": "remove-background",
"label": "Remove background",
"short_label": "Remove background",
"description": "Create a clean transparent version of the selected image.",
"examples": [
"Transparent PNG",
"Clean edges"
],
"group": "finish",
"kind": "utility",
"path": "/v1/studio/image/apps/remove-background",
"runnable": true,
"not_runnable_reason": null,
"returns": "assets",
"timing": "20–60 s",
"inputs": {
"type": "object",
"properties": {
"board_id": {
"type": "string",
"format": "uuid"
},
"source_asset_id": {
"type": "string",
"format": "uuid"
}
},
"required": [
"board_id",
"source_asset_id"
]
}
}
]
}#Run one
POST /v1/studio/{studio}/apps/{app} with that app's inputs — only those; anything else is refused. Apps that start from an image need a board_id, and their source images must already be on that board.
curl -X POST "https://app.attria.io/api/v1/studio/image/apps/product-photo" \
-H "Authorization: Bearer $ATTRIA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"board_id": "6f1c2d3e-4a5b-4c6d-9e7f-8a9b0c1d2e3f",
"product_asset_id": "9a2e3f4a-5b6c-4d7e-8f9a-0b1c2d3e4f5a",
"product": "A matte black insulated travel mug",
"direction": "Dawn café, soft window light, condensation detail",
"aspect": "4:5"
}'const res = await fetch("https://app.attria.io/api/v1/studio/image/apps/product-photo", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ATTRIA_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
board_id: "6f1c2d3e-4a5b-4c6d-9e7f-8a9b0c1d2e3f",
product_asset_id: "9a2e3f4a-5b6c-4d7e-8f9a-0b1c2d3e4f5a",
product: "A matte black insulated travel mug",
direction: "Dawn café, soft window light, condensation detail",
aspect: "4:5",
}),
});
const run = await res.json();import os, uuid, requests
res = requests.post(
"https://app.attria.io/api/v1/studio/image/apps/product-photo",
headers={
"Authorization": f"Bearer {os.environ['ATTRIA_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"board_id": "6f1c2d3e-4a5b-4c6d-9e7f-8a9b0c1d2e3f",
"product_asset_id": "9a2e3f4a-5b6c-4d7e-8f9a-0b1c2d3e4f5a",
"product": "A matte black insulated travel mug",
"direction": "Dawn café, soft window light, condensation detail",
"aspect": "4:5",
},
timeout=900, # a turn that waits can take minutes
)
run = res.json()| Kind | How it answers |
|---|---|
| Image apps | When the images are saved — usually 20–90 s — with assets (id, url, width, height). Without board_id, results go to the Library. |
| Video apps | In seconds, with 202, status: "building" and a job. The shot takes 1–3 minutes and is added to the end of the project's video. |
| Motion | Inside the request (1–4 minutes), as an editable composition. May answer needs_input when the brief is ambiguous — send a more specific prompt. |
#Checking on a video shot
A video app answers before the shot is filmed. To check on it, send the same request again with the same Idempotency-Key: the repeat reads the job and moves it forward — it never starts or charges a second shot. When status is complete, asset is the video.
A new key is a new shot. Keep the key you sent the first time for every check.
#Credits and refusals
Credits are reserved before a run and only what was made is charged; each result of a multi-result run is charged. Not enough credits is 402. Apps listed with runnable: false answer 422 with the reason — they need the Studio's own screen.
For open-ended work — “two promo images for our iced latte” — a Studio turn lets the director choose; use a content app when you know the exact operation.