Skip to content
Developer Portal

Quickstart

Get up and running with P-API in just a few minutes. This guide covers authentication, file uploads, and making your first image generation requests.

Create your API key yourself in the Pruna dashboard:

  1. Sign up or log in at dashboard.pruna.ai.
  2. Go to API Keys and accept the Terms of Service and the DPA.
  3. If your account is billed with credits, add a payment method in Billing.
  4. Click Create New API Key in API Keys.
  5. Copy the key and store it securely.

Once you have your API key, include it in the apikey header for all requests:

Terminal window
curl -H "apikey: YOUR_API_KEY" https://api.pruna.ai/v1/<endpoint> <body>

Let's generate an image using the P-Image model. We'll use synchronous mode (Try-Sync: true) to get results immediately:

Terminal window
curl -X POST https://api.pruna.ai/v1/predictions \
-H "apikey: YOUR_API_KEY" \
-H "Model: p-image" \
-H "Try-Sync: true" \
-H "Content-Type: application/json" \
-d '{
"input": {
"prompt": "A majestic lion standing on a rocky cliff at sunset, photorealistic, 4k",
"aspect_ratio": "16:9"
}
}'

Response (if completed within 60 seconds):

{
"status": "succeeded",
"generation_url": "https://api.pruna.ai/v1/predictions/delivery/xezq/abc123.../output.jpg"
}

Download your image: curl -H "apikey: YOUR_API_KEY" \ https://api.pruna.ai/v1/predictions/delivery/xezq/abc123.../output.jpg \ -o my-image.jpg

To edit images with P-Image-Edit, you'll first need to upload your reference images:

Terminal window
curl -X POST https://api.pruna.ai/v1/files \
-H "apikey: YOUR_API_KEY" \
-F "content=@my-photo.jpg" \
> upload1.json

Response:

{
"id": "file-abc123",
"urls": {
"get": "https://api.pruna.ai/v1/files/file-abc123"
}
}

Upload second image (optional, p-image-edit supports 1-5 images)

Section titled “Upload second image (optional, p-image-edit supports 1-5 images)”
Terminal window
curl -X POST https://api.pruna.ai/v1/files \
-H "apikey: YOUR_API_KEY" \
-F "content=@another-photo.jpg" \
> upload2.json

Response:

{
"id": "file-abc123",
"urls": {
"get": "https://api.pruna.ai/v1/files/file-def456"
}
}

Use the uploaded file URLs in your editing request:

Terminal window
curl -X POST https://api.pruna.ai/v1/predictions \
-H "apikey: YOUR_API_KEY" \
-H "Model: p-image-edit" \
-H "Try-Sync: true" \
-H "Content-Type: application/json" \
-d '{
"input": {
"prompt": "Transform into a watercolor painting style with vibrant colors",
"images": [
"https://api.pruna.ai/v1/files/file-abc123",
"https://api.pruna.ai/v1/files/file-xyz789"
],
"reference_image": "1",
"aspect_ratio": "16:9"
}
}'

Response:

{
"status": "succeeded",
"generation_url": "https://api.pruna.ai/v1/predictions/delivery/xezq/def456.../output.jpg"
}

Asynchronous Workflow (For Longer Requests)

Section titled “Asynchronous Workflow (For Longer Requests)”

Some models or complex requests may take longer than 60 seconds. For these, use the asynchronous workflow to avoid timeouts:

Terminal window
curl -X POST https://api.pruna.ai/v1/predictions \
-H "apikey: YOUR_API_KEY" \
-H "Model: p-image-edit" \
-H "Content-Type: application/json" \
-d '{
"input": {
"prompt": "Complex artistic transformation with multiple effects",
"images": ["https://api.pruna.ai/v1/files/file-abc123"]
}
}'

Response:

{
"id": "1zww7deyssrme0csqwr90phzzr",
"model": "p-image-edit",
"input": { ... },
"get_url": "https://api.pruna.ai/v1/predictions/status/1zww7deyssrme0csqwr90phzzr"
}

Poll the status endpoint to check progress:

Terminal window
curl -H "apikey: YOUR_API_KEY" \
https://api.pruna.ai/v1/predictions/status/1zww7deyssrme0csqwr90phzzr

Response (Starting):

{
"status": "starting",
"message": "Generation in progress"
}

Response (Processing):

{
"status": "processing",
"message": "Generation in progress"
}

Response (Completed):

"status": "succeeded",
"generation_url": "https://api.pruna.ai/v1/predictions/delivery/xezq/52UGYRrRfqViaKmvYsEnENTh0qLDAWHptQ8jOnEHu7XC6AtKA/output.mp4"
}

Response (Failed):

{
"status": "failed",
"message": "Prediction failed",
"error": "Number of samples, -5, must be non-negative.",
"moderation": null
}

Response (Blocked by content moderation):

{
"status": "failed",
"message": "Prediction failed",
"error": "Prediction failed: Content moderation: Blocked by the safety filter (copyright_detected). You can disable it through the API with enable_copyright_filter=false.",
"moderation": {
"blocked": true,
"phase": "input",
"categories": ["copyright_detected"],
"reason": "Blocked by content policy (copyright_detected). ...",
"can_disable": true,
"message": "Blocked by the safety filter (copyright_detected). You can disable it through the API with enable_copyright_filter=false."
}
}

moderation is set when content moderation blocked the request, and null for any other failure. categories lists what was detected, for example copyright_detected when enable_copyright_filter is on. can_disable is false when a category is always enforced, so no request parameter can lift the block. message is the same short explanation as the error text. This works the same for every model.

curl -H "apikey: YOUR_API_KEY" \
https://api.pruna.ai/v1/predictions/delivery/xezq/abc123.../output.jpg \
-o result.jpg

Asynchronous Mode (recommended)

  • ✅ Video generation models (wan-i2v, wan-t2v, vace)
  • ✅ Complex image processing that may take longer
  • ✅ When you want to avoid timeout issues
  • ✅ When processing multiple requests in parallel (causing a spike in usage will trigger infrastructure scaling and queuing of your requests)

Synchronous Mode (Try-Sync: true)

  • ✅ Fast models like p-image, p-image-edit, wan-image-small
  • ✅ Simple requests with quick processing times
  • ✅ When you need immediate results in a single request
  • ❌ Not recommended for video models or complex edits that may take ~10 seconds or more

In synchronous mode, a prediction blocked by content moderation returns HTTP 422 (see Blocked requests), any other failure HTTP 500, and a canceled prediction HTTP 499, each with the same body as the status endpoint above. A 422 with a non-null moderation is a block; do not retry it unchanged.

Content moderation can block a request. The prediction then fails with status: "failed" and a non-null moderation object, as in "Response (Blocked by content moderation)" above.

  • Without Try-Sync, the status endpoint returns that body.
  • With Try-Sync: true, the create call usually returns HTTP 422 with that body. If the block lands just after the gateway answers, the create call returns HTTP 201 with an id and get_url instead. Poll the status endpoint, which then returns the moderation object.

The error text names the parameter that lifts the block, and each model page lists it. When moderation.can_disable is false, the category is always enforced and no parameter lifts it. Do not retry a blocked request unchanged.

Note: use the synchronous mode at your own risk, you may encounter timeouts / 504 errors. Async mode is safer, but the sync mode gets you the results faster and with less code.

Different models have different rate limits:

  • P-Models (p-image, p-image-edit): 500 requests/minute
  • Other Image Models (flux-dev, qwen-image, etc.): 150 requests/minute
  • Video Models (wan-i2v, wan-t2v, vace): 30 requests/minute
  • Status Endpoint: 30,000 requests/minute
  • Delivery Endpoint: 10,000 requests/minute
  • Explore all /models and their capabilities
  • Learn about /api-reference for fine-tuning results
  • Check out /examples for inspiration

Need help? Contact us.