Images
OpenAI-compatible image generation and editing endpoints. Sakrylle documents them together because the request shape, error handling, and billing rules are identical — only the endpoint and edit-specific fields differ.
Requires an image group API key
Image endpoints are served by the GPT-Image group. Its model is gpt-image-2, billed at ¥0.15 per successful call.
Before calling, create an API key in the Console and bind it to GPT-Image. A key from another group returns 403 permission_error on image endpoints. /v1/models is the source of truth for models available to the key. See Models and pricing.
Generate images
Endpoint
POST https://api.sakrylle.com/v1/images/generationsHeaders
| Name | Required | Description |
|---|---|---|
Authorization | Yes | Bearer sk-xxxxxxxxxxxxxxxx |
Content-Type | Yes | application/json |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
model | string | Yes | Image model ID, determined by the group configuration |
prompt | string | Yes | Text prompt |
n | integer | No | Number of images, defaults to 1 |
size | string | No | e.g. 1024x1024 / 1024x1792 / 1792x1024 |
quality | string | No | Quality tier; values depend on the model (e.g. standard / hd) |
response_format | string | No | url or b64_json |
user | string | No | End-user identifier |
style | string | No | Style |
background | string | No | Transparent / opaque (model-dependent) |
output_format | string | No | Output format (model-dependent) |
output_compression | integer | No | Output compression level (model-dependent) |
The gateway validates
model,prompt,size,response_format,n,quality,background,style,output_format,output_compression,moderation,input_fidelity, andpartial_images. Any other field is dropped before forwarding upstream.
Example request
{
"model": "gpt-image-2",
"prompt": "A small cat meditating under a cherry blossom tree, watercolor style",
"n": 1,
"size": "1024x1024",
"response_format": "url"
}Example response
{
"created": 1716350400,
"data": [
{
"url": "https://cdn.example.com/generated/abc123.png",
"revised_prompt": "A small cat meditating under a cherry blossom tree, watercolor style"
}
]
}With response_format=b64_json, the response includes a b64_json field containing the base64-encoded image.
Edit images
Endpoint
POST https://api.sakrylle.com/v1/images/editsHeaders
| Name | Required | Description |
|---|---|---|
Authorization | Yes | Bearer sk-xxxxxxxxxxxxxxxx |
Content-Type | Yes | multipart/form-data |
Form fields
| Field | Type | Required | Description |
|---|---|---|---|
model | string | Yes | Image edit model ID |
image | file | Yes | Source image — PNG / JPEG / WebP |
prompt | string | Yes | Description of the desired edit |
mask | file | No | Mask whose transparent region is replaced (same dimensions as image) |
n | integer | No | Number of outputs, defaults to 1 |
size | string | No | Output size |
response_format | string | No | url or b64_json |
user | string | No | End-user identifier |
Example response
Same shape as image generation: results are returned in the data array.
Errors
400 invalid_request_error— missingmodel/prompt, or invalid field (e.g.nis not a positive integer)401 authentication_error— invalid API key403 permission_error— API key is not bound to the GPT-Image group (or the group does not have image capability enabled)403 billing_error— balance or plan quota exhausted429 rate_limit_error— concurrency or rate limit502 upstream_error— upstream repeatedly failed, please retry later
For the full table, see Errors.
Code samples
curl https://api.sakrylle.com/v1/images/generations \
-H "Authorization: Bearer sk-xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "A cat under cherry blossoms, watercolor",
"size": "1024x1024",
"n": 1
}'curl https://api.sakrylle.com/v1/images/edits \
-H "Authorization: Bearer sk-xxxxxxxxxxxxxxxx" \
-F model=gpt-image-2 \
-F image=@./input.png \
-F mask=@./mask.png \
-F prompt="Replace the background with a blue sky"from openai import OpenAI
client = OpenAI(
api_key="sk-xxxxxxxxxxxxxxxx",
base_url="https://api.sakrylle.com/v1",
)
# Generate
resp = client.images.generate(
model="gpt-image-2",
prompt="A cat under cherry blossoms, watercolor",
size="1024x1024",
n=1,
)
print(resp.data[0].url)
# Edit
edit = client.images.edit(
model="gpt-image-2",
image=open("input.png", "rb"),
mask=open("mask.png", "rb"),
prompt="Replace the background with a blue sky",
)
print(edit.data[0].url)import OpenAI from "openai";
import fs from "node:fs";
const client = new OpenAI({
apiKey: "sk-xxxxxxxxxxxxxxxx",
baseURL: "https://api.sakrylle.com/v1",
});
// Generate
const resp = await client.images.generate({
model: "gpt-image-2",
prompt: "A cat under cherry blossoms",
size: "1024x1024",
});
console.log(resp.data[0].url);
// Edit
const edit = await client.images.edit({
model: "gpt-image-2",
image: fs.createReadStream("input.png"),
mask: fs.createReadStream("mask.png"),
prompt: "Replace the background with a blue sky",
});
console.log(edit.data[0].url);package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
body := []byte(`{"model":"gpt-image-2","prompt":"A cat under cherry blossoms","size":"1024x1024"}`)
req, _ := http.NewRequest("POST",
"https://api.sakrylle.com/v1/images/generations",
bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer sk-xxxxxxxxxxxxxxxx")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(string(out))
}use reqwest::Client;
use serde_json::json;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let client = Client::new();
let resp: serde_json::Value = client
.post("https://api.sakrylle.com/v1/images/generations")
.bearer_auth("sk-xxxxxxxxxxxxxxxx")
.json(&json!({
"model": "gpt-image-2",
"prompt": "A cat under cherry blossoms",
"size": "1024x1024"
}))
.send()
.await?
.json()
.await?;
println!("{resp:#}");
Ok(())
}import java.net.URI;
import java.net.http.*;
public class Images {
public static void main(String[] args) throws Exception {
String body = """
{"model":"gpt-image-2","prompt":"A cat under cherry blossoms","size":"1024x1024"}
""";
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.sakrylle.com/v1/images/generations"))
.header("Authorization", "Bearer sk-xxxxxxxxxxxxxxxx")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());
}
}using System.Net.Http.Headers;
using System.Text;
var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "sk-xxxxxxxxxxxxxxxx");
var payload = """
{"model":"gpt-image-2","prompt":"A cat under cherry blossoms","size":"1024x1024"}
""";
var resp = await http.PostAsync(
"https://api.sakrylle.com/v1/images/generations",
new StringContent(payload, Encoding.UTF8, "application/json"));
Console.WriteLine(await resp.Content.ReadAsStringAsync());