{"components":{"headers":{"CacheControlHeader":{"description":"Output cache policy.","schema":{"example":"private, max-age=300","type":"string"}},"EtagHeader":{"description":"Strong SHA-256 ETag for output bytes.","schema":{"example":"\"sha256-abc123\"","type":"string"}},"RequestIdResponseHeader":{"description":"Request correlation id echoed from a valid client value or generated by the orchestrator.","schema":{"maxLength":128,"minLength":1,"type":"string"}},"RetryAfterHeader":{"description":"Seconds to wait before retrying a rate-limited request.","schema":{"minimum":1,"type":"integer"}}},"parameters":{"ApiClientIdPath":{"in":"path","name":"client_id","required":true,"schema":{"format":"uuid","type":"string"}},"ApiKeyIdPath":{"in":"path","name":"api_key_id","required":true,"schema":{"format":"uuid","type":"string"}},"IdempotencyKeyHeader":{"description":"Client-generated operation id. Same credential + key + request body replays the original task_id. Maximum 255 printable ASCII bytes.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"pattern":"^[!-~]+$","type":"string"}},"IfNoneMatchHeader":{"description":"Optional output ETag cache validator.","in":"header","name":"If-None-Match","required":false,"schema":{"type":"string"}},"JobIdPath":{"in":"path","name":"job_id","required":true,"schema":{"format":"uuid","type":"string"}},"OutputExpiresQuery":{"description":"Unix expiry timestamp issued with a signed task-result URL. Required when signature is present.","in":"query","name":"expires","required":false,"schema":{"format":"int64","minimum":1,"type":"integer"}},"OutputFileNamePath":{"in":"path","name":"file_name","required":true,"schema":{"pattern":"^output-[1-4](\\.(png|jpg|jpeg|webp)|-thumb\\.jpg)$","type":"string"}},"OutputSignatureQuery":{"description":"URL-safe HMAC-SHA256 signature bound to job id, file name, expiry and client id. Required when expires is present.","in":"query","name":"signature","required":false,"schema":{"maxLength":128,"minLength":1,"type":"string"}},"RequestIdHeader":{"description":"Optional client correlation id. Printable ASCII up to 128 bytes; missing or invalid values are replaced with a generated UUID.","in":"header","name":"X-Request-Id","required":false,"schema":{"maxLength":128,"minLength":1,"pattern":"^[!-~]+$","type":"string"}},"RequestLogLimitQuery":{"description":"Maximum number of recent request logs to return. Defaults to 250.","in":"query","name":"limit","required":false,"schema":{"maximum":5000,"minimum":1,"type":"integer"}},"TaskIdPath":{"in":"path","name":"task_id","required":true,"schema":{"pattern":"^task_[0-9a-fA-F-]{36}$","type":"string"}},"UsageClientIdQuery":{"description":"Admin-only filter for a single API client.","in":"query","name":"client_id","required":false,"schema":{"format":"uuid","type":"string"}},"UsageFromQuery":{"description":"Inclusive RFC3339 lower bound. Defaults to 24 hours before to.","in":"query","name":"from","required":false,"schema":{"format":"date-time","type":"string"}},"UsageToQuery":{"description":"Exclusive RFC3339 upper bound. Defaults to the current server time.","in":"query","name":"to","required":false,"schema":{"format":"date-time","type":"string"}},"WebhookDeliveryIdPath":{"in":"path","name":"delivery_id","required":true,"schema":{"format":"uuid","type":"string"}},"WebhookEndpointIdPath":{"in":"path","name":"endpoint_id","required":true,"schema":{"format":"uuid","type":"string"}}},"schemas":{"ApiClientListResponse":{"properties":{"clients":{"items":{"$ref":"#/components/schemas/ApiClientView"},"type":"array"}},"required":["clients"],"type":"object"},"ApiClientPolicy":{"additionalProperties":false,"properties":{"allowed_models":{"items":{"maxLength":240,"minLength":1,"type":"string"},"type":"array"},"allowed_providers":{"items":{"enum":["codex","google_vertex"],"type":"string"},"type":"array"},"daily_image_quota":{"maximum":100000000,"minimum":0,"type":"integer"},"max_concurrent_jobs":{"maximum":10000,"minimum":0,"type":"integer"},"max_n":{"maximum":4,"minimum":1,"type":"integer"},"output_retention_days":{"maximum":3650,"minimum":1,"type":"integer"},"rate_limit_per_minute":{"maximum":1000000,"minimum":0,"type":"integer"}},"type":"object"},"ApiClientStatus":{"enum":["active","disabled"],"type":"string"},"ApiClientView":{"properties":{"created_at":{"format":"date-time","type":"string"},"disabled_at":{"format":"date-time","type":["string","null"]},"id":{"format":"uuid","type":"string"},"name":{"type":"string"},"policy":{"$ref":"#/components/schemas/ApiClientPolicy"},"status":{"$ref":"#/components/schemas/ApiClientStatus"},"updated_at":{"format":"date-time","type":"string"}},"required":["id","name","status","policy","created_at","updated_at"],"type":"object"},"ApiError":{"properties":{"code":{"type":"string"},"kind":{"enum":["bad_request","unauthorized","not_logged_in","worker_unavailable","worker_busy","upstream","timeout","internal"],"type":"string"},"message":{"type":"string"},"request_id":{"maxLength":128,"minLength":1,"type":"string"},"type":{"$ref":"#/components/schemas/PublicErrorType"}},"required":["kind","message","type","request_id"],"type":"object"},"ApiKeyListResponse":{"properties":{"api_keys":{"items":{"$ref":"#/components/schemas/ApiKeyView"},"type":"array"}},"required":["api_keys"],"type":"object"},"ApiKeyView":{"properties":{"allowed_ips":{"items":{"type":"string"},"type":"array"},"client_id":{"format":"uuid","type":"string"},"client_name":{"type":["string","null"]},"created_at":{"format":"date-time","type":"string"},"expires_at":{"format":"date-time","type":["string","null"]},"id":{"format":"uuid","type":"string"},"key_prefix":{"example":"gpi_live_abc123def456","type":"string"},"last_used_at":{"format":"date-time","type":["string","null"]},"name":{"type":"string"},"revoked_at":{"format":"date-time","type":["string","null"]},"scopes":{"items":{"type":"string"},"type":"array"},"status":{"enum":["active","expired","revoked"],"type":"string"}},"required":["id","name","key_prefix","scopes","allowed_ips","client_id","status","created_at"],"type":"object"},"CreateApiClientRequest":{"additionalProperties":false,"properties":{"name":{"maxLength":120,"minLength":1,"type":"string"},"policy":{"$ref":"#/components/schemas/ApiClientPolicy"}},"required":["name"],"type":"object"},"CreateApiClientResponse":{"properties":{"client":{"$ref":"#/components/schemas/ApiClientView"}},"required":["client"],"type":"object"},"CreateApiKeyRequest":{"properties":{"allowed_ips":{"description":"Optional IP/CIDR allowlist for this key. Empty or omitted means any client IP is allowed.","items":{"type":"string"},"maxItems":64,"type":"array"},"client_id":{"description":"Optional API client id. Defaults to the built-in default client for backward compatibility.","format":"uuid","type":"string"},"expires_at":{"format":"date-time","type":["string","null"]},"name":{"maxLength":80,"minLength":1,"type":"string"},"scopes":{"items":{"enum":["images:write","tasks:read","outputs:read","admin:read","admin:write"],"type":"string"},"type":"array"}},"required":["name"],"type":"object"},"CreateApiKeyResponse":{"properties":{"api_key":{"$ref":"#/components/schemas/ApiKeyView"},"secret":{"description":"Returned once at creation and never listed again.","type":"string"}},"required":["api_key","secret"],"type":"object"},"CreateWebhookEndpointRequest":{"properties":{"description":{"maxLength":160,"type":["string","null"]},"url":{"description":"HTTPS endpoint URL. Private, loopback, link-local and Docker-internal targets are blocked unless WEBHOOK_ALLOW_LOCAL_TARGETS is enabled.","format":"uri","maxLength":2048,"type":"string"}},"required":["url"],"type":"object"},"CreateWebhookEndpointResponse":{"properties":{"endpoint":{"$ref":"#/components/schemas/WebhookEndpointView"},"signing_secret":{"description":"Returned once at creation. Store it server-side to verify webhook signatures.","type":"string"}},"required":["endpoint","signing_secret"],"type":"object"},"DisableApiClientResponse":{"properties":{"client":{"$ref":"#/components/schemas/ApiClientView"}},"required":["client"],"type":"object"},"ImageGenerationRequest":{"additionalProperties":true,"properties":{"action":{"enum":["generate","edit"],"type":"string"},"background":{"type":"string"},"image_model":{"type":"string"},"image_urls":{"default":[],"items":{"type":"string"},"maxItems":16,"type":"array"},"input_fidelity":{"type":"string"},"instructions":{"type":"string"},"main_model":{"type":"string"},"mask_image":{"type":"string"},"model":{"default":"gpt-image-2","type":"string"},"moderation":{"type":"string"},"n":{"default":1,"maximum":4,"minimum":1,"type":"integer"},"official_fallback":{"default":false,"type":"boolean"},"orientation":{"type":"string"},"output_compression":{"maximum":100,"minimum":0,"type":"integer"},"output_format":{"default":"png","enum":["png","jpeg","jpg","webp"],"type":"string"},"partial_images":{"maximum":4,"minimum":1,"type":"integer"},"prompt":{"minLength":1,"type":"string"},"prompt_fidelity":{"default":"strict","enum":["strict","original","off"],"type":"string"},"prompt_for_model":{"type":"string"},"provider":{"default":"codex","enum":["codex","google_vertex"],"type":"string"},"quality":{"type":"string"},"ratio":{"type":"string"},"reference_images":{"default":[],"items":{"type":"string"},"maxItems":16,"type":"array"},"resolution":{"default":"1k","enum":["1k","2k","4k"],"type":"string"},"size":{"description":"auto, aspect ratio such as 16:9, or direct pixel size such as 1280x720.","type":"string"},"web_search":{"default":false,"type":"boolean"}},"required":["prompt"],"type":"object"},"PublicErrorDetail":{"properties":{"code":{"type":"integer"},"message":{"type":"string"},"request_id":{"maxLength":128,"minLength":1,"type":"string"},"type":{"enum":["invalid_request","unauthorized","forbidden","not_found","output_expired","idempotency_conflict","rate_limited","worker_unavailable","provider_quota_limited","provider_auth_failed","provider_rejected","timeout","internal_error"],"type":"string"}},"required":["code","message","type","request_id"],"type":"object"},"PublicErrorResponse":{"properties":{"code":{"type":"integer"},"error":{"$ref":"#/components/schemas/PublicErrorDetail"}},"required":["code","error"],"type":"object"},"PublicErrorType":{"enum":["invalid_request","unauthorized","forbidden","not_found","output_expired","idempotency_conflict","rate_limited","worker_unavailable","provider_quota_limited","provider_auth_failed","provider_rejected","timeout","internal_error"],"type":"string"},"ReplayWebhookDeliveryResponse":{"properties":{"delivery":{"$ref":"#/components/schemas/WebhookDeliveryView"}},"required":["delivery"],"type":"object"},"RequestLogRecord":{"properties":{"api_key_id":{"format":"uuid","type":["string","null"]},"client_id":{"format":"uuid","type":["string","null"]},"client_ip":{"description":"Resolved client IP. Forwarded headers are trusted only when TRUST_PROXY_HEADERS=1.","type":["string","null"]},"created_at":{"format":"date-time","type":"string"},"id":{"format":"uuid","type":"string"},"method":{"type":"string"},"path":{"type":"string"},"request_id":{"maxLength":128,"minLength":1,"type":"string"},"status_code":{"maximum":599,"minimum":100,"type":"integer"}},"required":["id","request_id","method","path","status_code","created_at"],"type":"object"},"RequestLogsResponse":{"properties":{"requests":{"items":{"$ref":"#/components/schemas/RequestLogRecord"},"type":"array"}},"required":["requests"],"type":"object"},"RevokeApiKeyResponse":{"properties":{"api_key":{"$ref":"#/components/schemas/ApiKeyView"}},"required":["api_key"],"type":"object"},"RevokeWebhookEndpointResponse":{"properties":{"endpoint":{"$ref":"#/components/schemas/WebhookEndpointView"}},"required":["endpoint"],"type":"object"},"SubmitData":{"properties":{"status":{"enum":["submitted"],"type":"string"},"task_id":{"pattern":"^task_[0-9a-fA-F-]{36}$","type":"string"}},"required":["status","task_id"],"type":"object"},"SubmitResponse":{"properties":{"code":{"const":200,"type":"integer"},"data":{"items":{"$ref":"#/components/schemas/SubmitData"},"maxItems":1,"minItems":1,"type":"array"}},"required":["code","data"],"type":"object"},"TaskData":{"properties":{"actual_time":{"minimum":0,"type":"integer"},"completed":{"type":"integer"},"created":{"type":"integer"},"error":{"$ref":"#/components/schemas/PublicErrorDetail"},"estimated_time":{"minimum":0,"type":"integer"},"id":{"pattern":"^task_[0-9a-fA-F-]{36}$","type":"string"},"metadata":{"additionalProperties":true,"type":"object"},"progress":{"maximum":100,"minimum":0,"type":"integer"},"result":{"$ref":"#/components/schemas/TaskResult"},"status":{"enum":["pending","processing","completed","failed"],"type":"string"}},"required":["id","status","progress","created","estimated_time"],"type":"object"},"TaskImage":{"properties":{"expires_at":{"format":"date-time","type":["string","null"]},"url":{"items":{"format":"uri-reference","type":"string"},"minItems":1,"type":"array"}},"required":["url","expires_at"],"type":"object"},"TaskResponse":{"properties":{"code":{"const":200,"type":"integer"},"data":{"$ref":"#/components/schemas/TaskData"}},"required":["code","data"],"type":"object"},"TaskResult":{"properties":{"images":{"items":{"$ref":"#/components/schemas/TaskImage"},"type":"array"}},"required":["images"],"type":"object"},"UsageEvent":{"properties":{"api_key_id":{"format":"uuid","type":["string","null"]},"client_id":{"format":"uuid","type":"string"},"created_at":{"format":"date-time","type":"string"},"duration_ms":{"minimum":0,"type":["integer","null"]},"event_type":{"enum":["output.completed","output.failed"],"type":"string"},"id":{"format":"uuid","type":"string"},"image_count":{"minimum":0,"type":"integer"},"image_model":{"type":"string"},"input_tokens":{"minimum":0,"type":"integer"},"job_id":{"format":"uuid","type":"string"},"output_index":{"maximum":4,"minimum":1,"type":["integer","null"]},"output_tokens":{"minimum":0,"type":"integer"},"provider":{"enum":["codex","google_vertex"],"type":"string"},"status":{"$ref":"#/components/schemas/UsageEventStatus"},"task_id":{"pattern":"^task_[0-9a-fA-F-]{36}$","type":"string"},"total_tokens":{"minimum":0,"type":"integer"},"web_search_requests":{"minimum":0,"type":"integer"}},"required":["id","client_id","job_id","task_id","event_type","provider","image_model","status","image_count","input_tokens","output_tokens","total_tokens","web_search_requests","created_at"],"type":"object"},"UsageEventStatus":{"enum":["succeeded","failed"],"type":"string"},"UsageEventsResponse":{"properties":{"events":{"items":{"$ref":"#/components/schemas/UsageEvent"},"type":"array"},"from":{"format":"date-time","type":"string"},"to":{"format":"date-time","type":"string"}},"required":["from","to","events"],"type":"object"},"WebhookDeliveriesResponse":{"properties":{"deliveries":{"items":{"$ref":"#/components/schemas/WebhookDeliveryView"},"type":"array"}},"required":["deliveries"],"type":"object"},"WebhookDeliveryStatus":{"enum":["pending","retrying","delivered","failed"],"type":"string"},"WebhookDeliveryView":{"properties":{"attempt_count":{"minimum":0,"type":"integer"},"created_at":{"format":"date-time","type":"string"},"delivered_at":{"format":"date-time","type":["string","null"]},"endpoint_id":{"format":"uuid","type":"string"},"endpoint_url":{"format":"uri","type":"string"},"error_message":{"type":["string","null"]},"event_id":{"type":"string"},"http_status":{"maximum":599,"minimum":100,"type":["integer","null"]},"id":{"format":"uuid","type":"string"},"job_id":{"format":"uuid","type":"string"},"next_attempt_at":{"format":"date-time","type":["string","null"]},"output_index":{"maximum":4,"minimum":1,"type":["integer","null"]},"status":{"$ref":"#/components/schemas/WebhookDeliveryStatus"},"task_id":{"type":"string"},"type":{"$ref":"#/components/schemas/WebhookEventType"},"updated_at":{"format":"date-time","type":"string"}},"required":["id","endpoint_id","endpoint_url","event_id","type","task_id","job_id","status","attempt_count","created_at","updated_at"],"type":"object"},"WebhookEndpointView":{"properties":{"created_at":{"format":"date-time","type":"string"},"description":{"type":["string","null"]},"enabled":{"type":"boolean"},"id":{"format":"uuid","type":"string"},"last_delivery_at":{"format":"date-time","type":["string","null"]},"revoked_at":{"format":"date-time","type":["string","null"]},"updated_at":{"format":"date-time","type":"string"},"url":{"format":"uri","type":"string"}},"required":["id","url","enabled","created_at","updated_at"],"type":"object"},"WebhookEndpointsResponse":{"properties":{"endpoints":{"items":{"$ref":"#/components/schemas/WebhookEndpointView"},"type":"array"}},"required":["endpoints"],"type":"object"},"WebhookEventType":{"enum":["task.completed","task.failed","task.partial_failed","output.ready"],"type":"string"},"WebhookEventView":{"properties":{"created_at":{"format":"date-time","type":"string"},"id":{"pattern":"^evt_[0-9a-f]{32}$","type":"string"},"job_id":{"format":"uuid","type":"string"},"output_index":{"maximum":4,"minimum":1,"type":["integer","null"]},"task_id":{"pattern":"^task_[0-9a-fA-F-]{36}$","type":"string"},"type":{"$ref":"#/components/schemas/WebhookEventType"}},"required":["id","type","task_id","job_id","created_at"],"type":"object"},"WebhookEventsResponse":{"properties":{"events":{"items":{"$ref":"#/components/schemas/WebhookEventView"},"type":"array"}},"required":["events"],"type":"object"}},"securitySchemes":{"BearerAuth":{"bearerFormat":"API key or legacy token","description":"Use Authorization: Bearer <token>. Local/dev deployments may run without auth until a token or active managed key exists.","scheme":"bearer","type":"http"},"SignedOutputUrl":{"description":"Temporary HMAC signature issued in task result URLs. The matching expires query parameter is also required.","in":"query","name":"signature","type":"apiKey"}}},"info":{"description":"The /v1 API is the stable public integration surface. Additive fields may be introduced within /v1, while breaking request or response changes require a new version prefix such as /v2.","summary":"Public image generation, task polling, output retrieval and API key administration contract.","title":"GPT Image Orchestrator Public API","version":"1.0.0"},"jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","openapi":"3.1.0","paths":{"/openapi.json":{"get":{"operationId":"getOpenApiContract","parameters":[{"$ref":"#/components/parameters/RequestIdHeader"}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"OpenAPI 3.1 document for the public integration API.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"security":[],"summary":"Get the OpenAPI 3.1 contract","tags":["Contract"]}},"/v1/api-keys":{"get":{"operationId":"listApiKeys","parameters":[{"$ref":"#/components/parameters/RequestIdHeader"}],"responses":{"200":{"content":{"application/json":{"example":{"api_keys":[{"allowed_ips":["203.0.113.10","203.0.113.0/24"],"client_id":"440e8400-e29b-41d4-a716-446655440000","client_name":"partner-a","created_at":"2026-07-06T00:00:00Z","expires_at":null,"id":"550e8400-e29b-41d4-a716-446655440000","key_prefix":"gpi_live_abc123def456","last_used_at":null,"name":"images-client","revoked_at":null,"scopes":["images:write","tasks:read","outputs:read"],"status":"active"}]},"schema":{"$ref":"#/components/schemas/ApiKeyListResponse"}}},"description":"Managed API key views. Secrets and digests are never returned.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"API key does not grant the required scope","request_id":"client-request-123","type":"forbidden"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Credential is valid but lacks admin scope.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"summary":"List managed API keys","tags":["Admin API Keys"]},"post":{"operationId":"createApiKey","parameters":[{"$ref":"#/components/parameters/RequestIdHeader"}],"requestBody":{"content":{"application/json":{"examples":{"createImagesClient":{"value":{"allowed_ips":["203.0.113.10","203.0.113.0/24"],"client_id":"440e8400-e29b-41d4-a716-446655440000","expires_at":null,"name":"images-client","scopes":["images:write","tasks:read","outputs:read"]}}},"schema":{"$ref":"#/components/schemas/CreateApiKeyRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"api_key":{"allowed_ips":["203.0.113.10","203.0.113.0/24"],"client_id":"440e8400-e29b-41d4-a716-446655440000","client_name":"partner-a","created_at":"2026-07-06T00:00:00Z","expires_at":null,"id":"550e8400-e29b-41d4-a716-446655440000","key_prefix":"gpi_live_abc123def456","last_used_at":null,"name":"images-client","revoked_at":null,"scopes":["images:write","tasks:read","outputs:read"],"status":"active"},"secret":"gpi_live_abc123def456_example-secret-returned-once"},"schema":{"$ref":"#/components/schemas/CreateApiKeyResponse"}}},"description":"API key created. The secret is returned once and is not recoverable later.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"400":{"content":{"application/json":{"example":{"kind":"bad_request","message":"name must contain between 1 and 80 characters","request_id":"client-request-123","type":"invalid_request"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Invalid API key creation request.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"API key does not grant the required scope","request_id":"client-request-123","type":"forbidden"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Credential is valid but lacks admin scope.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"summary":"Create a managed API key","tags":["Admin API Keys"]}},"/v1/api-keys/{api_key_id}":{"delete":{"operationId":"revokeApiKey","parameters":[{"$ref":"#/components/parameters/ApiKeyIdPath"},{"$ref":"#/components/parameters/RequestIdHeader"}],"responses":{"200":{"content":{"application/json":{"example":{"api_key":{"allowed_ips":["203.0.113.10","203.0.113.0/24"],"client_id":"440e8400-e29b-41d4-a716-446655440000","client_name":"partner-a","created_at":"2026-07-06T00:00:00Z","expires_at":null,"id":"550e8400-e29b-41d4-a716-446655440000","key_prefix":"gpi_live_abc123def456","last_used_at":null,"name":"images-client","revoked_at":null,"scopes":["images:write","tasks:read","outputs:read"],"status":"revoked"}},"schema":{"$ref":"#/components/schemas/RevokeApiKeyResponse"}}},"description":"API key revoked.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"API key does not grant the required scope","request_id":"client-request-123","type":"forbidden"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Credential is valid but lacks admin scope.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"404":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API key not found","request_id":"client-request-123","type":"not_found"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API key not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"summary":"Revoke a managed API key","tags":["Admin API Keys"]}},"/v1/clients":{"get":{"operationId":"listApiClients","parameters":[{"$ref":"#/components/parameters/RequestIdHeader"}],"responses":{"200":{"content":{"application/json":{"example":{"clients":[{"created_at":"2026-07-06T00:00:00Z","disabled_at":null,"id":"440e8400-e29b-41d4-a716-446655440000","name":"partner-a","policy":{"allowed_models":["gpt-image-2"],"allowed_providers":["codex"],"daily_image_quota":1000,"max_concurrent_jobs":4,"max_n":4,"output_retention_days":30,"rate_limit_per_minute":120},"status":"active","updated_at":"2026-07-06T00:00:00Z"}]},"schema":{"$ref":"#/components/schemas/ApiClientListResponse"}}},"description":"Registered API clients and their policy.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"API key does not grant the required scope","request_id":"client-request-123","type":"forbidden"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Credential is valid but lacks admin scope.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"summary":"List API clients","tags":["Admin Clients"]},"post":{"operationId":"createApiClient","parameters":[{"$ref":"#/components/parameters/RequestIdHeader"}],"requestBody":{"content":{"application/json":{"examples":{"createPartner":{"value":{"name":"partner-a","policy":{"allowed_models":["gpt-image-2"],"allowed_providers":["codex"],"daily_image_quota":1000,"max_concurrent_jobs":4,"max_n":4,"output_retention_days":30,"rate_limit_per_minute":120}}}},"schema":{"$ref":"#/components/schemas/CreateApiClientRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"client":{"created_at":"2026-07-06T00:00:00Z","disabled_at":null,"id":"440e8400-e29b-41d4-a716-446655440000","name":"partner-a","policy":{"allowed_models":["gpt-image-2"],"allowed_providers":["codex"],"daily_image_quota":1000,"max_concurrent_jobs":4,"max_n":4,"output_retention_days":30,"rate_limit_per_minute":120},"status":"active","updated_at":"2026-07-06T00:00:00Z"}},"schema":{"$ref":"#/components/schemas/CreateApiClientResponse"}}},"description":"API client created.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"400":{"content":{"application/json":{"example":{"kind":"bad_request","message":"name must contain between 1 and 120 characters","request_id":"client-request-123","type":"invalid_request"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Invalid API client creation request.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"API key does not grant the required scope","request_id":"client-request-123","type":"forbidden"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Credential is valid but lacks admin scope.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"summary":"Create an API client","tags":["Admin Clients"]}},"/v1/clients/{client_id}":{"delete":{"operationId":"disableApiClient","parameters":[{"$ref":"#/components/parameters/ApiClientIdPath"},{"$ref":"#/components/parameters/RequestIdHeader"}],"responses":{"200":{"content":{"application/json":{"example":{"client":{"created_at":"2026-07-06T00:00:00Z","disabled_at":"2026-07-06T01:00:00Z","id":"440e8400-e29b-41d4-a716-446655440000","name":"partner-a","policy":{"allowed_models":["gpt-image-2"],"allowed_providers":["codex"],"daily_image_quota":1000,"max_concurrent_jobs":4,"max_n":4,"output_retention_days":30,"rate_limit_per_minute":120},"status":"disabled","updated_at":"2026-07-06T00:00:00Z"}},"schema":{"$ref":"#/components/schemas/DisableApiClientResponse"}}},"description":"API client disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"400":{"content":{"application/json":{"example":{"kind":"bad_request","message":"default API client cannot be disabled","request_id":"client-request-123","type":"invalid_request"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Invalid API client operation.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"API key does not grant the required scope","request_id":"client-request-123","type":"forbidden"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Credential is valid but lacks admin scope.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"404":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API client not found","request_id":"client-request-123","type":"not_found"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API client not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"summary":"Disable an API client","tags":["Admin Clients"]}},"/v1/images/generations":{"post":{"operationId":"createImageGeneration","parameters":[{"$ref":"#/components/parameters/IdempotencyKeyHeader"},{"$ref":"#/components/parameters/RequestIdHeader"}],"requestBody":{"content":{"application/json":{"examples":{"textToImage":{"summary":"Text-to-image submit request","value":{"action":"generate","model":"gpt-image-2","n":1,"output_format":"png","prompt":"A quiet brutalist library at blue hour","prompt_fidelity":"strict","quality":"low","resolution":"2k","size":"16:9"}}},"schema":{"$ref":"#/components/schemas/ImageGenerationRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"examples":{"submitted":{"summary":"Submitted task","value":{"code":200,"data":[{"status":"submitted","task_id":"task_550e8400-e29b-41d4-a716-446655440000"}]}}},"schema":{"$ref":"#/components/schemas/SubmitResponse"}}},"description":"Task accepted. Replays with the same Idempotency-Key return this original response.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"400":{"content":{"application/json":{"example":{"code":400,"error":{"code":400,"message":"prompt is required","request_id":"client-request-123","type":"invalid_request"}},"schema":{"$ref":"#/components/schemas/PublicErrorResponse"}}},"description":"Malformed JSON or invalid request shape.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"code":401,"error":{"code":401,"message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"}},"schema":{"$ref":"#/components/schemas/PublicErrorResponse"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"code":403,"error":{"code":403,"message":"API key does not grant the required scope","request_id":"client-request-123","type":"forbidden"}},"schema":{"$ref":"#/components/schemas/PublicErrorResponse"}}},"description":"Credential is valid but lacks the required scope.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"409":{"content":{"application/json":{"example":{"code":409,"error":{"code":409,"message":"idempotency key reused with a different request body","request_id":"client-request-123","type":"idempotency_conflict"}},"schema":{"$ref":"#/components/schemas/PublicErrorResponse"}}},"description":"Idempotency-Key was reused with a different request body.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"code":429,"error":{"code":429,"message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"}},"schema":{"$ref":"#/components/schemas/PublicErrorResponse"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"500":{"content":{"application/json":{"example":{"code":500,"error":{"code":500,"message":"failed to persist new job state","request_id":"client-request-123","type":"internal_error"}},"schema":{"$ref":"#/components/schemas/PublicErrorResponse"}}},"description":"Internal server error.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"summary":"Submit an asynchronous image generation task","tags":["Images"]}},"/v1/jobs/{job_id}/outputs/{file_name}":{"get":{"description":"Authenticate with outputs:read Bearer/cookie credentials for an output owned by the same API client, use an admin scope, or use the expires and signature query parameters exactly as issued in a task response.","operationId":"getJobOutput","parameters":[{"$ref":"#/components/parameters/JobIdPath"},{"$ref":"#/components/parameters/OutputFileNamePath"},{"$ref":"#/components/parameters/OutputExpiresQuery"},{"$ref":"#/components/parameters/OutputSignatureQuery"},{"$ref":"#/components/parameters/IfNoneMatchHeader"},{"$ref":"#/components/parameters/RequestIdHeader"}],"responses":{"200":{"content":{"image/jpeg":{"schema":{"format":"binary","type":"string"}},"image/png":{"schema":{"format":"binary","type":"string"}},"image/webp":{"schema":{"format":"binary","type":"string"}}},"description":"Generated image bytes.","headers":{"Cache-Control":{"$ref":"#/components/headers/CacheControlHeader"},"ETag":{"$ref":"#/components/headers/EtagHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"304":{"description":"The supplied If-None-Match value matches the current output ETag.","headers":{"Cache-Control":{"$ref":"#/components/headers/CacheControlHeader"},"ETag":{"$ref":"#/components/headers/EtagHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"400":{"content":{"application/json":{"example":{"kind":"bad_request","message":"invalid output file name","request_id":"client-request-123","type":"invalid_request"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Invalid output file name.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"code":"signed_url_expired","kind":"unauthorized","message":"signed output URL has expired","request_id":"client-request-123","type":"forbidden"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Credential lacks scope or job access, or the signed URL is invalid or expired.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"404":{"content":{"application/json":{"example":{"kind":"bad_request","message":"output file not found for job","request_id":"client-request-123","type":"not_found"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Job or output file does not exist.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"410":{"content":{"application/json":{"example":{"code":"output_expired","kind":"bad_request","message":"output expired or deleted by retention policy","request_id":"client-request-123","type":"output_expired"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Output retention expired and the object is no longer available.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"500":{"content":{"application/json":{"example":{"kind":"internal","message":"failed to read output","request_id":"client-request-123","type":"internal_error"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Internal server error.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"security":[{"BearerAuth":[]},{"SignedOutputUrl":[]}],"summary":"Download generated image bytes","tags":["Outputs"]}},"/v1/request-logs":{"get":{"operationId":"listRequestLogs","parameters":[{"$ref":"#/components/parameters/RequestLogLimitQuery"},{"$ref":"#/components/parameters/RequestIdHeader"}],"responses":{"200":{"content":{"application/json":{"example":{"requests":[{"api_key_id":"550e8400-e29b-41d4-a716-446655440000","client_id":"440e8400-e29b-41d4-a716-446655440000","client_ip":"203.0.113.10","created_at":"2026-07-06T00:00:01Z","id":"660e8400-e29b-41d4-a716-446655440000","method":"POST","path":"/v1/images/generations","request_id":"client-request-123","status_code":200}]},"schema":{"$ref":"#/components/schemas/RequestLogsResponse"}}},"description":"Recent request audit rows with resolved client IP when available.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"API key does not grant the required scope","request_id":"client-request-123","type":"forbidden"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Credential is valid but lacks admin scope.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"summary":"List recent request logs","tags":["Request Logs"]}},"/v1/tasks/{task_id}":{"get":{"description":"Managed API keys can poll tasks owned by the same API client. Admin scopes and legacy bootstrap tokens can read any task.","operationId":"getImageTask","parameters":[{"$ref":"#/components/parameters/TaskIdPath"},{"$ref":"#/components/parameters/RequestIdHeader"}],"responses":{"200":{"content":{"application/json":{"examples":{"completed":{"summary":"Completed task","value":{"code":200,"data":{"actual_time":52,"completed":1776748726,"created":1776748674,"estimated_time":100,"id":"task_550e8400-e29b-41d4-a716-446655440000","progress":100,"result":{"images":[{"expires_at":"2026-07-06T12:34:56Z","url":["http://localhost:8022/v1/jobs/550e8400-e29b-41d4-a716-446655440000/outputs/output-1.png?expires=1783341296&signature=example-signature"]}]},"status":"completed"}}},"failed":{"summary":"Failed task","value":{"code":200,"data":{"actual_time":52,"completed":1776748726,"created":1776748674,"error":{"code":400,"message":"no online logged-in account slot available","request_id":"client-request-123","type":"worker_unavailable"},"estimated_time":100,"id":"task_550e8400-e29b-41d4-a716-446655440000","progress":100,"status":"failed"}}},"partialFailed":{"summary":"Partially failed task with successful images","value":{"code":200,"data":{"actual_time":52,"completed":1776748726,"created":1776748674,"estimated_time":100,"id":"task_550e8400-e29b-41d4-a716-446655440000","metadata":{"failed_count":1,"generated_count":1,"state":"partial_failed","warning":"task completed with partial image failures"},"progress":100,"result":{"images":[{"expires_at":"2026-07-06T12:34:56Z","url":["http://localhost:8022/v1/jobs/550e8400-e29b-41d4-a716-446655440000/outputs/output-1.png?expires=1783341296&signature=example-signature"]}]},"status":"completed"}}},"pending":{"summary":"Queued task","value":{"code":200,"data":{"created":1776748674,"estimated_time":100,"id":"task_550e8400-e29b-41d4-a716-446655440000","progress":0,"status":"pending"}}},"processing":{"summary":"Running task","value":{"code":200,"data":{"created":1776748674,"estimated_time":100,"id":"task_550e8400-e29b-41d4-a716-446655440000","progress":25,"status":"processing"}}},"providerAuthFailed":{"summary":"Provider authentication failure","value":{"code":200,"data":{"actual_time":52,"completed":1776748726,"created":1776748674,"error":{"code":502,"message":"HTTP 401 unauthorized from provider","request_id":"client-request-123","type":"provider_auth_failed"},"estimated_time":100,"id":"task_550e8400-e29b-41d4-a716-446655440000","progress":100,"status":"failed"}}},"providerQuotaFailed":{"summary":"Provider quota failure","value":{"code":200,"data":{"actual_time":52,"completed":1776748726,"created":1776748674,"error":{"code":502,"message":"insufficient_user_quota","request_id":"client-request-123","type":"provider_quota_limited"},"estimated_time":100,"id":"task_550e8400-e29b-41d4-a716-446655440000","progress":100,"status":"failed"}}}},"schema":{"$ref":"#/components/schemas/TaskResponse"}}},"description":"Current task snapshot. Failed tasks still return HTTP 200 with data.status = failed.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"400":{"content":{"application/json":{"example":{"code":400,"error":{"code":400,"message":"invalid task id","request_id":"client-request-123","type":"invalid_request"}},"schema":{"$ref":"#/components/schemas/PublicErrorResponse"}}},"description":"Invalid task id.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"code":401,"error":{"code":401,"message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"}},"schema":{"$ref":"#/components/schemas/PublicErrorResponse"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"code":403,"error":{"code":403,"message":"API key is not allowed to access this job","request_id":"client-request-123","type":"forbidden"}},"schema":{"$ref":"#/components/schemas/PublicErrorResponse"}}},"description":"Credential is valid but lacks the required scope or is not allowed to read this task.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"404":{"content":{"application/json":{"example":{"code":404,"error":{"code":404,"message":"task not found","request_id":"client-request-123","type":"not_found"}},"schema":{"$ref":"#/components/schemas/PublicErrorResponse"}}},"description":"Task id is valid but no task exists.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"code":429,"error":{"code":429,"message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"}},"schema":{"$ref":"#/components/schemas/PublicErrorResponse"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"500":{"content":{"application/json":{"example":{"code":500,"error":{"code":500,"message":"failed to load task","request_id":"client-request-123","type":"internal_error"}},"schema":{"$ref":"#/components/schemas/PublicErrorResponse"}}},"description":"Internal server error.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"summary":"Poll an image generation task","tags":["Tasks"]}},"/v1/usage":{"get":{"description":"Admin-scoped append-only usage ledger export. The time range is half-open: from is inclusive and to is exclusive.","operationId":"listUsageEvents","parameters":[{"$ref":"#/components/parameters/UsageFromQuery"},{"$ref":"#/components/parameters/UsageToQuery"},{"$ref":"#/components/parameters/UsageClientIdQuery"},{"$ref":"#/components/parameters/RequestIdHeader"}],"responses":{"200":{"content":{"application/json":{"example":{"events":[{"api_key_id":"550e8400-e29b-41d4-a716-446655440000","client_id":"440e8400-e29b-41d4-a716-446655440000","created_at":"2026-07-06T00:00:42Z","duration_ms":42000,"event_type":"output.completed","id":"880e8400-e29b-41d4-a716-446655440000","image_count":1,"image_model":"gpt-image-2","input_tokens":120,"job_id":"550e8400-e29b-41d4-a716-446655440000","output_index":1,"output_tokens":30,"provider":"codex","status":"succeeded","task_id":"task_550e8400-e29b-41d4-a716-446655440000","total_tokens":150,"web_search_requests":1}],"from":"2026-07-06T00:00:00Z","to":"2026-07-07T00:00:00Z"},"schema":{"$ref":"#/components/schemas/UsageEventsResponse"}}},"description":"Usage ledger events matching the supplied filters.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"400":{"content":{"application/json":{"example":{"kind":"bad_request","message":"usage from must be before to","request_id":"client-request-123","type":"invalid_request"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Invalid usage date range.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"API key does not grant the required scope","request_id":"client-request-123","type":"forbidden"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Credential is valid but lacks admin scope.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"summary":"Export usage ledger events","tags":["Usage"]}},"/v1/usage/self":{"get":{"description":"Client-scoped append-only usage ledger export. The caller must use a managed API key with tasks:read scope.","operationId":"listOwnUsageEvents","parameters":[{"$ref":"#/components/parameters/UsageFromQuery"},{"$ref":"#/components/parameters/UsageToQuery"},{"$ref":"#/components/parameters/RequestIdHeader"}],"responses":{"200":{"content":{"application/json":{"example":{"events":[{"api_key_id":"550e8400-e29b-41d4-a716-446655440000","client_id":"440e8400-e29b-41d4-a716-446655440000","created_at":"2026-07-06T00:00:42Z","duration_ms":42000,"event_type":"output.completed","id":"880e8400-e29b-41d4-a716-446655440000","image_count":1,"image_model":"gpt-image-2","input_tokens":120,"job_id":"550e8400-e29b-41d4-a716-446655440000","output_index":1,"output_tokens":30,"provider":"codex","status":"succeeded","task_id":"task_550e8400-e29b-41d4-a716-446655440000","total_tokens":150,"web_search_requests":1}],"from":"2026-07-06T00:00:00Z","to":"2026-07-07T00:00:00Z"},"schema":{"$ref":"#/components/schemas/UsageEventsResponse"}}},"description":"Usage ledger events for the authenticated API client.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"400":{"content":{"application/json":{"example":{"kind":"bad_request","message":"usage from must be before to","request_id":"client-request-123","type":"invalid_request"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Invalid usage date range.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"managed API key is required for client usage","request_id":"client-request-123","type":"forbidden"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Credential is valid but lacks tasks:read scope or is not attached to a managed API client.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"summary":"Export usage ledger events for the authenticated client","tags":["Usage"]}},"/v1/webhook-deliveries":{"get":{"operationId":"listWebhookDeliveries","parameters":[{"$ref":"#/components/parameters/RequestIdHeader"}],"responses":{"200":{"content":{"application/json":{"example":{"deliveries":[{"attempt_count":1,"created_at":"2026-07-06T00:00:05Z","delivered_at":"2026-07-06T00:00:06Z","endpoint_id":"660e8400-e29b-41d4-a716-446655440000","endpoint_url":"https://client.example.com/gpt-image/webhook","error_message":null,"event_id":"evt_550e8400e29b41d4a716446655440000","http_status":204,"id":"770e8400-e29b-41d4-a716-446655440000","job_id":"550e8400-e29b-41d4-a716-446655440000","next_attempt_at":null,"output_index":null,"status":"delivered","task_id":"task_550e8400-e29b-41d4-a716-446655440000","type":"task.completed","updated_at":"2026-07-06T00:00:06Z"}]},"schema":{"$ref":"#/components/schemas/WebhookDeliveriesResponse"}}},"description":"Webhook delivery state for debugging and support.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"API key does not grant the required scope","request_id":"client-request-123","type":"forbidden"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Credential is valid but lacks admin scope.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"summary":"List webhook delivery attempts","tags":["Admin Webhooks"]}},"/v1/webhook-deliveries/{delivery_id}/replay":{"post":{"operationId":"replayWebhookDelivery","parameters":[{"$ref":"#/components/parameters/WebhookDeliveryIdPath"},{"$ref":"#/components/parameters/RequestIdHeader"}],"responses":{"200":{"content":{"application/json":{"example":{"delivery":{"attempt_count":1,"created_at":"2026-07-06T00:00:05Z","delivered_at":null,"endpoint_id":"660e8400-e29b-41d4-a716-446655440000","endpoint_url":"https://client.example.com/gpt-image/webhook","error_message":null,"event_id":"evt_550e8400e29b41d4a716446655440000","http_status":null,"id":"770e8400-e29b-41d4-a716-446655440000","job_id":"550e8400-e29b-41d4-a716-446655440000","next_attempt_at":null,"output_index":null,"status":"pending","task_id":"task_550e8400-e29b-41d4-a716-446655440000","type":"task.completed","updated_at":"2026-07-06T00:00:06Z"}},"schema":{"$ref":"#/components/schemas/ReplayWebhookDeliveryResponse"}}},"description":"Failed delivery reset to pending and queued for retry.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"400":{"content":{"application/json":{"example":{"kind":"bad_request","message":"only failed webhook deliveries can be replayed","request_id":"client-request-123","type":"invalid_request"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Delivery is not failed.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"API key does not grant the required scope","request_id":"client-request-123","type":"forbidden"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Credential is valid but lacks admin scope.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"404":{"content":{"application/json":{"example":{"kind":"bad_request","message":"webhook delivery not found","request_id":"client-request-123","type":"not_found"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Webhook delivery not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"summary":"Replay a failed webhook delivery","tags":["Admin Webhooks"]}},"/v1/webhook-events":{"get":{"operationId":"listWebhookEvents","parameters":[{"$ref":"#/components/parameters/RequestIdHeader"}],"responses":{"200":{"content":{"application/json":{"example":{"events":[{"created_at":"2026-07-06T00:00:05Z","id":"evt_550e8400e29b41d4a716446655440000","job_id":"550e8400-e29b-41d4-a716-446655440000","output_index":null,"task_id":"task_550e8400-e29b-41d4-a716-446655440000","type":"task.completed"}]},"schema":{"$ref":"#/components/schemas/WebhookEventsResponse"}}},"description":"Webhook events created from terminal public image tasks.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"API key does not grant the required scope","request_id":"client-request-123","type":"forbidden"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Credential is valid but lacks admin scope.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"summary":"List persisted webhook events","tags":["Admin Webhooks"]}},"/v1/webhooks":{"get":{"operationId":"listWebhookEndpoints","parameters":[{"$ref":"#/components/parameters/RequestIdHeader"}],"responses":{"200":{"content":{"application/json":{"example":{"endpoints":[{"created_at":"2026-07-06T00:00:00Z","description":"Production image task receiver","enabled":true,"id":"660e8400-e29b-41d4-a716-446655440000","last_delivery_at":"2026-07-06T00:00:05Z","revoked_at":null,"updated_at":"2026-07-06T00:00:05Z","url":"https://client.example.com/gpt-image/webhook"}]},"schema":{"$ref":"#/components/schemas/WebhookEndpointsResponse"}}},"description":"Registered webhook endpoints. Signing secrets are never returned after creation.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"API key does not grant the required scope","request_id":"client-request-123","type":"forbidden"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Credential is valid but lacks admin scope.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"summary":"List webhook endpoints","tags":["Admin Webhooks"]},"post":{"operationId":"createWebhookEndpoint","parameters":[{"$ref":"#/components/parameters/RequestIdHeader"}],"requestBody":{"content":{"application/json":{"example":{"description":"Production image task receiver","url":"https://client.example.com/gpt-image/webhook"},"schema":{"$ref":"#/components/schemas/CreateWebhookEndpointRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"endpoint":{"created_at":"2026-07-06T00:00:00Z","description":"Production image task receiver","enabled":true,"id":"660e8400-e29b-41d4-a716-446655440000","last_delivery_at":"2026-07-06T00:00:05Z","revoked_at":null,"updated_at":"2026-07-06T00:00:05Z","url":"https://client.example.com/gpt-image/webhook"},"signing_secret":"whsec_example-returned-once"},"schema":{"$ref":"#/components/schemas/CreateWebhookEndpointResponse"}}},"description":"Webhook endpoint created. The signing secret is returned once.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"400":{"content":{"application/json":{"example":{"kind":"bad_request","message":"webhook url must use https","request_id":"client-request-123","type":"invalid_request"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Invalid webhook endpoint request or blocked target URL.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"API key does not grant the required scope","request_id":"client-request-123","type":"forbidden"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Credential is valid but lacks admin scope.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"summary":"Create a webhook endpoint","tags":["Admin Webhooks"]}},"/v1/webhooks/{endpoint_id}":{"delete":{"operationId":"revokeWebhookEndpoint","parameters":[{"$ref":"#/components/parameters/WebhookEndpointIdPath"},{"$ref":"#/components/parameters/RequestIdHeader"}],"responses":{"200":{"content":{"application/json":{"example":{"endpoint":{"created_at":"2026-07-06T00:00:00Z","description":"Production image task receiver","enabled":false,"id":"660e8400-e29b-41d4-a716-446655440000","last_delivery_at":null,"revoked_at":"2026-07-06T00:00:05Z","updated_at":"2026-07-06T00:00:05Z","url":"https://client.example.com/gpt-image/webhook"}},"schema":{"$ref":"#/components/schemas/RevokeWebhookEndpointResponse"}}},"description":"Webhook endpoint revoked.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"401":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"missing authorization credential","request_id":"client-request-123","type":"unauthorized"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Missing or invalid Bearer credential.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"403":{"content":{"application/json":{"example":{"kind":"unauthorized","message":"API key does not grant the required scope","request_id":"client-request-123","type":"forbidden"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Credential is valid but lacks admin scope.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"404":{"content":{"application/json":{"example":{"kind":"bad_request","message":"webhook endpoint not found","request_id":"client-request-123","type":"not_found"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Webhook endpoint not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}},"429":{"content":{"application/json":{"example":{"kind":"bad_request","message":"API rate limit exceeded","request_id":"client-request-123","type":"rate_limited"},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limit exceeded. Retry-After contains the delay in seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfterHeader"},"X-Request-Id":{"$ref":"#/components/headers/RequestIdResponseHeader"}}}},"summary":"Revoke a webhook endpoint","tags":["Admin Webhooks"]}}},"security":[{"BearerAuth":[]}],"servers":[{"description":"Same-origin orchestrator entrypoint. Docker Compose publishes only port 8022.","url":"/"}],"tags":[{"description":"Machine-readable API contract.","name":"Contract"},{"description":"Submit asynchronous public image generation tasks.","name":"Images"},{"description":"Poll task state and image result URLs.","name":"Tasks"},{"description":"Download generated image bytes through the orchestrator.","name":"Outputs"},{"description":"Export append-only usage ledger events for billing and quota reconciliation.","name":"Usage"},{"description":"Admin-scoped request audit log with resolved client IPs.","name":"Request Logs"},{"description":"Admin-scoped client, quota and policy management surface.","name":"Admin Clients"},{"description":"Admin-scoped API key management surface.","name":"Admin API Keys"},{"description":"Admin-scoped webhook endpoint registration, delivery inspection and replay.","name":"Admin Webhooks"}]}