Hermosso API
Every studio tool over REST — image generation, editing, upscaling to 22K, photo-to-video. Authenticated with a key, billed from the credits your plan already includes.
Getting a key
API access is included with the Studio plan. Create a key under Billing → API keys. The key is shown once and never again — we store only a hash, so it cannot be recovered. If you lose one, revoke it and make another.
Authentication
curl https://hermosso.com/api/v1/me \ -H "Authorization: Bearer pm_live_…"
Entitlement is checked on every request rather than at key creation, so a subscription change takes effect immediately — and a plan set to cancel keeps working until the period it was paid for ends.
Billing
Requests draw on your plan's credits. There is no separate meter and no second invoice: a call costs exactly what the same action costs inside the app, because it runs the same code. credits_remaining comes back on every response so you can track spend without a second request.
Failed work is refunded automatically — when the provider reports a failure, and after thirty minutes for a job that never reports at all.
Endpoints
| Method | Path | What it does |
|---|---|---|
GET |
/api/v1/me |
Your account, credit balance and limits. The first call to make. |
POST |
/api/v1/images/generate |
Text to image across every engine.{ "prompt": "…", "model": "nano-banana-2", "aspectRatio": "3:4", "resolution": "2k", "count": 2 } |
POST |
/api/v1/images/edit |
Prompt-driven edit, with references or a mask.{ "sourceImageUrl": "https://…", "prompt": "…" } |
POST |
/api/v1/images/upscale |
Enlarge to 4K, 8K or 22K.{ "sourceImageUrl": "https://…", "mode": "max" } |
POST |
/api/v1/images/restore |
Repair, face-restore and colorize an old photo.{ "sourceImageUrl": "https://…" } |
POST |
/api/v1/images/remove-background |
Cut out to a transparent PNG.{ "sourceImageUrl": "https://…" } |
POST |
/api/v1/images/relight |
Relight a subject.{ "sourceImageUrl": "https://…", "prompt": "warm rim light from the left" } |
POST |
/api/v1/images/extend |
Outpaint beyond the frame.{ "sourceImageUrl": "https://…", "direction": "all" } |
POST |
/api/v1/images/variations |
Reimagine a shot several ways.{ "sourceImageUrl": "https://…", "count": 4 } |
POST |
/api/v1/videos/animate |
Photo to video.{ "sourceImageUrl": "https://…", "engine": "hailuo-h3-max", "audio": true } |
POST |
/api/v1/videos/generate |
Text to video.{ "prompt": "…", "engine": "hailuo-h3-max", "aspectRatio": "16:9", "audio": true } |
POST |
/api/v1/videos/upscale |
Upscale a clip.{ "sourceVideoUrl": "https://…", "target": "4k", "durationSeconds": 5 } |
GET |
/api/v1/jobs?image=1,2&video=7 |
Poll jobs by id. Up to 50 of each per call. |
A complete run
Generation is asynchronous — a request returns job ids straight away, and you poll until they finish.
# 1. start the work
curl -X POST https://hermosso.com/api/v1/images/generate \
-H "Authorization: Bearer pm_live_…" \
-H "Content-Type: application/json" \
-d '{"prompt":"A bright calm living room, oak floors, soft afternoon light",
"model":"nano-banana-2","aspectRatio":"3:4","resolution":"2k","count":2}'
# → 202
# {"jobs":[{"id":70,"kind":"image","status":"pending"},
# {"id":71,"kind":"image","status":"pending"}],
# "credits_remaining":59700}
# 2. poll until done
curl "https://hermosso.com/api/v1/jobs?image=70,71" \
-H "Authorization: Bearer pm_live_…"
# → {"jobs":[{"id":70,"kind":"image","status":"done","url":"https://…"}, …]}
Limits
- Five concurrent generations per account. A sixth returns
429 too_many_concurrent. Reading is never limited, so you can always poll to find out when a slot frees. - Fifty job ids per
/jobscall, per kind. - Ten active keys per account. Revoke one to make another.
Errors
Every failure returns the same envelope, so you can branch on code rather than parsing prose:
{ "error": { "code": "plan_required", "message": "…" } }
| Status | Code | Meaning |
|---|---|---|
401 | missing_key | No key on the request. Send it as Authorization: Bearer. |
401 | invalid_key | The key is unknown or has been revoked. |
403 | plan_required | The account is not on Studio, or its subscription has lapsed. |
402 | forbidden | Out of credits. |
429 | too_many_concurrent | Five generations are already in flight. Poll and retry. |
400 | invalid_json | The request body was not JSON. |
400 | bad_request | The body failed validation. The message names the field. |
Frequently asked
Does the API cost extra?
No. It draws on the credits your plan already includes, at the same price as the app.
Can I use the output commercially?
Yes — commercial usage rights are included with Pro and Studio.
What happens when my subscription ends?
Keys stop authenticating and return 403 plan_required. They are not deleted, so resubscribing brings the same keys back to life without changing your code.
Start building
API access is included with Studio. New accounts start with 750 free credits and no card, so you can try the tools in the app before wiring anything up.
See plans →