Your recipes, workflows and skills
Run the recipes, canvas workflows and Poppie skills you saved on popnow.ai from the REST API or from ChatGPT and Claude. List them, pass your own files, cap the price and follow each run.
Anything you save on popnow.ai can be run from your own code or from a chat:
- a recipe: a result you liked, saved from Studio with Save as recipe (model, prompt, settings, look and the files it used);
- a canvas workflow: a chain of steps saved from the canvas, where each step can use the earlier steps' results;
- a Poppie skill: instructions you wrote with Poppie, readable by another assistant.
They stay private. Only you, and the teams you share them with, can list or run them; there is no public catalog. Prompts of recipes a teammate shared are never returned, and the server assembles them at run time. A run is billed to whoever starts it, at the same prices as the website.
At a glance
| List | GET /api/v1/recipes (recipes and workflows), GET /api/v1/skills |
| Price one | GET /api/v1/recipes/{id} returns estimatedCredits for a run with the saved files |
| Run | POST /api/v1/recipes/{id}/run with an Idempotency-Key |
| Follow | GET /api/v1/recipes/runs/{runId}, then GET /api/v1/jobs/recordInfo for download links |
| In a chat | list_my_recipes, run_my_recipe, get_recipe_run, list_my_skills, use_my_skill over MCP |
| IDs and code | Developer console → Recipes & skills lists every item with its ID and ready-to-run code |
Find what you can run
curl "https://api.popnow.ai/api/v1/recipes?kind=recipe" \
-H "Authorization: Bearer $POPNOW_API_KEY"Leave out kind to get both recipes and workflows. Your own items come first, then the ones shared with a team you belong to (mine: false, with teamId). Each item lists the inputs a run takes:
{
"code": 200,
"msg": "success",
"data": {
"items": [
{
"id": "svd_01jbq8x4m2c7d9f3h5k6n8p0rt",
"kind": "recipe",
"name": "Weekly post",
"mine": true,
"media": "image",
"inputs": [
{ "id": "image_urls", "label": "Product", "media": "image", "multiple": false, "required": false },
{ "id": "prompt", "label": "Prompt", "media": "text", "multiple": false, "required": false }
],
"steps": 1,
"estimatedCredits": null,
"updatedAt": "2026-10-21T09:12:00Z"
}
]
}
}estimatedCredits is null in the list. Read one item to get the current price of a run with the saved files:
curl https://api.popnow.ai/api/v1/recipes/svd_01jbq8x4m2c7d9f3h5k6n8p0rt \
-H "Authorization: Bearer $POPNOW_API_KEY"Run it
curl https://api.popnow.ai/api/v1/recipes/svd_01jbq8x4m2c7d9f3h5k6n8p0rt/run \
-H "Authorization: Bearer $POPNOW_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"inputs":{"image_urls":"https://example.com/your-photo.jpg"},"count":2,"maxCredits":200}'{
"code": 200,
"msg": "success",
"data": { "runId": "sfg_01jbq9a3d5f7g9h2k4m6n8p0qs", "estimatedCredits": 96, "steps": 2 }
}inputsmaps an input ID to a file reference, a list of references, or text. Inputs you leave out use the files saved with the recipe, so{}reruns it exactly as saved.count(1–4, recipes only) makes several pieces in one run. Workflows always run once.maxCreditsis the most the run may cost. If the current price is higher, nothing starts and you get409withreason: price_changedand the newestimatedCredits. Without it, the run starts at the quoted price and never spends more than that.Idempotency-Keyis required. Sending the same key again returns the same run instead of starting a second one.
What the inputs are
| Input IDs | Accepts | |
|---|---|---|
| Recipe | The model's file fields saved with it, such as image_urls, first_frame_url or refs, plus prompt to replace the saved prompt | Files: popnow://g/<job>/<n> (an earlier result), popnow://f/<file> (an upload), popnow://a/<asset> (an API asset) or an https URL. Text: plain text |
| Workflow | in1, in2 … in the order the list shows them; text inputs fill a step that has no prompt of its own | The same |
A field that takes one file gets the first reference; a field that takes several gets them all. An input ID the item does not have, or a value of the wrong shape, returns 400 with param set to inputs.<id>.
Follow a run
curl https://api.popnow.ai/api/v1/recipes/runs/sfg_01jbq9a3d5f7g9h2k4m6n8p0qs \
-H "Authorization: Bearer $POPNOW_API_KEY"{
"code": 200,
"msg": "success",
"data": {
"runId": "sfg_01jbq9a3d5f7g9h2k4m6n8p0qs",
"state": "done",
"spentCredits": 96,
"estimatedCredits": 96,
"items": [
{ "stepId": "r1", "state": "succeeded", "jobId": "job_01jbq9a6v8w0x2y4z6a8b0c2d4", "uri": "popnow://g/job_01jbq9a6v8w0x2y4z6a8b0c2d4/0" },
{ "stepId": "r2", "state": "succeeded", "jobId": "job_01jbq9a6v8w0x2y4z6a8b0c2d6", "uri": "popnow://g/job_01jbq9a6v8w0x2y4z6a8b0c2d6/0" }
]
}
}state is draft, running, paused, done, stopped or failed; poll every few seconds until it is no longer draft or running. Each item is one task (r1, r2 … for a recipe, the workflow's own step IDs for a workflow): uri is a stable reference to its first result that you can pass to another run, and GET /api/v1/jobs/recordInfo?taskId=<jobId> gives the download links and full details. A task that fails is refunded like any other task.
import os, time, uuid, requests
BASE = "https://api.popnow.ai/api/v1"
headers = {"Authorization": f"Bearer {os.environ['POPNOW_API_KEY']}"}
started = requests.post(
f"{BASE}/recipes/svd_01jbq8x4m2c7d9f3h5k6n8p0rt/run",
headers={**headers, "Idempotency-Key": str(uuid.uuid4())},
json={"inputs": {"image_urls": "https://example.com/your-photo.jpg"}, "maxCredits": 200},
).json()
run_id = started["data"]["runId"]
while True:
time.sleep(5)
run = requests.get(f"{BASE}/recipes/runs/{run_id}", headers=headers).json()["data"]
if run["state"] not in ("draft", "running"):
break
for item in run["items"]:
if item.get("jobId"):
task = requests.get(f"{BASE}/jobs/recordInfo", params={"taskId": item["jobId"]}, headers=headers).json()["data"]
print(item["stepId"], task["state"], (task.get("output") or {}).get("assets", [{}])[0].get("url"))Skills
curl https://api.popnow.ai/api/v1/skills/skl_01jbpz7c9e1g3j5m7q9s1v3x5z \
-H "Authorization: Bearer $POPNOW_API_KEY"GET /api/v1/skills lists your skills and the ones shared with your teams; GET /api/v1/skills/{id} adds body, the skill's instructions as Markdown, so another assistant can follow them with PopNow's tools. A team skill shared as use only (shareMode: "use") has no body: it can be used in PopNow, but its steps stay hidden.
In ChatGPT and Claude
Once PopNow is connected as an MCP server, the assistant can find and run what you saved when you ask in plain words, for example “run my recipe Weekly post with this photo”.
| Tool | What it does | Parameters |
|---|---|---|
list_my_recipes | Your recipes and workflows, with their inputs | none |
run_my_recipe | Prices a run first; with max_credits it starts it | recipe_id (required), inputs (input ID → one popnow:// or https:// link, or text), count, max_credits |
get_recipe_run | A run's state and its results | run_id (required) |
list_my_skills | Your skills and your teams' skills | none |
use_my_skill | Returns a skill's instructions for the assistant to follow | skill_id (required) |
run_my_recipe without max_credits only quotes the price and spends nothing; the assistant asks you, then calls it again with the agreed amount. The same call repeated within 10 seconds starts only one run. Use-only team skills are not returned by use_my_skill.
Limits and errors
| Status | When |
|---|---|
400 | An unknown input ID or a value of the wrong shape (param is inputs.<id>) |
402 | Not enough credits for the quoted price |
403 | The API key has a model list or a spending limit; recipes run as a batch the key limits cannot follow, so use a key without them |
404 | The recipe, run or skill does not exist or is not shared with you |
409 | reason: price_changed (the current price is above your maxCredits), or the recipe's model was retired: open it on popnow.ai and save it again |
Can other people see or run my recipes?
No. Recipes, workflows and skills are visible only to you and to the teams you share them with on popnow.ai. There is no public catalog, no share link and no way to run someone else's item by guessing its ID: an item you cannot reach returns 404.
Who pays when I run a recipe my team shared?
You do. A run is billed to the account that starts it, at the same prices as the website, and the API response shows the quote before anything is spent. Team members can run a shared recipe but cannot read its prompt.
Do I need to upload my files again for each run?
No. Pass an https URL or a popnow:// reference from an earlier result, upload, or API asset. Inputs you leave out reuse the files saved with the recipe, so a run with {} repeats it exactly.
What happens when the model a recipe used is retired?
The run returns 409 and nothing is charged. Open the recipe on popnow.ai: the website picks the current model for the same job, and saving it again makes it runnable from the API.
Is there an SDK for recipes?
Not yet. The endpoints are plain JSON over HTTPS, so the curl and Python examples on this page, or any HTTP client, are all you need.

