Generations
Create a generation, follow it, and download the result.
A generation is one job: one photo in, one finished image out.
Create a generation
curl https://api.foodshot.ai/v1/generations \
-H "Authorization: Bearer $FOODSHOT_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 5f0c2b7e-9a4d-4c1b-8e3f-6d2a1b9c7e40" \
-d '{
"image_url": "https://docs.foodshot.ai/samples/dish.jpg",
"style_id": "pure-shot",
"metadata": { "dish_id": "d_456" }
}'| Field | What to send |
|---|---|
image_url or image_base64 | The photo: an https URL, or the file in base64. JPEG, PNG, WebP or HEIC. |
style_id | A style id from GET /v1/styles. |
instruction | Optional. A short note in plain words, such as Keep the blue bowl. See Instructions. |
aspect_ratio | Optional. 1:1 (default), 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9 or 21:9. |
resolution | Optional. 4k (default) or 2k. Both cost 1 credit. See the result sizes. |
format | Optional. jpeg (default) or png: the file type of the result. |
metadata | Optional. Up to 10 string pairs, such as your dish id. We send them back with the result. |
Send one of image_url or image_base64, and a style_id, an instruction or both.
The answer is 202 Accepted with the new generation, in queued status. It usually comes within seconds. Use a client timeout of 60 seconds.
Idempotency
Every create needs an Idempotency-Key header: one new UUID per photo.
- Retry with the same key and the same body. Within 24 hours you get the same generation back, and nothing is charged again.
- The same key with a different body gets
409 idempotency_conflict. - After a failed job, use a new key to try again.
Statuses
queued → processing → succeeded or failed
succeeded and failed are final. A failed job is refunded, and error.code says why.
Our objective is about 30-40 seconds once a job starts; it is an objective, not a promise, and 4K jobs usually take a little longer than 2K. Up to 5 jobs per account run at the same time; the others wait in your queue.
Get the result
The best way is a webhook. To poll instead, get the generation about 20 seconds after you created it, then every 5 seconds until it is final.
curl https://api.foodshot.ai/v1/generations/$GENERATION_ID \
-H "Authorization: Bearer $FOODSHOT_API_KEY"A succeeded generation, shortened:
{
"id": "gen_4Kq9xT2mVb7Zp1Ls8Hc3Rw",
"status": "succeeded",
"metadata": { "dish_id": "d_456" },
"output": {
"url": "https://api.foodshot.ai/v1/files/gen_4Kq9xT2mVb7Zp1Ls8Hc3Rw/image.jpg?exp=…&sig=…",
"content_type": "image/jpeg",
"width": 4096,
"height": 4096
},
"error": null
}The fields you need most:
output.urlis a link to the file. It needs no key and works for 24 hours; everyGETreturns a fresh one.output.content_typeisimage/jpegorimage/png. Name the file by it.error.codesays why a job failed. See Errors.metadatais what you sent.
Download the file from your server and keep your own copy: we delete it after 30 days. A download is cut off after 60 seconds, and an expired link answers 403 permission_denied: get the generation again for a fresh link. Every field is in the API reference.
To catch up after downtime, list your generations by status and created_gte.
Instructions
instruction is a short note in plain words, such as Keep the blue bowl or Make the background darker.
- With a
style_id, it adjusts the style. - Without a
style_id, it describes the whole look. Results are less predictable than with a style. - Don't use it to add food that isn't in the photo, or for personal information.