Skip to main content
Singularity Layer Grid image generation turns a text prompt into one PNG. It runs the pinned flux2-klein-4b-q4 model (FLUX.2 klein 4B, 4-bit, Apache-2.0) on a capability-qualified, attested provider node. The prompt is sealed to that node on your side, and the result is sealed back to you, so the Grid never sees either in plaintext. See the content rules for what you can and cannot generate. To make images locally or serve them as a provider, see the Singularity Node desktop app.

At a glance

The quote is max(0.002, ceil6(width * height / 1e6 * 4 * 0.0015)) in USD.

Request flow

Image generation uses three requests: reserve, submit, poll.
  1. POST /v1/images/reserve sends metadata only. It returns a ready node, the node’s verified keys, a quote, and a reservation_token.
  2. The client verifies the node key binding, seals the prompt to the node, and sends POST /v1/images/generations with the token and the sealed envelope. The response is 202 with a job_id and a poll_url.
  3. GET /v1/images/generations/<job_id> every 5 seconds until status is completed. The sealed PNG is returned once, along with the node’s signature over the ciphertext. The client verifies the signature, then opens the result locally.
Authenticate every request with your API key (X-API-Key: x402c_...) or a session token (Authorization: Bearer sgl_sess...).

1. Reserve

POST /v1/images/reserve (JSON body, 16 KiB cap).
The response echoes your request and pins (model_revision, model_sha256, image_protocol), and adds reservation_token, node_id, node_ed25519_pubkey, node_x25519_pubkey, node_x25519_pubkey_sig, key_version, attestation_verified, and a quote object with price_usd.
Before sealing, verify that node_x25519_pubkey_sig is a valid Ed25519 signature by node_ed25519_pubkey over the key binding (node_id, key_version, and the X25519 key), and that the echoed fields match what you asked for. Refuse to seal if either check fails.

2. Seal and submit

Build this plaintext JSON with the keys in exactly this order:
seed is null when you did not send one. prompt.bytes is the UTF-8 byte count, not the character count. Generate a fresh X25519 response keypair, then seal the plaintext to node_x25519_pubkey with the x25519-xchacha20poly1305-hkdf-v2 algorithm. The ciphertext must decode to exactly len(canonical JSON with data = "") + 4 * ceil(bytes / 3) + 40 bytes, or the orchestrator rejects it. Use the SDK helper where available so the canonical form and sealing stay consistent. POST /v1/images/generations (JSON body, 64 KiB cap) takes exactly two fields:
A successful submit returns 202:
estimated_seconds is a conservative upper bound. Typical jobs finish in about 60 to 75 seconds. Credits are held at submit and settled only when the image is delivered. A failed job refunds the hold.

3. Poll and open

GET /v1/images/generations/<job_id> returns status of queued, running, completed, failed, or expired. Only the same account and the same API key that submitted the job can read it; anything else returns 404. When status is completed, the response includes sealed_result (algorithm, encoding, ciphertext, ephemeral_public_key), result_envelope_signature, node_id, and usage.cost_usd. Then:
  1. Check node_id matches the reserved node.
  2. Verify result_envelope_signature with the reserved node_ed25519_pubkey over sgl-result-v1\n<job_id>\nimage\n<sha256 hex of the ciphertext string>.
  3. Open the ciphertext with your response secret key and ephemeral_public_key.
  4. The plaintext is one JSON header line, a newline, then the PNG bytes. Check the header (protocol, request_id, job_id, model, model_revision, model_sha256, width, height, prompt_bytes, image.sha256, image.bytes) against what you sent, and check the PNG magic and dimensions.
Fetch and save the result promptly. It is purged 5 minutes after the first delivery and 30 minutes after completion at the latest. After that, polling returns expired.

Complete client

A minimal Node 20+ client for the whole flow. It uses only published packages (@noble/curves, @noble/ciphers, @noble/hashes, bs58). Save it as image-client.mjs, then run SGL_API_KEY=x402c_... node image-client.mjs. It writes out.png.
The seal key is HKDF-SHA256(x25519 shared secret, salt "sgl-e2e-v2-salt", info "sgl-e2e-v2-input") and the output key uses info sgl-e2e-v2-output. The AAD binds the node key, your ephemeral key and your response key, so a sealed prompt cannot be replayed against another key.

Errors

A failed job reports failure_reason such as image_input_invalid or image_runtime_failed, and the credit hold is refunded.