Images
curl --request POST \
--url https://api.example.com/images/generations \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"prompt": "<string>",
"n": 123,
"size": "<string>",
"quality": "<string>",
"background": "<string>",
"output_format": "<string>",
"output_compression": 123,
"moderation": "<string>",
"response_format": "<string>",
"safety_identifier": "<string>",
"provider": {}
}
'import requests
url = "https://api.example.com/images/generations"
payload = {
"model": "<string>",
"prompt": "<string>",
"n": 123,
"size": "<string>",
"quality": "<string>",
"background": "<string>",
"output_format": "<string>",
"output_compression": 123,
"moderation": "<string>",
"response_format": "<string>",
"safety_identifier": "<string>",
"provider": {}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
prompt: '<string>',
n: 123,
size: '<string>',
quality: '<string>',
background: '<string>',
output_format: '<string>',
output_compression: 123,
moderation: '<string>',
response_format: '<string>',
safety_identifier: '<string>',
provider: {}
})
};
fetch('https://api.example.com/images/generations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/images/generations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => '<string>',
'prompt' => '<string>',
'n' => 123,
'size' => '<string>',
'quality' => '<string>',
'background' => '<string>',
'output_format' => '<string>',
'output_compression' => 123,
'moderation' => '<string>',
'response_format' => '<string>',
'safety_identifier' => '<string>',
'provider' => [
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/images/generations"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"n\": 123,\n \"size\": \"<string>\",\n \"quality\": \"<string>\",\n \"background\": \"<string>\",\n \"output_format\": \"<string>\",\n \"output_compression\": 123,\n \"moderation\": \"<string>\",\n \"response_format\": \"<string>\",\n \"safety_identifier\": \"<string>\",\n \"provider\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/images/generations")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"n\": 123,\n \"size\": \"<string>\",\n \"quality\": \"<string>\",\n \"background\": \"<string>\",\n \"output_format\": \"<string>\",\n \"output_compression\": 123,\n \"moderation\": \"<string>\",\n \"response_format\": \"<string>\",\n \"safety_identifier\": \"<string>\",\n \"provider\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/images/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"n\": 123,\n \"size\": \"<string>\",\n \"quality\": \"<string>\",\n \"background\": \"<string>\",\n \"output_format\": \"<string>\",\n \"output_compression\": 123,\n \"moderation\": \"<string>\",\n \"response_format\": \"<string>\",\n \"safety_identifier\": \"<string>\",\n \"provider\": {}\n}"
response = http.request(request)
puts response.read_bodyAPI Reference
Images
Generate images with inline base64 output and per-image billing through the attested gateway.
POST
/
images
/
generations
Images
curl --request POST \
--url https://api.example.com/images/generations \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"prompt": "<string>",
"n": 123,
"size": "<string>",
"quality": "<string>",
"background": "<string>",
"output_format": "<string>",
"output_compression": 123,
"moderation": "<string>",
"response_format": "<string>",
"safety_identifier": "<string>",
"provider": {}
}
'import requests
url = "https://api.example.com/images/generations"
payload = {
"model": "<string>",
"prompt": "<string>",
"n": 123,
"size": "<string>",
"quality": "<string>",
"background": "<string>",
"output_format": "<string>",
"output_compression": 123,
"moderation": "<string>",
"response_format": "<string>",
"safety_identifier": "<string>",
"provider": {}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
prompt: '<string>',
n: 123,
size: '<string>',
quality: '<string>',
background: '<string>',
output_format: '<string>',
output_compression: 123,
moderation: '<string>',
response_format: '<string>',
safety_identifier: '<string>',
provider: {}
})
};
fetch('https://api.example.com/images/generations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/images/generations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => '<string>',
'prompt' => '<string>',
'n' => 123,
'size' => '<string>',
'quality' => '<string>',
'background' => '<string>',
'output_format' => '<string>',
'output_compression' => 123,
'moderation' => '<string>',
'response_format' => '<string>',
'safety_identifier' => '<string>',
'provider' => [
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/images/generations"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"n\": 123,\n \"size\": \"<string>\",\n \"quality\": \"<string>\",\n \"background\": \"<string>\",\n \"output_format\": \"<string>\",\n \"output_compression\": 123,\n \"moderation\": \"<string>\",\n \"response_format\": \"<string>\",\n \"safety_identifier\": \"<string>\",\n \"provider\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/images/generations")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"n\": 123,\n \"size\": \"<string>\",\n \"quality\": \"<string>\",\n \"background\": \"<string>\",\n \"output_format\": \"<string>\",\n \"output_compression\": 123,\n \"moderation\": \"<string>\",\n \"response_format\": \"<string>\",\n \"safety_identifier\": \"<string>\",\n \"provider\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/images/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"n\": 123,\n \"size\": \"<string>\",\n \"quality\": \"<string>\",\n \"background\": \"<string>\",\n \"output_format\": \"<string>\",\n \"output_compression\": 123,\n \"moderation\": \"<string>\",\n \"response_format\": \"<string>\",\n \"safety_identifier\": \"<string>\",\n \"provider\": {}\n}"
response = http.request(request)
puts response.read_bodyEndpoint
POST https://inference.phala.com/v1/images/generations
x-receipt-id header for verification.
Models and Pricing
The live model catalog lists image models withimage in output_modalities. It currently offers black-forest-labs/flux.2-klein-4b at $0.015 per returned image, published as pricing.image_generation in USD per image. Check the catalog for current availability and pricing.
Request Body
string
required
Image model ID, for example
black-forest-labs/flux.2-klein-4b.string
required
Text describing the image, up to 32,000 Unicode characters.
integer
Maximum number of images to generate, from
1 through 10. Defaults to 1. Providers may return fewer images; billing uses the returned count.string
Image dimensions, for example
512x512, or auto if supported by the model.string
Model-specific quality setting.
string
Model-specific background setting.
string
Requested image encoding, subject to model support. The current FLUX route returns JPEG bytes even when
png is requested. Save its output as .jpg; do not infer the encoding from this parameter.integer
Compression setting from
0 through 100, if supported by the model and encoding.string
Model-specific moderation setting.
string
Omit this field or set it to
b64_json. The gateway requests inline base64 output. Image URLs are not supported.string
Accepted for SDK compatibility but removed before forwarding upstream.
object
The same routing constraints as Chat Completions, including
zdr, aci_verified, and aci_session_ids. The Phala endpoint requires verified serving independently of request-level constraints.user and style are accepted as strings but removed before forwarding. Unknown fields, including seed, are rejected. Omit stream and partial_images entirely, including stream: false. Streaming and ACI E2EE are not supported on this endpoint.
Examples
Both examples save the first FLUX image asimage.jpg. The cURL example also saves the raw response and headers, including the receipt ID.
curl --fail-with-body --silent --show-error \
https://inference.phala.com/v1/images/generations \
-H "Authorization: Bearer $PHALA_AI_API_KEY" \
-H "Content-Type: application/json" \
-D image-headers.txt -o image-response.json \
-d '{
"model": "black-forest-labs/flux.2-klein-4b",
"prompt": "A blue circle on a white background.",
"size": "512x512"
}' && \
python3 - <<'PY'
import base64
import json
from pathlib import Path
response = json.loads(Path("image-response.json").read_text())
image = base64.b64decode(response["data"][0]["b64_json"], validate=True)
Path("image.jpg").write_bytes(image)
PY
import base64
import os
from pathlib import Path
from openai import OpenAI
client = OpenAI(
api_key=os.environ["PHALA_AI_API_KEY"],
base_url="https://inference.phala.com/v1",
)
response = client.images.generate(
model="black-forest-labs/flux.2-klein-4b",
prompt="A blue circle on a white background.",
size="512x512",
)
if not response.data or not response.data[0].b64_json:
raise ValueError("The response did not contain an inline image")
image = base64.b64decode(response.data[0].b64_json, validate=True)
Path("image.jpg").write_bytes(image)
Response
Example for one FLUX image at the current rate. The base64 data is shortened.{
"created": 1793859850,
"data": [
{
"b64_json": "/9j/4AAQSkZJRg...",
"revised_prompt": "A blue circle on a white background."
}
],
"usage": {
"input_tokens": 0,
"output_tokens": 0,
"total_tokens": 0,
"input_tokens_details": { "text_tokens": 0, "image_tokens": 0 },
"cost": 0.015
}
}
created is a Unix timestamp in seconds. data is a nonempty array of images with b64_json; an item may also contain revised_prompt as a string or null. The current FLUX response does not include top-level size or output_format fields.
When present, usage includes integer token counts, with missing counts filled with 0. The gateway adds usage.cost in USD when pricing is available: returned image count times the per-image rate, plus token charges if token usage and rates are available. Zero token counts do not imply free image generation.
Verification
Capturex-receipt-id from the response headers and fetch GET /v1/aci/receipts/{id} with the same bearer token. Image receipts have chat_id: null; use the receipt ID. See Get Receipt and Verify a Response. Ordinary cURL and OpenAI SDK clients do not verify the gateway or audit receipts.
Errors
Errors use a JSONerror object, with error.code and error.param where applicable.
| Status | Error field | Condition |
|---|---|---|
| 400 | code: unknown_parameter | Unrecognized field, such as seed; param names the field. |
| 400 | code: invalid_parameter | Missing required strings, invalid option types or ranges, n outside 1–10 or not an integer, response_format: "url", any stream or partial_images field, or a prompt over 32,000 characters. |
| 400 | type: invalid_request_error | Invalid JSON or malformed routing constraints. |
| 400 | type: e2ee_unsupported_endpoint | E2EE headers are present. |
| 404 | type: model_not_found | No eligible route supports image generation for the model. |
| 429 | type: rate_limit_error, code: rate_limit_exceeded | Capacity is full or a rate limit is reached; respect Retry-After when present. |
| 502 | type: upstream_error | Upstream failure, buffered response over 64 MiB, or malformed response, including empty data, too many images, or missing inline image data. |
Related
List Models
Get Receipt
Was this page helpful?

