Goodtake AI

Stream (SSE)

Server-Sent Events stream for real-time generation status

Endpoint

GET /v1/image/generations/{id}/stream

Opens a text/event-stream connection that delivers real-time status updates for an in-progress generation.

Behaviour

  • Each data: frame is a full result object (same shape as the poll endpoint)
  • A : heartbeat comment is sent every 15 seconds to keep the connection alive
  • The stream closes on any terminal status: completed, failed, cancelled, timeout
  • The final completed frame carries the signed images array

Example stream

data: {"id":"550e8400-...","status":"processing","model":"gpt-image-2","prompt":"...","images":[],"cost_credits":0}

: heartbeat

data: {"id":"550e8400-...","status":"completed","model":"gpt-image-2","prompt":"...","images":[{"url":"https://...signed...","width":1024,"height":1024}],"cost_credits":0.1,"completed_at":"2026-06-22T10:00:18Z"}

Usage

# Open a stream after submitting a generation
ID=$(curl -s -X POST https://api.goodtake.ai/v1/image/generate \
  -H "Authorization: Bearer $GOODTAKE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model_identifier":"gpt-image-2","prompt":"a red fox in snow"}' \
  | jq -r .id)

curl -N "https://api.goodtake.ai/v1/image/generations/$ID/stream" \
  -H "Authorization: Bearer $GOODTAKE_API_KEY"

JavaScript (EventSource)

const es = new EventSource(
  `https://api.goodtake.ai/v1/image/generations/${id}/stream`,
  { headers: { Authorization: `Bearer ${process.env.GOODTAKE_API_KEY}` } }
);

es.onmessage = (event) => {
  const result = JSON.parse(event.data);
  if (result.status === "completed") {
    console.log("Images:", result.images);
    es.close();
  } else if (result.status === "failed") {
    console.error("Error:", result.error_message);
    es.close();
  }
};

Python (sseclient)

import sseclient, requests, json, os

url = f"https://api.goodtake.ai/v1/image/generations/{generation_id}/stream"
resp = requests.get(url, headers={"Authorization": f"Bearer {os.environ['GOODTAKE_API_KEY']}"}, stream=True)
client = sseclient.SSEClient(resp)

for event in client.events():
    if event.data:
        result = json.loads(event.data)
        if result["status"] in ("completed", "failed", "cancelled", "timeout"):
            print(result)
            break

Timeout recovery

Some MCP clients (e.g. Claude.ai) have a 30-second HTTP timeout. If the connection drops mid-poll, store the id from the original job and resume with:

curl -s "https://api.goodtake.ai/v1/image/generations/$ID" \
  -H "Authorization: Bearer $GOODTAKE_API_KEY" | jq .

On this page