promptstringWymaganeDo 5000 znaków. Opisz obiekt, otoczenie, światło i obiektyw zwykłymi zdaniami; słowa w cudzysłowie są drukowane na obrazie.
- Domyślnie
- Nie określono
- Ograniczenia
- minLength:1maxLength:5000
Tekst na obraz w Nano Banana 2.1 to najnowszy model Nano Banana od Google. Generuje w 1k, 2k lub 4k w czternastu proporcjach do 8:1, poprawnie zapisuje tekst w cudzysłowie i przed rysowaniem może przeszukać sieć lub obrazy referencyjne.
Przykłady korzystają z publicznych definicji parametrów wybranego endpointu. Podmień klucz API i przykładowe media, a potem wyślij żądanie ze swojego serwera.
SDK i integracjehttps://api.spicyapi.ai/api/v1/jobs/createTaskKlucz API trzymaj w zmiennej środowiskowej serwera SPICY_API_KEY. Dla żądań JSON używaj uwierzytelniania Bearer i Content-Type: application/json.
Authorization: Bearer $SPICY_API_KEY
# Generate the idempotency key once; reuse it when retrying after a lost response.
export SPICY_IDEMPOTENCY_KEY="${SPICY_IDEMPOTENCY_KEY:-$(uuidgen)}"
curl -X POST https://api.spicyapi.ai/api/v1/jobs/createTask \
-H "Authorization: Bearer $SPICY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $SPICY_IDEMPOTENCY_KEY" \
-d '{
"model": "google/nano-banana-2.1/text-to-image",
"input": {
"prompt": "A ceramic teapot on a linen cloth, soft window light, muted palette",
"resolution": "1k",
"aspect_ratio": "16:9",
"output_format": "png",
"enable_web_search": false,
"enable_image_search": false
}
}'
# Copy data.taskId from the response into TASK_ID, then poll the status.
TASK_ID="TASK_ID_FROM_RESPONSE"
curl "https://api.spicyapi.ai/api/v1/jobs/recordInfo?taskId=$TASK_ID" \
-H "Authorization: Bearer $SPICY_API_KEY"Wygenerowane ze schematu wejścia tego modelu – tego samego, względem którego API waliduje każde żądanie.
Te pola umieść w obiekcie input w ciele żądania. Nazwy i typy odpowiadają API. Gdy wartości domyślnej nie podano, nie zakładaj żadnej.
promptstringWymaganeDo 5000 znaków. Opisz obiekt, otoczenie, światło i obiektyw zwykłymi zdaniami; słowa w cudzysłowie są drukowane na obrazie.
official_fallbackbooleanOpcjonalneDomyślnie włączone. Każde żądanie najpierw wykonuje się ścieżką ekonomiczną. Jeśli ta ścieżka nie może go zrealizować, na przykład dlatego, że odrzuca prompt na poziomie Łagodny, żądanie uruchamia się ponownie oficjalną ścieżką i jest rozliczane po oficjalnej, a nie ekonomicznej cenie. Wyłącz, aby płacić tylko cenę ekonomiczną; żądanie może wtedy zostać odrzucone lub zakończyć się błędem, a wyszukiwanie w sieci i wyszukiwanie obrazów są niedostępne.
output_formatstringOpcjonalnepng (domyślnie) lub jpeg. Pliki JPEG są kilkukrotnie mniejsze; cena jest taka sama.
"png""jpeg"enable_image_searchbooleanOpcjonalneWpływa na cenęDomyślnie wyłączone. Po włączeniu model przed rysowaniem szuka w sieci obrazów referencyjnych, co pomaga przy prawdziwych miejscach i produktach. Dolicza do żądania opłatę za wyszukiwanie, widoczną w wycenie. W takim przypadku żądanie idzie oficjalną trasą po cenie oficjalnej, więc zostaw opcję Official fallback włączoną.
enable_web_searchbooleanOpcjonalneWpływa na cenęDomyślnie wyłączone. Po włączeniu model przed rysowaniem sprawdza aktualne fakty, takie jak daty, pogoda czy wydarzenia. Dolicza do żądania opłatę za wyszukiwanie, widoczną w wycenie. W takim przypadku żądanie idzie oficjalną trasą po cenie oficjalnej, więc zostaw opcję Official fallback włączoną.
resolutionstringOpcjonalneWpływa na cenę1k (domyślnie), 2k lub 4k. Kwadratowy kadr ma bok 1024, 2048 lub 4096 pikseli; każdy poziom ma własną cenę.
"1k""2k""4k"aspect_ratiostringOpcjonalneJedna z czternastu proporcji, domyślnie 16:9; proporcje nie zmieniają ceny. Skrajne proporcje 4:1, 1:4, 8:1 i 1:8 czasem wracają jako kilka zszytych ujęć, zależnie od tego, co pokazują: przy 4:1 i 8:1 trzymaj ludzi małych i blisko środka albo pokaż krajobraz, a 1:4 i 1:8 daj obiekt, który sam jest wysoki. Sprawdź wynik, zanim go użyjesz.
"1:1""3:2""2:3""3:4""4:3""4:5""5:4""9:16""16:9""21:9""1:4""4:1""1:8""8:1"{
"type": "object",
"required": [
"prompt"
],
"x-pricing": {
"billingMode": "formula",
"variantFields": [
"resolution"
]
},
"properties": {
"prompt": {
"type": "string",
"x-ui": {
"order": 100,
"widget": "textarea"
},
"maxLength": 5000,
"minLength": 1,
"description": "Describe the image you want."
},
"resolution": {
"enum": [
"1k",
"2k",
"4k"
],
"type": "string",
"x-ui": {
"order": 78,
"widget": "radio",
"affects_price": true
},
"default": "1k",
"description": "Output size tier."
},
"aspect_ratio": {
"enum": [
"1:1",
"3:2",
"2:3",
"3:4",
"4:3",
"4:5",
"5:4",
"9:16",
"16:9",
"21:9",
"1:4",
"4:1",
"1:8",
"8:1"
],
"type": "string",
"x-ui": {
"order": 80,
"widget": "select"
},
"default": "16:9",
"description": "Output aspect ratio."
},
"output_format": {
"enum": [
"png",
"jpeg"
],
"type": "string",
"x-ui": {
"order": 30,
"widget": "select"
},
"default": "png",
"description": "File format of the result."
},
"enable_web_search": {
"type": "boolean",
"x-ui": {
"order": 40,
"widget": "switch",
"affects_price": true
},
"default": false,
"description": "Look up current facts on the web before drawing."
},
"official_fallback": {
"type": "boolean",
"x-ui": {
"order": 20,
"widget": "switch"
},
"default": true,
"description": "If the economy route cannot complete the request, retry it on the official route and bill it at the official price."
},
"enable_image_search": {
"type": "boolean",
"x-ui": {
"order": 38,
"widget": "switch",
"affects_price": true
},
"default": false,
"description": "Look up reference pictures on the web before drawing."
}
},
"additionalProperties": false
}HTTP 202 oznacza, że zadanie zostało przyjęte, a nie ukończone. Zapisz zwrócone taskId i odpytuj właśnie to zadanie. Nie twórz kolejnego zadania, czekając na jego wynik.
HTTP/1.1 202 Accepted
Location: /api/v1/jobs/recordInfo?taskId=job_01k3m8x9q2z4v7n5p6r8s0t1w3
{
"code": 200,
"msg": "success",
"request_id": "req_example_create",
"data": {
"taskId": "job_01k3m8x9q2z4v7n5p6r8s0t1w3",
"state": "queued",
"estimatedCost": "0.750000"
}
}Odpowiedź o przyjęciu zawiera szacunek, dzięki czemu twoja aplikacja pokaże tę samą kwotę w historii zadań i w rozliczeniach.
curl --get "https://api.spicyapi.ai/api/v1/jobs/recordInfo" \
--data-urlencode "taskId=$TASK_ID" \
-H "Authorization: Bearer $SPICY_API_KEY"Zacznij odpytywać mniej więcej co 2 sekundy i stopniowo wydłużaj odstęp. Zatrzymaj się na stanie końcowym. Po zerwaniu połączenia odpytaj pierwotne taskId. Tworzenie ponawiaj wyłącznie z pierwotnym kluczem idempotentności i pierwotnym ciałem żądania.
import { verifyWebhook } from "@spicyapi/sdk";
// express.raw keeps the bytes we signed; express.json never matches.
app.post("/hooks/spicy", express.raw({ type: "application/json" }), (req, res) => {
const { payload } = verifyWebhook({
rawBody: req.body,
timestamp: req.header("X-Webhook-Timestamp"),
signature: req.header("X-Webhook-Signature"),
payloadVersion: Number(req.header("X-Webhook-Payload-Version")),
secret: process.env.SPICY_WEBHOOK_SECRET,
});
res.status(200).end();
void handleFinishedTask(payload);
});Podaj callBackUrl przy tworzeniu zadania, a gotowy rekord przyjdzie do ciebie metodą POST – bez żadnej pętli odpytywania. Każda dostawa niesie X-Webhook-Timestamp, X-Webhook-Signature i X-Webhook-Payload-Version. Podpis to HMAC-SHA256 w base64 z taskId.timestamp.sha256(body), więc trzeba go sprawdzać na surowych bajtach: sparsowanie JSON-a i ponowne zserializowanie zmienia je i weryfikacja się nie powiedzie. Nieudane dostawy są ponawiane, więc to samo taskId może przyjść dwa razy – zrób obsługę idempotentną. Najpierw odpowiedz kodem 2xx, a pracę wykonaj potem; wolna obsługa jest traktowana jak nieudana dostawa.
Wynik wykorzystuj dopiero przy stanie succeeded. Przy niepowodzeniu skorzystaj z errorCode, errorMessage i request_id. Przykładowe koszty i stany nie odpowiadają rzeczywistemu rozliczeniu.
{
"code": 200,
"msg": "success",
"request_id": "req_example_record",
"data": {
"taskId": "job_01k3m8x9q2z4v7n5p6r8s0t1w3",
"model": "google/nano-banana-2.1/text-to-image",
"state": "succeeded",
"output": {
"assets": [
{
"key": "tasks/2026/08/28/job_01k3m8x9q2z4v7n5p6r8s0t1w3/3f7a1c9e5b2d48f0a6c1e3d5b7f9a1c3.png",
"mime": "image/png",
"url": "https://example.r2.cloudflarestorage.com/results/job_01k3m8x9q2z4v7n5p6r8s0t1w3/result.png?X-Amz-Signature=SIGNATURE_FROM_RESPONSE",
"expiresAt": "2026-08-28T12:20:08.000Z"
}
]
},
"cost": "0.750000",
"settled": true,
"createdAt": "2026-08-28T12:00:00Z",
"completedAt": "2026-08-28T12:00:30Z"
}
}Każdy dostępny materiał otwieraj lub pobieraj bezpośrednio spod assets[].url, bez nagłówka Authorization. Podpisany adres wygasa o expiresAt; odpytaj zadanie ponownie, żeby go odświeżyć, dopóki materiał mieści się w okresie przechowywania. Materiał oczekujący lub niedostępny nie ma adresu. Podpisane adresy traktuj jako prywatne.
Korzystaj ze SpicyAPI w aplikacji, terminalu, asystencie AI lub wizualnym przepływie pracy. Wybierz instrukcję konfiguracji.
Nie musisz pisać żadnego z powyższych fragmentów kodu. Wystarczy raz podłączyć serwer MCP, a każdy agent obsługujący MCP — Claude Code, Codex, Cursor, Windsurf, VS Code, Gemini CLI, Cline, LibreChat — może uruchomić ten model po nazwie. Można go też wywołać z powłoki jednym poleceniem.
Użyj google/nano-banana-2.1/text-to-image, żeby wygenerować portret tancerki w neonowym świetle, i zapisz go do ./out/.
Agent znajduje model w aktualnym katalogu, sam wysyła plik lokalny, a potem pokazuje dokładną wycenę wraz z maksymalną opłatą i czeka na twoje potwierdzenie. Nic nie zostaje naliczone, dopóki nie zgodzisz się wprost.
claude mcp add spicyapi -e SPICY_API_KEY=$SPICY_API_KEY \
-- npx --yes --package=@spicyapi/mcp spicyapi-mcp
npx skills add spicyapi-ai/spicy-skillPierwsza linia daje agentowi narzędzia; druga daje mu Skill, czyli reguły ich używania: najpierw wycena, potem opłata, wysyłanie plików lokalnych zamiast wklejania bajtów i odczyt gotowego adresu materiału zamiast zgadywania. Każdy inny klient podłącza ten sam serwer przez własny plik konfiguracyjny – zobacz centrum dla deweloperów.
npx @spicyapi/cli tasks create --model google/nano-banana-2.1/text-to-image \
--input-json '{"prompt":"A ceramic teapot on a linen cloth, soft window light, muted palette","resolution":"1k","aspect_ratio":"16:9","output_format":"png","enable_web_search":false,"enable_image_search":false}' \
--waitWejściem jest własny schemat tego endpointu, ten sam co w przykładach powyżej. --wait odpytuje aż do zakończenia zadania i wypisuje wynik; dodaj --yes, żeby pominąć pytanie o potwierdzenie w CI. Najpierw ustaw SPICY_API_KEY – jeden klucz działa w API, w CLI i na serwerze MCP.
npx @spicyapi/cli tasks create --model google/nano-banana-2.1/text-to-image \
--input-json '{…}' --retention 1h --wait
npx @spicyapi/cli tasks get $TASK_ID # read back the retention that applied--retention potrafi wyłącznie skrócić okno – 30m, 1h, 7d albo 0, żeby usunąć zaraz po osiągnięciu przez zadanie stanu końcowego. Obowiązuje najkrótsza z trzech wartości: twojego żądania, ustawień konta i maksimum platformy, więc odczytaj ją z rekordu zadania, zamiast zakładać, że podana liczba zadziałała. Podanie okna dłuższego, niż pozwala konto, nic nie zmienia.
Zainstaluj węzły SpicyAPI przez ComfyUI Manager albo poleceniem poniżej, a potem wyszukaj na płótnie Nano Banana 2.1 · Text to Image. Węzeł ma te same opcje co ta strona i pokazuje cenę, zanim ruszy.
cd ComfyUI/custom_nodes
git clone https://github.com/spicyapi-ai/comfyui-spicyapiOsadzony panel czyta ten sam schemat co ta strona, więc nie może się od API rozjechać. Jeśli twoja dokumentacja potrzebuje treści przeszukiwalnej, pobierz JSON spod /api/embed/models/ i wyrenderuj go samodzielnie.
<iframe src="https://spicyapi.ai/embed/pl/models/nano-banana-2-1/api?model=google%2Fnano-banana-2.1%2Ftext-to-image" width="100%" height="560" loading="lazy" title="Przykładowe żądanie" style="border:1px solid rgba(0,0,0,.12)"></iframe>