The Adobe Firefly API is official, and finding it is harder than calling it. Three names get mixed together: Adobe Firefly Services is the platform, Adobe Firefly API is what you integrate, Adobe Firefly Image 5 is the model that answers. Sorting them out leaves four steps: credentials, a token, one async request, one poll.

What the official names actually are

Adobe names the platform on its own guides page: Firefly Services includes Firefly APIs, Lightroom APIs, Photoshop APIs, and Content Tagging APIs. The page a search for adobe firefly api lands on is headed Adobe Firefly API - Firefly Services, and opens with The Adobe Firefly API makes it easy for you to integrate generative AI into your creative workflows.

That page also enumerates the platform’s ten APIs and names the credential Firefly Services Client ID and Client Secret, which is platform-level rather than per-model.

The model is named just as precisely: The Image5 model is Firefly's latest model and brings native 4 MP resolution plus Instruct Edit. Two mistakes are worth avoiding in tickets: the API is not Adobe Firefly Services API, and its name carries no version number. The Adobe Firefly Image topic hub holds the product-level picture.

Credentials come before code

The admin step in the Developer Console

Adobe states the prerequisite plainly: This tutorial assumes you have worked with your Adobe Representative and have the following: a Developer Console account and A project with Firefly API OAuth Server-to-Server credentials set up. The credential page is marked [Admins only]: search for Adobe Firefly API, click Create project, read the client ID, then select OAuth Server-to-Server and retrieve the client secret. If the product card is missing, Adobe says to Reach out to your Adobe liaison. Share the secret with developers rather than access tokens, which expire.

Exchanging credentials for an access token

Every request made to Firefly APIs must include an encrypted access token. You get one from the Adobe Identity Management System (IMS), server-side.

# Requires curl and jq.
export FIREFLY_CLIENT_ID=<your-client-id>
export FIREFLY_CLIENT_SECRET=<your-client-secret>

# 1. Exchange the Firefly Services credentials for an access token.
curl -s -X POST 'https://ims-na1.adobelogin.com/ims/token/v3' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=client_credentials' \
  -d "client_id=${FIREFLY_CLIENT_ID}" \
  -d "client_secret=${FIREFLY_CLIENT_SECRET}" \
  -d 'scope=openid,AdobeID,session,additional_info,read_organizations,firefly_api,ff_apis' \
  | jq -r .access_token > firefly-token.txt

# The documented response shape:
# {"access_token":"yourExampleTokenAsdf123","token_type":"bearer","expires_in":86399}

Each access token is valid for 24 hours, so a long-running worker refreshes rather than caching once at boot.

Sending your first generation request

Async is the only path left. On 2025-10-03 Adobe removed the deprecated non-synchronous versions with Please use the async versions of these APIs instead:, covering the v3 generate, similar-images, object-composite, expand and fill endpoints. A tutorial showing a bare synchronous call is out of date.

# 2. Call the async image generation endpoint.
curl -X POST 'https://firefly-api.adobe.io/v3/images/generate-async' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H "x-api-key: ${FIREFLY_CLIENT_ID}" \
  -H "Authorization: Bearer $(cat firefly-token.txt)" \
  -d '{
    "prompt": "a red kite over wet sand at low tide, wide shot",
    "numVariations": 1,
    "size": { "width": 2688, "height": 1536 },
    "promptBiasingLocaleCode": "en-US",
    "contentClass": "photo"
  }'

Fields the Image5 schema expects

Model selection now lives in the header, because Model selection is now at a higher level, in the header. In the body, numVariations replaces the old count field, contentClass separates photo from art, promptBiasingLocaleCode pins the prompt language, visualIntensity tunes the result, and negativePrompt removes what you do not want. modelSpecificPayload.prompt_reasoner takes quality or speed, and quality populates an altText field. Adobe scopes the three families on the same page: Custom Models Train subject or style models, Composite covers Object Composite, Adaptive Composite and Precise Composite, and Upscale adds User Assets Upsampler and Generated Image Upsampler.

Polling the job until it succeeds

Adobe documents five beats: request, receive a job ID that includes a URL, check the job, receive a result containing URLs, then retrieve the assets. The create call answers with a jobId, a statusUrl and a cancelUrl built on an id like urn:ff:jobs:eso851211:86ffe2ea-d765-4bd3-b2fd-568ca8fc36ac. you can use statusUrl and cancelUrl to get the latest status of your request or to cancel the request. Terminal states are succeeded and failed.

# 3. Poll the statusUrl from the previous response until it settles.
STATUS_URL='https://firefly-api.adobe.io/v3/status/urn:ff:jobs:eso851211:86ffe2ea-d765-4bd3-b2fd-568ca8fc36ac'

while true; do
  body=$(curl -s "${STATUS_URL}" \
    -H "x-api-key: ${FIREFLY_CLIENT_ID}" \
    -H "Authorization: Bearer $(cat firefly-token.txt)")
  state=$(printf '%s' "$body" | jq -r .status)
  if [ "$state" = 'succeeded' ] || [ "$state" = 'failed' ]; then
    printf '%s' "$body" | jq .
    break
  fi
  sleep 5
done

The Image5 migration is a breaking change

The old and new schemas are not compatible, and migration requires rewriting the request payload. Adobe calls it a major version upgrade with non-backwards-compatible changes, and warns that Payloads that do not conform to the new schema will be rejected by the API.

Adobe's official Firefly Image Model 5 expanded-frame demo: a flower-covered whale and an astronaut on red, with a cursor
Adobe
ChangeOld schemaNew schema
Variation countnnumVariations
Custom modelmodelIdcustomModelId — new semantics, not a remap
Aspect ratioaspectRatioremoved — Only size is supported.
Model versionmodelVersionremoved — No version selection in the API.
Model payloadmodelSpecificPayloadremoved
CAI metadataoutput.cairemoved
Stored inputsoutput.storeInputsremoved
Generation metadatagenerationMetadataremoved — no longer client-supplied
Prompt reasoningnot availablemodelSpecificPayload.prompt_reasoner

One trap: these changes live only in the overview page and the migration guide, and the changelog has no Image5 entry at all. The Firefly Image 5 walkthrough covers the same model from the interface side.

Rate limits, storage and unpublished numbers

Limits are enforced per organization: 4 requests per minute (RPM) and 9,000 requests per day (RPD), and the daily ceiling still applies to accounts already raised above 4 RPM. Exceeding either returns HTTP 429 Too Many Requests; Adobe’s guidance is Implement retry logic via a retry-after HTTP header or an exponential backoff strategy. Raises go through your account manager.

The Image Model 5 endpoint /v4/images/generate-async accepts five storage hosts: amazonaws.com, windows.net, dropboxusercontent.com, storage.googleapis.com and frontdoor.prod.azure.cxp.adobe.com. Composite work uploads first through /v2/storage/image, and Object Composite caps input at 10MB. Upscale covers 2×, 4× and 6×, and since 2026-04-24 creative_upsampler_v1 returns a 422 in favour of precise_upsampler_v1.

The per-image API price is not published by the vendor, and the Custom Models status is split the same way, documented on one page and waitlisted on another. Our Recraft API notes cover a vendor that does publish per-image rates.

Frequently asked questions

Is the Adobe Firefly API official? Yes — documented on developer.adobe.com under Adobe Firefly Services, with an API reference and a changelog.

Can I open an account myself? Not from the documentation. Adobe’s prerequisite is a prior conversation with your Adobe Representative, and the credential page is marked [Admins only].

Which endpoint should my code call, and do I need to poll? POST https://firefly-api.adobe.io/v3/images/generate-async, then poll the statusUrl until succeeded or failed.

Why is my old payload rejected? Image5 changed the schema: n became numVariations, modelId became customModelId, and aspectRatio, modelVersion and output.cai were removed.

What does one image cost? Not published by the vendor; Adobe publishes rate limits, not per-image prices.

Treat the credentials as the first deliverable, keep token refresh inside the worker, and re-read the migration guide before touching an existing payload.