Automatica API

Everything the app can do for you, from your own code: v1.

Getting started

Generate images and videos with AI models, read your library and run templates, with the same abilities the Automatica MCP server offers. Generations are paid for in credits and run asynchronously: start one, then poll it until it has finished.

  1. Create a token under Settings, API tokens, choosing what it may do and when it expires. The token is shown once.
  2. Call GET /models to see what you can generate with, then price a choice of settings with POST /generations/estimate.
  3. Start a generation, poll it until it has finished, and fetch the files from GET /artifacts/{id}/media.
Your first call
curl "https://automaticaapp.com/api/v1/account" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN"

Authentication

Every request carries your token as a bearer token in the Authorization header. A token has one or both abilities, and each endpoint below names the one it needs. Requests with the wrong ability answer 403; a revoked or expired token answers 401.

  • api:readRead your account, models, library and templates.
  • api:writeStart generations, run templates, create templates and upload media. Spends your credits.

A token can also carry the MCP ability, which lets MCP clients that cannot sign in with OAuth use the same token against the MCP server. Keep tokens out of source control and revoke any you no longer use.

Limits, paging and errors

Rate limits

Up to 120 requests a minute per account, 10 generations started a minute and 20 uploads a minute. A refused request answers 429 with a Retry-After header saying how many seconds to wait.

Paging

List endpoints take page and per_page and answer {data, meta}; meta.last_page says when you have everything. The default page holds 15 results and the largest 50.

Generations are asynchronous

Starting a generation answers at once with status processing. Poll it every 10 to 20 seconds; images usually finish within a minute and videos within a few. Credits are spent only when a generation succeeds, and the artifacts arrive on the generation once it has.

Idempotency

Send a UUID of your own when starting a generation. Retrying with the same key returns the generation it started (200) instead of starting another (201).

Errors

Every error is JSON with a message. Validation errors (422) add errors, a map of field names to the messages for each. Insufficient credits answer 402 with the credits required and available.

Error body

FieldTypeDescription
message*string
errorsobjectOn 422 only: field name to the messages for it.

Account

Your plan and credits.

get/openapi.json

This document

Request
curl "https://automaticaapp.com/api/v1/openapi.json"

Responses

  • 200objectThe OpenAPI 3.1 document.
get/accountapi:read

Your plan and credits

balance is what you hold, reserved is held by generations still in progress, and available is what a new generation can spend.

Request
curl "https://automaticaapp.com/api/v1/account" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN"
Response 200
{
  "username": "ada",
  "plan": "Creator",
  "credits": {
    "balance": 1200,
    "reserved": 8,
    "available": 1192
  }
}

Responses

  • 200AccountYour account.
  • 201ErrorNo valid token was sent.
  • 202ErrorThe token lacks the scope this call needs, or the email address is unverified.
  • 203ErrorThe per-minute request cap was reached. Retry-After says when to try again.

Models

The models you can generate with, their settings and prices.

get/modelsapi:read

List the models you can generate with

price is in credits: per is the unit one rate buys and from/to are the cheapest and dearest rates the settings can select. A model that takes media may name an edit_model or image_to_video_model to use when you attach an image or video.

Parameters

NameInTypeDescription
typequery"image" | "video"Only models that produce this kind of media.
Request
curl "https://automaticaapp.com/api/v1/models" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN"

Responses

  • 200objectThe models, unpaginated.
  • 422Errortype is not image or video.
  • 423ErrorNo valid token was sent.
  • 424ErrorThe token lacks the scope this call needs, or the email address is unverified.
  • 425ErrorThe per-minute request cap was reached. Retry-After says when to try again.
get/models/{model}api:read

A model with its settings and prices

settings lists each setting by field name with its options or range and default. pricing.options pairs each combination of the settings that affect price with its rate in credits; the total also multiplies by the number of outputs.

Parameters

NameInTypeDescription
model*pathstringA model key from the list, including an edit_model or image_to_video_model key.
Request
curl "https://automaticaapp.com/api/v1/models/{model}" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN"

Responses

  • 200ModelDetailThe model.
  • 404ErrorNo such model, or it has no active price.
  • 405ErrorNo valid token was sent.
  • 406ErrorThe token lacks the scope this call needs, or the email address is unverified.
  • 407ErrorThe per-minute request cap was reached. Retry-After says when to try again.

Generations

Start generations and follow them to the end.

post/generations/estimateapi:read

Price a generation before starting it

Nothing is generated or charged. For a model that edits an input video, give artifact_id or upload_id so the price uses that video's duration.

Request body

FieldTypeDescription
model*stringA model key from GET /models.
settingsobjectSetting values keyed by the field names GET /models/{model} returns.
artifact_iduuidAn input video from your library, for video edits.
upload_iduuidAn input video from your uploads, instead of artifact_id.
Request
curl -X POST "https://automaticaapp.com/api/v1/generations/estimate" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"fal-veo-3.1","settings":{"duration":"4s","resolution":"720p","generate_audio":false}}'
Response 200
{
  "credits": 40,
  "outputs": 1,
  "duration_seconds": 4,
  "available_credits": 1192,
  "affordable": true
}

Responses

  • 200EstimateThe price against your credits.
  • 422ErrorUnknown model (errors.model), unknown or unpriced settings (errors.settings), or an unusable input video.
  • 423ErrorNo valid token was sent.
  • 424ErrorThe token lacks the scope this call needs, or the email address is unverified.
  • 425ErrorThe per-minute request cap was reached. Retry-After says when to try again.
post/generationsapi:write

Start a generation

Spends credits when it succeeds. The answer has status processing: poll GET /generations/{generation} for the outcome rather than calling this again. Images usually finish within a minute and videos within a few. Up to 10 generations may be started a minute.

Request body

FieldTypeDescription
model*stringA model key from GET /models, or an edit_model / image_to_video_model key when attaching media.
prompt*string
settingsobjectSetting values keyed by field name; anything left out uses the default.
media_inputsarray<MediaReference>Each with a slot.
idempotency_keyuuid
Request
curl -X POST "https://automaticaapp.com/api/v1/generations" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"fal-flux-pro","prompt":"A copper kettle on a slate worktop, morning light","settings":{"num_images":2},"idempotency_key":"6f9619ff-8b86-4d01-b42d-00cf4fc964ff"}'
Response 200
{
  "id": "4c1b7e52-2a9f-4d3b-8e6a-1f2c3d4e5f60",
  "status": "processing",
  "model": "fal-flux-pro",
  "prompt": "A copper kettle on a slate worktop, morning light",
  "settings": {
    "num_images": 2
  },
  "outputs": 2,
  "cost": 8,
  "created_at": "2026-10-10T09:12:44+00:00"
}

Responses

  • 200GenerationThe idempotency key was seen before: the generation it started.
  • 201GenerationThe generation started.
  • 401ErrorNo valid token was sent.
  • 402InsufficientCreditsNot enough credits.
  • 403ErrorThe token lacks the scope this call needs, or the email address is unverified.
  • 422ErrorValidation failed: errors.model, errors.settings, errors.media_inputs or errors.idempotency_key say why.
  • 429ErrorToo many generations started this minute, or too many requests. Retry-After says when to try again.
get/generations/{generation}api:read

Check on a generation

status is processing until it is over; then succeeded with its artifacts, failed or moderated with error saying why, or cancelled. Only a generation that succeeded is charged. Poll every 10 to 20 seconds.

Parameters

NameInTypeDescription
generation*pathuuidThe generation id.
Request
curl "https://automaticaapp.com/api/v1/generations/{generation}" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN"
Response 200
{
  "id": "4c1b7e52-2a9f-4d3b-8e6a-1f2c3d4e5f60",
  "status": "succeeded",
  "model": "fal-flux-pro",
  "prompt": "A copper kettle on a slate worktop, morning light",
  "settings": {
    "num_images": 2
  },
  "outputs": 2,
  "cost": 8,
  "created_at": "2026-10-10T09:12:44+00:00",
  "finished_at": "2026-10-10T09:13:20+00:00",
  "artifacts": [
    {
      "id": "9d2f7a8e-5a0b-4c7e-9a2c-0f1d4e6b8c21",
      "type": "image",
      "model": "fal-flux-pro",
      "prompt": "A copper kettle on a slate worktop, morning light",
      "creator": "ada",
      "width": 1024,
      "height": 768,
      "created_at": "2026-10-10T09:12:44+00:00",
      "app_url": "https://automatica.example/artifacts?artifact=9d2f7a8e-5a0b-4c7e-9a2c-0f1d4e6b8c21"
    }
  ]
}

Responses

  • 200GenerationThe generation.
  • 404ErrorNot one of your generations.
  • 405ErrorNo valid token was sent.
  • 406ErrorThe token lacks the scope this call needs, or the email address is unverified.
  • 407ErrorThe per-minute request cap was reached. Retry-After says when to try again.

Artifacts

The images and videos in your library.

get/artifactsapi:read

List or search your library

Everything you generated plus anything you saved from other people. search matches by meaning and keyword and ranks by relevance; without it, results are newest first. prompt is cut short here and missing for artifacts made from someone else's template.

Parameters

NameInTypeDescription
searchquerystringWhat the artifact shows, in plain words.
typequery"image" | "video"Only this kind of media.
modelquerystringOnly artifacts generated with this model key.
ownershipquery"mine" | "imported"mine for what you generated, imported for what you saved from others.
likedquerybooleanOnly artifacts you liked.
sortquery"newest" | "oldest"Ignored when searching. Default "newest".
pagequeryintegerPage number, from 1. Default 1.
per_pagequeryintegerResults per page. Default 15.
Request
curl "https://automaticaapp.com/api/v1/artifacts" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN"
Response 200
{
  "data": [
    {
      "id": "9d2f7a8e-5a0b-4c7e-9a2c-0f1d4e6b8c21",
      "type": "image",
      "model": "fal-flux-pro",
      "prompt": "A copper kettle on a slate worktop, morning light",
      "creator": "ada",
      "width": 1024,
      "height": 768,
      "created_at": "2026-10-10T09:12:44+00:00",
      "app_url": "https://automatica.example/artifacts?artifact=9d2f7a8e-5a0b-4c7e-9a2c-0f1d4e6b8c21"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 15,
    "total": 1,
    "last_page": 1
  }
}

Responses

  • 200objectA page of artifacts.
  • 422ErrorA filter or page parameter is invalid.
  • 423ErrorNo valid token was sent.
  • 424ErrorThe token lacks the scope this call needs, or the email address is unverified.
  • 425ErrorThe per-minute request cap was reached. Retry-After says when to try again.
get/artifacts/{artifact}api:read

One artifact with its prompt and settings

cost is the credits this output cost. prompt is missing when the artifact came from someone else's template; template names it and template_variables holds what was filled in.

Parameters

NameInTypeDescription
artifact*pathuuidThe artifact id.
Request
curl "https://automaticaapp.com/api/v1/artifacts/{artifact}" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN"
Response 200
{
  "id": "9d2f7a8e-5a0b-4c7e-9a2c-0f1d4e6b8c21",
  "type": "image",
  "model": "fal-flux-pro",
  "prompt": "A copper kettle on a slate worktop, morning light",
  "creator": "ada",
  "width": 1024,
  "height": 768,
  "created_at": "2026-10-10T09:12:44+00:00",
  "app_url": "https://automatica.example/artifacts?artifact=9d2f7a8e-5a0b-4c7e-9a2c-0f1d4e6b8c21",
  "settings": {
    "num_images": 2
  },
  "mime_type": "image/png",
  "cost": 4,
  "can_create_template": true
}

Responses

  • 200ArtifactDetailThe artifact.
  • 404ErrorNot in your library.
  • 405ErrorNo valid token was sent.
  • 406ErrorThe token lacks the scope this call needs, or the email address is unverified.
  • 407ErrorThe per-minute request cap was reached. Retry-After says when to try again.
get/artifacts/{artifact}/mediaapi:read

Temporary links to the file and its preview

download_url serves the original with a download disposition and preview_url a small image (a video's first frame). Both expire at expires_at: use them straight away and call again for new ones. preview_url is null until the preview has been made.

Parameters

NameInTypeDescription
artifact*pathuuidThe artifact id.
Request
curl "https://automaticaapp.com/api/v1/artifacts/{artifact}/media" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN"
Response 200
{
  "id": "9d2f7a8e-5a0b-4c7e-9a2c-0f1d4e6b8c21",
  "type": "image",
  "mime_type": "image/png",
  "bytes": 482133,
  "width": 1024,
  "height": 768,
  "duration_ms": null,
  "download_url": "https://storage.example/artifacts/9d2f7a8e.png?X-Amz-Signature=...",
  "preview_url": "https://storage.example/thumbnails/9d2f7a8e.webp?X-Amz-Signature=...",
  "expires_at": "2026-10-10T09:43:20+00:00"
}

Responses

  • 200MediaLinksThe links.
  • 404ErrorNot in your library.
  • 405ErrorNo valid token was sent.
  • 406ErrorThe token lacks the scope this call needs, or the email address is unverified.
  • 407ErrorThe per-minute request cap was reached. Retry-After says when to try again.
get/artifacts/{artifact}/downloadapi:read

Download the file

Redirects to a temporary link for the original, so `curl -L -o out.png` saves it in one call.

Parameters

NameInTypeDescription
artifact*pathuuidThe artifact id.
Request
curl "https://automaticaapp.com/api/v1/artifacts/{artifact}/download" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN"

Responses

  • 302Redirect to the file.
  • 404ErrorNot in your library.
  • 405ErrorNo valid token was sent.
  • 406ErrorThe token lacks the scope this call needs, or the email address is unverified.
  • 407ErrorThe per-minute request cap was reached. Retry-After says when to try again.

Templates

Prompt templates in your library and on Explore.

get/templatesapi:read

List or search templates

scope library (the default) is your own templates, drafts included, plus those you saved; scope explore is everything published to Explore. runnable is false for an unfinished draft.

Parameters

NameInTypeDescription
scopequery"library" | "explore"Which templates. Default "library".
searchquerystringWhat the template is for, in plain words.
modelquerystringOnly templates built on this model key.
ownershipquery"mine" | "imported"Library only: mine for templates you created, imported for ones you saved.
viewquery"top" | "rising" | "recent"Explore only: the order when not searching. Default "top".
pagequeryintegerPage number, from 1. Default 1.
per_pagequeryintegerResults per page. Default 15.
Request
curl "https://automaticaapp.com/api/v1/templates" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN"

Responses

  • 200objectA page of templates.
  • 422ErrorA filter or page parameter is invalid.
  • 423ErrorNo valid token was sent.
  • 424ErrorThe token lacks the scope this call needs, or the email address is unverified.
  • 425ErrorThe per-minute request cap was reached. Retry-After says when to try again.
post/templatesapi:write

Save a template to your library

Base it on one of your own generations with artifact_id, which copies that generation's model, settings, prompt and attached media, or describe it from scratch with model, settings and prompt. Mark each blank in the prompt as {{id}} and declare it in variables under the same id. The template stays private until you publish it on the site. Nothing is generated or charged.

Request body

FieldTypeDescription
title*string
descriptionstring
artifact_iduuidOne of your own generations to base the template on.
modelstringRequired unless artifact_id is given.
settingsobject
promptstringWith each blank written as {{id}}. Required unless artifact_id is given.
variablesarray<object>
media_inputsarray<object>
Request
curl -X POST "https://automaticaapp.com/api/v1/templates" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Kettle shots","model":"fal-nano-banana-edit","settings":{"num_images":2},"prompt":"A {{subject}} on a {{surface}}, studio lit","variables":[{"id":"subject","label":"Subject","placeholder":"copper kettle"},{"id":"surface","label":"Surface"}],"media_inputs":[{"slot":"reference_images","label":"Your product"}]}'

Responses

  • 201TemplateDetailThe template.
  • 401ErrorNo valid token was sent.
  • 403ErrorThe generation was made with someone else's prompt.
  • 422ErrorValidation failed: errors.variables, errors.model, errors.settings, errors.media_inputs or errors.artifact_id say why.
  • 429ErrorThe per-minute request cap was reached. Retry-After says when to try again.
get/templates/{template}api:read

What a template asks you to fill in

variables are its text blanks and media_inputs the images or videos it asks for; keep their ids, a run is keyed by them. prompt and settings are returned only to the template's creator. cost is the credits one run spends; it is missing when the price depends on the input video.

Parameters

NameInTypeDescription
template*pathuuidThe template id.
Request
curl "https://automaticaapp.com/api/v1/templates/{template}" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN"
Response 200
{
  "id": "2b7e1f4a-9c3d-4e5f-8a6b-7c8d9e0f1a2b",
  "title": "Studio product shot",
  "model": "fal-nano-banana-edit",
  "creator": "grace",
  "is_owner": false,
  "in_library": false,
  "runnable": true,
  "app_url": "https://automatica.example/explore/templates?template=2b7e1f4a-9c3d-4e5f-8a6b-7c8d9e0f1a2b",
  "variables": [
    {
      "id": "subject",
      "label": "Subject",
      "placeholder": "A teapot"
    }
  ],
  "media_inputs": [
    {
      "id": "7f3a2b1c-4d5e-4f60-8a1b-2c3d4e5f6a7b",
      "slot": "reference_images",
      "label": "Your product",
      "description": null
    }
  ],
  "cost": 6
}

Responses

  • 200TemplateDetailThe template.
  • 404ErrorNot in your library and not published.
  • 405ErrorNo valid token was sent.
  • 406ErrorThe token lacks the scope this call needs, or the email address is unverified.
  • 407ErrorThe per-minute request cap was reached. Retry-After says when to try again.
post/templates/{template}/runsapi:write

Run a template

Spends the credits GET /templates/{template} reports as cost. variables takes a value for every variable keyed by id; media takes an artifact_id or upload_id for every media input keyed by its id. The prompt is filled in on the server, so a template can be run without seeing it. Poll GET /generations/{generation} for the outcome.

Parameters

NameInTypeDescription
template*pathuuidThe template id.

Request body

FieldTypeDescription
variablesobjectA value for each variable, keyed by its id.
mediaobjectFor each media input id, an artifact_id or upload_id.
idempotency_keyuuid
Request
curl -X POST "https://automaticaapp.com/api/v1/templates/{template}/runs" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"variables":{"subject":"a copper kettle"},"media":{"7f3a2b1c-4d5e-4f60-8a1b-2c3d4e5f6a7b":{"artifact_id":"9d2f7a8e-5a0b-4c7e-9a2c-0f1d4e6b8c21"}},"idempotency_key":"6f9619ff-8b86-4d01-b42d-00cf4fc964ff"}'

Responses

  • 200GenerationThe idempotency key was seen before: the generation it started.
  • 201GenerationThe generation started.
  • 401ErrorNo valid token was sent.
  • 402InsufficientCreditsNot enough credits.
  • 403ErrorThe token lacks the scope this call needs, or the email address is unverified.
  • 404ErrorNot in your library and not published.
  • 409ErrorThe template is still a draft.
  • 422ErrorValidation failed: errors.variables or errors.media say what is missing or unknown.
  • 429ErrorToo many generations started this minute, or too many requests.

Uploads

Reference images and videos for generations.

get/uploadsapi:read

List your uploads

Parameters

NameInTypeDescription
typequery"image" | "video"Only this kind of media.
pagequeryintegerPage number, from 1. Default 1.
per_pagequeryintegerResults per page. Default 15.
Request
curl "https://automaticaapp.com/api/v1/uploads" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN"

Responses

  • 200objectA page of uploads.
  • 422ErrorA filter or page parameter is invalid.
  • 423ErrorNo valid token was sent.
  • 424ErrorThe token lacks the scope this call needs, or the email address is unverified.
  • 425ErrorThe per-minute request cap was reached. Retry-After says when to try again.
post/uploadsapi:write

Upload a reference image or video

multipart/form-data with one file field. Images (jpeg, png, webp) up to 10 MB and videos (mp4, mov, webm, avi) up to 200 MB. Use the returned id as upload_id in a generation's media_inputs or a template run's media. The upload appears on My Uploads and stays until you delete it. Up to 20 uploads a minute.

Request
curl -X POST "https://automaticaapp.com/api/v1/uploads" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN" \
  -F "file=@reference.png"
Response 201
{
  "id": "c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f",
  "type": "image",
  "mime_type": "image/png",
  "bytes": 204800,
  "width": 1024,
  "height": 1024,
  "created_at": "2026-10-10T09:12:44+00:00"
}

Responses

  • 200UploadThe same bytes were uploaded before: the existing upload.
  • 201UploadThe upload.
  • 401ErrorNo valid token was sent.
  • 403ErrorThe token lacks the scope this call needs, or the email address is unverified.
  • 422ErrorThe file is missing, too large or not a supported type.
  • 429ErrorToo many uploads this minute, or too many requests.
get/uploads/{upload}api:read

One upload

Parameters

NameInTypeDescription
upload*pathuuidThe upload id.
Request
curl "https://automaticaapp.com/api/v1/uploads/{upload}" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN"

Responses

  • 200UploadThe upload.
  • 404ErrorNot one of your uploads.
  • 405ErrorNo valid token was sent.
  • 406ErrorThe token lacks the scope this call needs, or the email address is unverified.
  • 407ErrorThe per-minute request cap was reached. Retry-After says when to try again.
delete/uploads/{upload}api:write

Delete an upload

Refused while the upload sits in the web generation form's tray.

Parameters

NameInTypeDescription
upload*pathuuidThe upload id.
Request
curl -X DELETE "https://automaticaapp.com/api/v1/uploads/{upload}" \
  -H "Authorization: Bearer $AUTOMATICA_TOKEN"

Responses

  • 204Deleted.
  • 404ErrorNot one of your uploads.
  • 422ErrorThe upload is in use in the web generation form.
  • 423ErrorNo valid token was sent.
  • 424ErrorThe token lacks the scope this call needs, or the email address is unverified.
  • 425ErrorThe per-minute request cap was reached. Retry-After says when to try again.

Webhooks

Register an HTTPS endpoint under Settings, Webhooks and Automatica posts these events to it when a generation finishes, signed with the endpoint's secret.

generation.succeeded

A generation finished with its artifacts

Posted to each endpoint registered under Settings, Webhooks and subscribed to this event. The body is JSON; X-Automatica-Signature carries t=<unix time>,v1=<hex> where v1 is HMAC-SHA256 of "<t>.<raw body>" with the endpoint secret; recompute it over the exact bytes received and reject a t more than 300 seconds old. Answer 2xx within 5 seconds; anything else is retried with backoff up to 5 times, and an endpoint that keeps failing is switched off. Deliveries can repeat: event_id identifies the event.

Payload

FieldTypeDescription
event_id*uuidThe same for every endpoint and retry of one event.
event*"generation.succeeded" | "generation.failed" | "generation.moderated"
api_version*string
created_at*string
data*object
Payload
{
  "event_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
  "event": "generation.succeeded",
  "api_version": "v1",
  "created_at": "2026-10-10T09:13:20+00:00",
  "data": {
    "generation": {
      "id": "4c1b7e52-2a9f-4d3b-8e6a-1f2c3d4e5f60",
      "status": "succeeded",
      "model": "fal-flux-pro",
      "prompt": "A copper kettle on a slate worktop, morning light",
      "settings": {
        "num_images": 2
      },
      "outputs": 2,
      "cost": 8,
      "created_at": "2026-10-10T09:12:44+00:00",
      "finished_at": "2026-10-10T09:13:20+00:00",
      "artifacts": [
        {
          "id": "9d2f7a8e-5a0b-4c7e-9a2c-0f1d4e6b8c21",
          "type": "image",
          "model": "fal-flux-pro",
          "prompt": "A copper kettle on a slate worktop, morning light",
          "creator": "ada",
          "width": 1024,
          "height": 768,
          "created_at": "2026-10-10T09:12:44+00:00",
          "app_url": "https://automatica.example/artifacts?artifact=9d2f7a8e-5a0b-4c7e-9a2c-0f1d4e6b8c21",
          "download_url": "https://storage.example/artifacts/9d2f7a8e.png?X-Amz-Signature=...",
          "preview_url": "https://storage.example/thumbnails/9d2f7a8e.webp?X-Amz-Signature=...",
          "links_expire_at": "2026-10-10T10:13:20+00:00"
        }
      ]
    }
  }
}
generation.failed

A generation failed

Posted to each endpoint registered under Settings, Webhooks and subscribed to this event. The body is JSON; X-Automatica-Signature carries t=<unix time>,v1=<hex> where v1 is HMAC-SHA256 of "<t>.<raw body>" with the endpoint secret; recompute it over the exact bytes received and reject a t more than 300 seconds old. Answer 2xx within 5 seconds; anything else is retried with backoff up to 5 times, and an endpoint that keeps failing is switched off. Deliveries can repeat: event_id identifies the event.

Payload

FieldTypeDescription
event_id*uuidThe same for every endpoint and retry of one event.
event*"generation.succeeded" | "generation.failed" | "generation.moderated"
api_version*string
created_at*string
data*object
Payload
{
  "event_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
  "event": "generation.failed",
  "api_version": "v1",
  "created_at": "2026-10-10T09:13:20+00:00",
  "data": {
    "generation": {
      "id": "4c1b7e52-2a9f-4d3b-8e6a-1f2c3d4e5f60",
      "status": "failed",
      "model": "fal-flux-pro",
      "prompt": "A copper kettle on a slate worktop, morning light",
      "settings": {
        "num_images": 2
      },
      "outputs": 2,
      "cost": 8,
      "created_at": "2026-10-10T09:12:44+00:00",
      "finished_at": "2026-10-10T09:13:20+00:00",
      "error": "The provider is busy or unavailable right now. Try again in a few minutes."
    }
  }
}
generation.moderated

A generation was stopped by content moderation

Posted to each endpoint registered under Settings, Webhooks and subscribed to this event. The body is JSON; X-Automatica-Signature carries t=<unix time>,v1=<hex> where v1 is HMAC-SHA256 of "<t>.<raw body>" with the endpoint secret; recompute it over the exact bytes received and reject a t more than 300 seconds old. Answer 2xx within 5 seconds; anything else is retried with backoff up to 5 times, and an endpoint that keeps failing is switched off. Deliveries can repeat: event_id identifies the event.

Payload

FieldTypeDescription
event_id*uuidThe same for every endpoint and retry of one event.
event*"generation.succeeded" | "generation.failed" | "generation.moderated"
api_version*string
created_at*string
data*object
Payload
{
  "event_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
  "event": "generation.moderated",
  "api_version": "v1",
  "created_at": "2026-10-10T09:13:20+00:00",
  "data": {
    "generation": {
      "id": "4c1b7e52-2a9f-4d3b-8e6a-1f2c3d4e5f60",
      "status": "moderated",
      "model": "fal-flux-pro",
      "prompt": "A copper kettle on a slate worktop, morning light",
      "settings": {
        "num_images": 2
      },
      "outputs": 2,
      "cost": 8,
      "created_at": "2026-10-10T09:12:44+00:00",
      "finished_at": "2026-10-10T09:13:20+00:00",
      "error": "The provider is busy or unavailable right now. Try again in a few minutes."
    }
  }
}