curl --request POST \
--url https://api.mage.space/v1/nano_banana_v2/generate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"prompt": "Editorial portrait in soft daylight, 35mm film look",
"aspect_ratio": "1:1"
}
'import Mage from '@mage-space/sdk';
const mage = new Mage(); // reads MAGE_API_KEY
const request = await mage.run('nano_banana_v2', {
prompt: 'Editorial portrait in soft daylight, 35mm film look',
aspect_ratio: '1:1',
});
console.log(request.result.url);from mage_space import Mage
mage = Mage() # reads MAGE_API_KEY
request = mage.run("nano_banana_v2", {
"prompt": "Editorial portrait in soft daylight, 35mm film look",
"aspect_ratio": "1:1",
})
print(request["result"]["url"])const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
prompt: 'Editorial portrait in soft daylight, 35mm film look',
aspect_ratio: '1:1'
})
};
fetch('https://api.mage.space/v1/nano_banana_v2/generate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"request_id": "d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff",
"status": "in_progress",
"architecture": "nano_banana_v2",
"model_id": "nano-banana-v2.1",
"created_at": "2026-09-17T14:52:48.000Z",
"updated_at": "2026-09-17T14:52:49.000Z",
"billing": {
"mode": "gems",
"gems_charged": 51
},
"result": null,
"error": null,
"status_url": "https://api.mage.space/v1/requests/d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff/status",
"cancel_url": "https://api.mage.space/v1/requests/d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff/cancel"
}{
"error": {
"code": "invalid_config",
"message": "`resolution` must be one of: 768P, 2K."
}
}{
"error": {
"code": "unauthorized",
"message": "The API key is invalid or has been revoked."
}
}{
"error": {
"code": "insufficient_gems",
"message": "This generation costs 40 gems and the account balance is too low.",
"request_id": "d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff",
"gems_required": 40
}
}{
"error": {
"code": "content_blocked",
"message": "The request was blocked by Mage's content policy.",
"request_id": "d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff"
}
}{
"error": {
"code": "architecture_retired",
"message": "This architecture has been retired.",
"request_id": "d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff"
}
}{
"error": {
"code": "too_many_requests",
"message": "At most 20 generations may be in flight at once for this account; 20 are running now."
}
}{
"error": {
"code": "content_blocked",
"message": "The request was blocked by an external content restriction.",
"request_id": "d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff"
}
}{
"error": {
"code": "internal_error",
"message": "Something went wrong on our side. Retry, and contact support if it persists."
}
}Nano Banana 2
Generate images with Nano Banana 2 through the Mage API: the fields of POST /v1/nano_banana_v2/generate, its options by model, the rules it enforces, and its gem price.
curl --request POST \
--url https://api.mage.space/v1/nano_banana_v2/generate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"prompt": "Editorial portrait in soft daylight, 35mm film look",
"aspect_ratio": "1:1"
}
'import Mage from '@mage-space/sdk';
const mage = new Mage(); // reads MAGE_API_KEY
const request = await mage.run('nano_banana_v2', {
prompt: 'Editorial portrait in soft daylight, 35mm film look',
aspect_ratio: '1:1',
});
console.log(request.result.url);from mage_space import Mage
mage = Mage() # reads MAGE_API_KEY
request = mage.run("nano_banana_v2", {
"prompt": "Editorial portrait in soft daylight, 35mm film look",
"aspect_ratio": "1:1",
})
print(request["result"]["url"])const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
prompt: 'Editorial portrait in soft daylight, 35mm film look',
aspect_ratio: '1:1'
})
};
fetch('https://api.mage.space/v1/nano_banana_v2/generate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"request_id": "d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff",
"status": "in_progress",
"architecture": "nano_banana_v2",
"model_id": "nano-banana-v2.1",
"created_at": "2026-09-17T14:52:48.000Z",
"updated_at": "2026-09-17T14:52:49.000Z",
"billing": {
"mode": "gems",
"gems_charged": 51
},
"result": null,
"error": null,
"status_url": "https://api.mage.space/v1/requests/d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff/status",
"cancel_url": "https://api.mage.space/v1/requests/d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff/cancel"
}{
"error": {
"code": "invalid_config",
"message": "`resolution` must be one of: 768P, 2K."
}
}{
"error": {
"code": "unauthorized",
"message": "The API key is invalid or has been revoked."
}
}{
"error": {
"code": "insufficient_gems",
"message": "This generation costs 40 gems and the account balance is too low.",
"request_id": "d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff",
"gems_required": 40
}
}{
"error": {
"code": "content_blocked",
"message": "The request was blocked by Mage's content policy.",
"request_id": "d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff"
}
}{
"error": {
"code": "architecture_retired",
"message": "This architecture has been retired.",
"request_id": "d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff"
}
}{
"error": {
"code": "too_many_requests",
"message": "At most 20 generations may be in flight at once for this account; 20 are running now."
}
}{
"error": {
"code": "content_blocked",
"message": "The request was blocked by an external content restriction.",
"request_id": "d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff"
}
}{
"error": {
"code": "internal_error",
"message": "Something went wrong on our side. Retry, and contact support if it persists."
}
}nano-banana-v2.1), the default, costs less; Nano Banana 2 (nano-banana-v2) also renders at 512. Google’s safety filter applies.
| Detail | |
|---|---|
| Type | Image |
| Models | nano-banana-v2 (Nano Banana 2), nano-banana-v2.1 (Nano Banana 2.1, default) |
| Image inputs | image (reference image), additional_images (additional reference images) |
| Video inputs | None |
| Gems | 51 at the default settings |
| Model page | Nano Banana 2 |
Options by model
The tokens each variant accepts. A field left out inherits the architecture default, clamped to the variant’s first listed token when the variant does not offer it.| Model | resolution |
|---|---|
nano-banana-v2 | 512, 1K, 2K, 4K |
nano-banana-v2.1 | 1K, 2K, 4K |
Mentions
Write@handle in prompt to attach one of your saved entities, exactly as in the app. Each mention counts against the budget below; a mention that does not resolve, or that the chosen model does not support, is refused with 400 invalid_config before any gems are charged. See Characters and references.
| Mention | Models | Budget |
|---|---|---|
| Characters | All models | 14 images, characters, and references per request |
| References | All models | 14 images, characters, and references per request |
{
"prompt": "@ana walking through a night market, wearing @red-coat"
}
billing.gems_charged, and the balance at GET /v1/account.Authorizations
Create a key in API → API Keys: select Create API key, name it in the popup, then select Create key. Copy the one-time key and send it as Authorization: Bearer mage_sk_…. Keys are for server-side code only.
Headers
A key of your choosing, 1 to 255 characters, scoped to your API key. A retried submit with the same key returns the original request with 200 instead of charging again. The key identifies the first submission made with it; later bodies are not compared. A refusal recorded under the key (its envelope carries request_id) replays the same way, so a new attempt needs a new key.
1 - 255Body
A partial config for Nano Banana 2.
The text prompt.
1Integer seed for reproducible output; omit or send null for a random seed.
The model variant to generate with.
nano-banana-v2, nano-banana-v2.1 Aspect ratio as W:H.
1:1, 3:2, 2:3, 3:4, 4:1, 4:3, 4:5, 5:4, 8:1, 9:16, 16:9, 21:9 Output resolution token.
512, 1K, 2K, 4K The reference image. An https URL or a data URL.
Additional reference images. Each an https URL or a data URL.
Response
The request was accepted; poll status_url for the result. A retried submit whose Idempotency-Key was used before answers 200 with the same shape, the original request, and charges nothing.
The request id, also the id in status_url and cancel_url.
queued and in_progress are live; completed, failed, and cancelled are final.
queued, in_progress, completed, failed, cancelled The architecture the request generates with.
The model variant, when the architecture has variants.
When the request was accepted.
When the request last changed.
Show child attributes
Show child attributes
The output once status is completed, else null.
Show child attributes
Show child attributes
Why the request failed once status is failed, else null.
Show child attributes
Show child attributes
Poll this URL for the request.
POST to this URL to stop the request.

