API Reference
PaperBanana Open API documentation for image generation
Overview
The PaperBanana API allows you to programmatically generate images using our Standard (text/image-to-image) and Pipeline (AI-powered scientific illustration) models.
Base URL
https://open.paper-banana.org/api/v1All requests must be made over HTTPS.
Authentication
API access requires a Team plan (Team Basic or Team Pro). You can generate team API keys from your team settings.
Authenticate using a Bearer token in the Authorization header:
curl -H "Authorization: Bearer sk-team-your-api-key" \
https://open.paper-banana.org/api/v1/creditsAll team API keys use the sk-team- prefix. Personal API keys (sk-) are no longer accepted for API access.
Team Plans
API access is available exclusively through Team plans:
| Plan | Price | Credits | API Keys | Rate Limit |
|---|---|---|---|---|
| Team Basic | $999/year | 12,000/year | Up to 3 | 120 RPM |
| Team Pro | $1,499/year | 24,000/year | Up to 10 | 300 RPM |
- Credits are shared across the team and consumed at full price (no resolution discounts on API calls).
- Team members using PaperBanana on the web draw from the team credit pool and retain plan-level discounts.
Rate Limiting
Three layers of rate limiting are enforced:
| Layer | Limit | Scope |
|---|---|---|
| IP-based | 120 requests/min | Per client IP (runs before authentication) |
| Key-based | 60 requests/min | Per API key |
| Team-based | 120 or 300 requests/min | Per team (Basic: 120, Pro: 300) |
When any limit is exceeded, the API returns a 429 status with a Retry-After header.
Request Limits
| Constraint | Limit |
|---|---|
| Request body size | 1 MB max |
Content-Length header | Required for POST requests |
prompt length | 10,000 characters |
options.content length | 100,000 characters |
options.image_input items | 10 max |
Endpoints
Check Credits
Returns the remaining credits for your account.
GET /api/v1/creditsResponse
{
"success": true,
"data": {
"remaining_credits": 450
}
}Generate Image
Creates an image generation task. The task runs asynchronously — use the Query Task endpoint to poll for results.
POST /api/v1/generateCommon Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
type | string | Yes | "standard" or "pipeline" |
scene | string | Yes | "text-to-image" or "image-to-image" |
prompt | string | Conditional | Text prompt describing the desired image |
model | string | Conditional | Model name (Standard only) |
options | object | No | Additional options (see below) |
Standard Mode
Uses Kie/Fal providers for general-purpose image generation.
| Parameter | Type | Required | Description |
|---|---|---|---|
model | string | Yes | "nano-banana-pro" or "nano-banana-2" |
prompt | string | Yes | Text prompt |
options.resolution | string | No | "1K" (default), "2K", or "4K" |
options.aspect_ratio | string | No | Aspect ratio, default "auto" |
options.output_format | string | No | "png" (default), "jpg", "jpeg", "webp" |
options.image_input | string[] | image-to-image | Array of source image URLs (HTTPS only, max 10) |
options.google_search | boolean | No | Enable Google search (nano-banana-2 only) |
Image URL restrictions: All
image_inputURLs must usehttps://, must not point to private/internal network addresses, and must not use non-standard ports.
Example: Standard text-to-image
curl -X POST https://open.paper-banana.org/api/v1/generate \
-H "Authorization: Bearer sk-team-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"type": "standard",
"scene": "text-to-image",
"prompt": "A futuristic city skyline at sunset",
"model": "nano-banana-pro",
"options": {
"resolution": "2K",
"output_format": "png"
}
}'Example: Standard image-to-image
curl -X POST https://open.paper-banana.org/api/v1/generate \
-H "Authorization: Bearer sk-team-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"type": "standard",
"scene": "image-to-image",
"prompt": "Make this more professional",
"model": "nano-banana-2",
"options": {
"image_input": ["https://example.com/source.png"],
"resolution": "1K"
}
}'Pipeline Mode
Uses the DeepScience multi-step pipeline for AI-powered scientific illustrations, diagrams, and plots.
| Parameter | Type | Required | Description |
|---|---|---|---|
prompt | string | text-to-image | Text prompt |
options.content | string | Yes | Paper text or context for the pipeline |
options.task_name | string | No | "diagram" (default) or "plot" |
options.resolution | string | No | "1K" (default), "2K", or "4K" |
options.output_format | string | No | "png" (default), "jpg", "jpeg", "webp" |
options.image_input | string[] | image-to-image | Array of source image URLs (HTTPS only, max 10) |
Image URL restrictions: Same restrictions as Standard mode apply — HTTPS only, no private IPs, no non-standard ports.
Pipeline mode requires a Basic or Pro plan.
Example: Pipeline text-to-image
curl -X POST https://open.paper-banana.org/api/v1/generate \
-H "Authorization: Bearer sk-team-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"type": "pipeline",
"scene": "text-to-image",
"prompt": "Architecture diagram for transformer model",
"options": {
"content": "This paper presents a novel transformer architecture with multi-head attention...",
"task_name": "diagram",
"resolution": "2K"
}
}'Example: Pipeline image-to-image
curl -X POST https://open.paper-banana.org/api/v1/generate \
-H "Authorization: Bearer sk-team-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"type": "pipeline",
"scene": "image-to-image",
"options": {
"content": "This paper presents a novel transformer architecture...",
"image_input": ["https://example.com/my-diagram.png"],
"resolution": "2K"
}
}'Generate Response
{
"success": true,
"data": {
"task_id": "7655ed66-3a83-4a5a-9cb1-3b7c449ec4a9",
"status": "pending",
"cost_credits": 20
}
}List Tasks
Returns a paginated list of your generation tasks, with optional status filtering.
GET /api/v1/tasksQuery Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
page | number | No | Page number, default 1 |
limit | number | No | Items per page, default 20, max 100 |
status | string | No | Filter by status: "pending", "processing", "success", "failed", or "canceled" |
Response
{
"success": true,
"data": {
"tasks": [
{
"task_id": "7655ed66-3a83-4a5a-9cb1-3b7c449ec4a9",
"type": "standard",
"model": "nano-banana-pro",
"scene": "text-to-image",
"status": "success",
"cost_credits": 10,
"created_at": "2026-03-12T06:57:48.067Z",
"output": {
"images": [
{
"url": "https://storage.paper-banana.org/uploads/...",
"type": "image/png"
}
]
},
"error": null
}
],
"pagination": {
"total": 42,
"page": 1,
"limit": 20,
"total_pages": 3
}
}
}Example
# List all tasks (page 1)
curl -H "Authorization: Bearer sk-team-your-api-key" \
"https://open.paper-banana.org/api/v1/tasks"
# Filter by status with pagination
curl -H "Authorization: Bearer sk-team-your-api-key" \
"https://open.paper-banana.org/api/v1/tasks?status=success&page=2&limit=10"Query Task
Poll the status of a generation task. Keep polling until status is "success", "failed", or "canceled".
GET /api/v1/task/:taskIdResponse (processing)
{
"success": true,
"data": {
"task_id": "7655ed66-...",
"type": "pipeline",
"model": "pipeline",
"scene": "text-to-image",
"status": "processing",
"cost_credits": 14,
"created_at": "2026-03-12T06:57:48.067Z",
"output": {
"images": [],
"current_stage": "stylist"
},
"error": null
}
}The current_stage field is available for Pipeline tasks and shows which step is currently executing (e.g. retriever, planner, stylist, visualizer, critic_round_0, etc.).
Response (completed)
{
"success": true,
"data": {
"task_id": "7655ed66-...",
"type": "standard",
"model": "nano-banana-pro",
"scene": "text-to-image",
"status": "success",
"cost_credits": 14,
"created_at": "2026-03-12T06:57:48.067Z",
"output": {
"images": [
{
"url": "https://storage.paper-banana.org/uploads/...",
"type": "image/png"
}
]
},
"error": null
}
}Response (failed)
{
"success": true,
"data": {
"task_id": "7655ed66-...",
"type": "standard",
"model": "nano-banana-pro",
"scene": "text-to-image",
"status": "failed",
"cost_credits": 0,
"created_at": "2026-03-12T06:57:48.067Z",
"output": {
"images": []
},
"error": "task failed"
}
}Credit Costs
Credits are consumed when a task completes successfully. The cost depends on the generation type, model, resolution, and your plan.
Standard Mode
| Model | 1K | 2K | 4K |
|---|---|---|---|
| nano-banana-pro | 10 | 20 | 40 |
| nano-banana-2 | 5 | 10 | 20 |
Pipeline Mode
Base cost: 6 credits at 1K resolution (default steps).
| Resolution | Multiplier |
|---|---|
| 1K | x1 |
| 2K | x2 |
| 4K | x4 |
Plan Discounts (Web Only)
Higher-tier plans receive discounts on high-resolution generation when using the web interface. API calls are always charged at full price with no resolution discounts.
| Plan | Standard 2K | Standard 4K | Pipeline 2K | Pipeline 4K |
|---|---|---|---|---|
| Hobby | Full price | Full price | Full price | Full price |
| Basic | Same as 1K | 50% off | Same as 1K | 50% off |
| Pro | Same as 1K | Same as 1K | Same as 1K | Same as 1K |
| Team (API) | Full price | Full price | Full price | Full price |
Errors
All error responses follow the same format:
{
"success": false,
"error": {
"message": "error description"
}
}| HTTP Status | Description |
|---|---|
| 400 | Bad request — missing or invalid parameters |
| 401 | Unauthorized — invalid or missing API key |
| 402 | Payment required — insufficient credits |
| 403 | Forbidden — API access requires a Team plan (personal sk- keys are not accepted) |
| 404 | Not found — task does not exist or belongs to another user |
| 411 | Length required — Content-Length header missing on POST request |
| 413 | Payload too large — request body exceeds 1 MB |
| 429 | Too many requests — rate limit exceeded |
| 500 | Internal server error |
| 503 | Service unavailable — provider temporarily unavailable |
Quick Start
Here is a complete example that generates an image and polls for the result:
API_KEY="sk-team-your-api-key"
BASE_URL="https://open.paper-banana.org/api/v1"
# 1. Check your credits
curl -s -H "Authorization: Bearer $API_KEY" "$BASE_URL/credits"
# 2. Create a generation task
RESPONSE=$(curl -s -X POST "$BASE_URL/generate" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "standard",
"scene": "text-to-image",
"prompt": "A red apple on a white background",
"model": "nano-banana-pro"
}')
echo "$RESPONSE"
TASK_ID=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['task_id'])")
# 3. Poll until complete
while true; do
RESULT=$(curl -s -H "Authorization: Bearer $API_KEY" "$BASE_URL/task/$TASK_ID")
STATUS=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['status'])")
echo "Status: $STATUS"
if [ "$STATUS" = "success" ] || [ "$STATUS" = "failed" ] || [ "$STATUS" = "canceled" ]; then
echo "$RESULT" | python3 -m json.tool
break
fi
sleep 5
done