Images
Images are synchronous: one call, one image, returned in the response. Each image is paid from the API wallet at the model’s price per image. Every model, with its sizes and price, is in the Image models table. The live list is in GET /v1/usage/prices (the image array) and on the Developers page.
Generate an image
Section titled “Generate an image”POSThttps://api.aderra.ai/v1/images/generations
Send the key as Authorization: Bearer. The body is JSON.
Request body
promptstringrequired- What to draw.
modelstringoptional- An image model id, for example
gpt-image-2.6orseedream-v45: see Image models. Absent:flux-schnell, the default. A name Aderra does not know also falls back to the default, unlessmaxPriceMicrois set, when it is refused. sizestringoptional- One of the model’s
sizes, for example1024x1024. Absent: its first size. Another size is refused withunsupported_size, which lists the allowed ones. maxPriceMicrostringoptional- Optional price ceiling, in micro-credits as a string of digits (1 credit = 1,000,000 micro-credits; 1,000 credits = $1). A model that costs more is refused with
price_limit_exceededbefore anything is charged.
n, quality, style and response_format are not read. Every call returns one image.
curl https://api.aderra.ai/v1/images/generations \ -H "Authorization: Bearer $ADERRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"prompt": "A lighthouse in a storm, oil painting"}' \ | jq -r '.data[0].b64_json // .data[0].url'import base64, osfrom openai import OpenAI
client = OpenAI(base_url="https://api.aderra.ai/v1", api_key=os.environ["ADERRA_API_KEY"])
result = client.images.generate( prompt="A lighthouse in a storm, oil painting",)image = result.data[0]if image.b64_json: with open("lighthouse.png", "wb") as f: f.write(base64.b64decode(image.b64_json))else: print(image.url)import fs from 'node:fs';import OpenAI from 'openai';
const client = new OpenAI({ baseURL: 'https://api.aderra.ai/v1', apiKey: process.env.ADERRA_API_KEY,});
const result = await client.images.generate({ prompt: 'A lighthouse in a storm, oil painting',});const image = result.data[0];if (image.b64_json) { fs.writeFileSync('lighthouse.png', Buffer.from(image.b64_json, 'base64'));} else { console.log(image.url);}{ "created": 1762862400, "data": [{ "b64_json": "iVBORw0KGgo..." }], "included": false, "billed_micro": "..."}Response: application/json
The response
Section titled “The response”dataholds one image, either asb64_json(PNG data) or as aurl, depending on the model. Handle both, as the examples do.billed_microis what this image cost, in micro-credits, as a string.includedis alwaysfalsefor an API key (plan allowances never apply to the API wallet).prompt_rewritten: trueappears when your prompt was reworded after a content refusal (see below).
A URL can stop working after a while: save the image when you receive it.
Edit or combine images
Section titled “Edit or combine images”POSThttps://api.aderra.ai/v1/images/edits
Image to image. The body is the same as for generation. The request carries no image. The images to edit are your account’s most recent images: up to 8, newest first, from roughly the last two hours:
- images you generated with
/v1/images/generations; - images you sent as
image_urlparts to/v1/chat/completions.
So to edit a picture of your own, send it in a chat completion first, then call edits with what to change. To combine several, send them together. With no recent image the call is refused with 400 no_reference_image.
curl https://api.aderra.ai/v1/images/edits \ -H "Authorization: Bearer $ADERRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"prompt": "Make it night, with the lamp lit"}'import osimport requests
r = requests.post( "https://api.aderra.ai/v1/images/edits", headers={"Authorization": f"Bearer {os.environ['ADERRA_API_KEY']}"}, json={"prompt": "Make it night, with the lamp lit"}, timeout=120,)r.raise_for_status()print(r.json()["data"][0].keys())const r = await fetch('https://api.aderra.ai/v1/images/edits', { method: 'POST', headers: { Authorization: `Bearer ${process.env.ADERRA_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ prompt: 'Make it night, with the lamp lit' }),});const result = await r.json();console.log(Object.keys(result.data[0]));Response: application/jsonThe same shape as a generation.
The SDKs’ images.edit() methods upload a file as multipart form data, which this endpoint does not read; call it with JSON as above.
Content refusals
Section titled “Content refusals”Some image models apply their own content filter. When a filter refuses a prompt:
- Aderra may reword the prompt once and try again on the same model (
prompt_rewritten: truein the response), - then try once on an unfiltered model, which is billed at that model’s price.
If the image is still refused you get 422 refused_blank or 422 image_content_refused, and nothing is charged. A model that returns a blank frame instead of an image is detected and not charged either. The filtered field in /v1/usage/prices tells you which models filter. What you may ask for is set by the content policy.
Errors
Section titled “Errors”| Status | error |
What to do |
|---|---|---|
| 400 | invalid_json, missing_prompt |
Send a JSON body with a non-empty prompt |
| 400 | invalid_size, unsupported_size |
Use one of the allowed sizes in the response |
| 400 | invalid_price_limit, unknown_model |
maxPriceMicro must be digits; check the model name |
| 400 | no_reference_image |
Edits: send or generate an image first |
| 402 | price_limit_exceeded |
The model costs more than your maxPriceMicro |
| 402 | api_wallet_empty, key_spend_cap_reached |
Add funds, or raise the key’s cap |
| 422 | refused_blank, image_content_refused |
Reword the prompt. Not charged |
| 502 | image_failed |
The model failed. Not charged. Try again |
Media errors send error as a plain string, sometimes with a message; wallet and rate-limit refusals use the object shape. See Errors.