{"openapi":"3.1.0","info":{"title":"Cutstack API","version":"1.0.0","summary":"Background removal for product photos, in batches, with an automatic quality check.","description":"Everything the Cutstack studio does, one request per step: create a batch, add photos (files or links), start it, follow it (`?wait=`, an event stream, or webhooks), read the review queue, download the ZIP. One photo at a time: `POST /v1/images`.\n\n**Credits.** One credit per photo that comes out clean; a photo the automatic check flags is refunded. Credits are spent plan first, then bought ones. A re-run with our strongest model costs two.\n\n**Results live two hours.** Download what you need; the API is not an archive.\n\n**Limits.** 60 requests per minute and 2,000 photos per hour per key, 200 photos per batch. Accepted inputs: JPEG, PNG, WebP, or a ZIP of them.\n\n**Errors** are RFC 9457 `application/problem+json` with a stable `code`.","contact":{"url":"https://trycutstack.com/help"},"termsOfService":"https://trycutstack.com/terms","license":{"name":"Proprietary","url":"https://trycutstack.com/terms"}},"servers":[{"url":"https://trycutstack.com","description":"Production"}],"security":[{"apiKey":[]}],"tags":[{"name":"Batches","description":"Create, fill, start, follow and delete batches."},{"name":"Photos","description":"Change, re-run or remove photos of a batch."},{"name":"Review","description":"The photos worth a second look, and reporting a broken one."},{"name":"Files","description":"Outputs, cutouts, originals and the ZIP."},{"name":"Events","description":"Live progress and webhooks."},{"name":"Single photo","description":"The one-call shortcut."},{"name":"Account","description":"Credits and limits."},{"name":"Reference","description":"Presets and this document."}],"paths":{"/v1/jobs":{"post":{"tags":["Batches"],"operationId":"createJob","summary":"Create an empty batch","description":"Step 1 of 3. Nothing is charged. Then add photos and start it. With `webhookUrl` the answer carries `webhookSecret`, shown only once.","requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateJobRequest"}},"multipart/form-data":{"schema":{"type":"object","properties":{"options":{"type":"string","description":"JSON, the same shape as `defaults`."},"background":{"type":"string","format":"binary","description":"Background image for `background.mode = image`."}}}}}},"responses":{"201":{"description":"The draft.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobCreated"}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/Unavailable"},"507":{"description":"Storage full (`STORAGE_FULL`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"tags":["Batches"],"operationId":"listJobs","summary":"List your batches","parameters":[{"name":"limit","in":"query","required":false,"schema":{"default":20,"type":"integer","minimum":1,"maximum":100}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["draft","queued","running","paused","done","failed","cancelled"]}},{"name":"before","in":"query","required":false,"description":"Only batches created before this server time (ms); pass `nextBefore` to page.","schema":{"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Newest first, without photos.","content":{"application/json":{"schema":{"type":"object","properties":{"jobs":{"type":"array","items":{"$ref":"#/components/schemas/JobSummary"}},"hasMore":{"type":"boolean"},"nextBefore":{"oneOf":[{"type":"integer"},{"type":"null"}]}},"required":["jobs","hasMore","nextBefore"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/jobs/{id}":{"get":{"tags":["Batches"],"operationId":"getJob","summary":"Read a batch, optionally waiting for a change","description":"`since` returns only the photos changed at or after that server time (`delta: true`). `fields=summary` leaves the photos out. `wait` holds the answer up to that many seconds until something changes after `since` (or after the request arrived), the batch stops running, or the time is up. One request instead of a polling loop.","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}},{"name":"since","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":9007199254740991}},{"name":"fields","in":"query","required":false,"schema":{"default":"full","type":"string","enum":["full","summary"]}},{"name":"wait","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":60}}],"responses":{"200":{"description":"The batch (or its summary).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Job"},{"$ref":"#/components/schemas/JobSummary"}]}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"tags":["Batches"],"operationId":"deleteJob","summary":"Delete a batch now","description":"Drafts and stopped batches included; open reservations are released. A running batch must be stopped first.","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}}],"responses":{"204":{"description":"Deleted."},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Still running (`CONFLICT`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/jobs/{id}/items":{"post":{"tags":["Batches"],"operationId":"addItems","summary":"Add photos to a draft","description":"Step 2 of 3. Files as multipart, or links as JSON (fetched server-side; public https hosts). As many requests as you like until you start. Counts against the per-key photo budget.","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"files":{"type":"array","items":{"type":"string","format":"binary"},"description":"JPEG, PNG, WebP, or ZIPs of them. Photos over the 200-per-batch limit are rejected with a reason."}},"required":["files"]}},"application/json":{"schema":{"$ref":"#/components/schemas/UrlItemsRequest"}}}},"responses":{"200":{"description":"The batch with the new photos; refused ones in `rejected`.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Job"},{"type":"object","properties":{"added":{"type":"integer"}},"required":["added"],"additionalProperties":false}]}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Already started (`NOT_DRAFT`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"507":{"description":"Storage full (`STORAGE_FULL`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"tags":["Photos"],"operationId":"deleteItems","summary":"Remove several photos","description":"Photos in flight are skipped; nothing is refunded.","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteItemsRequest"}}}},"responses":{"200":{"description":"The batch.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Job"},{"type":"object","properties":{"removed":{"type":"integer"}},"required":["removed"],"additionalProperties":false}]}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/jobs/{id}/start":{"post":{"tags":["Batches"],"operationId":"startJob","summary":"Charge and start a draft","description":"Step 3 of 3. Reserves one credit per photo (two for a `heavy` re-run later). `sample` runs N photos first and holds the rest for POST /continue. `defaults` replaces the settings every photo starts with. Send an `Idempotency-Key`.","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"8–128 characters of your choice. A retry with the same key replays the first answer instead of running (and charging) twice; remembered for 24 h.","schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartRequest"}}}},"responses":{"202":{"description":"Queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"402":{"$ref":"#/components/responses/NoCredits"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"`NOT_DRAFT` (already started), `TOO_MANY_ACTIVE` (batches running), or `IN_PROGRESS` (same Idempotency-Key still running).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/jobs/{id}/continue":{"post":{"tags":["Batches"],"operationId":"continueJob","summary":"Run the held photos","description":"After a sample run or a stop. This is where the rest of the batch is charged.","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}}],"responses":{"202":{"description":"Queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"402":{"$ref":"#/components/responses/NoCredits"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Nothing held (`CONFLICT`) or too many batches running (`TOO_MANY_ACTIVE`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/jobs/{id}/cancel":{"post":{"tags":["Batches"],"operationId":"cancelJob","summary":"Stop a running batch","description":"Queued photos go back to waiting and their credits are released at once; photos already at the model finish. The batch ends up `paused`, so POST /continue resumes it.","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The batch, with how many photos were stopped and how many are still in flight.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Job"},{"type":"object","properties":{"stopped":{"type":"integer"},"inFlight":{"type":"integer"}},"required":["stopped","inFlight"],"additionalProperties":false}]}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Not running (`NOT_RUNNING`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/jobs/{id}/apply":{"post":{"tags":["Photos"],"operationId":"applySettings","summary":"Change the output of finished photos","description":"Preset, background, alignment, scale, corrections: re-rendered from the stored cutouts, never through the model again. Free. Multipart adds a background image shared by the selection.","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyRequest"}},"multipart/form-data":{"schema":{"type":"object","properties":{"payload":{"type":"string","description":"JSON, the same shape as the JSON body."},"image":{"type":"string","format":"binary"}},"required":["payload"]}}}},"responses":{"200":{"description":"The batch, re-rendered.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/jobs/{id}/retry":{"post":{"tags":["Photos"],"operationId":"retryItems","summary":"Run photos through the model again","description":"One credit per photo, reserved at once. For our strongest model on one photo use the per-photo retry with `tier: heavy`.","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetryRequest"}}}},"responses":{"202":{"description":"Queued.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Job"},{"type":"object","properties":{"retried":{"type":"integer"},"charged":{"type":"integer"}},"required":["retried","charged"],"additionalProperties":false}]}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"402":{"$ref":"#/components/responses/NoCredits"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Nothing to retry, or a photo is still running (`CONFLICT`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/jobs/{id}/download":{"get":{"tags":["Files"],"operationId":"downloadZip","summary":"Download the finished photos as a ZIP","description":"Streamed. `Content-Length` is sent when nothing needs converting (`optimize=off`, no `format`, no extra presets), so a progress bar is possible. Name tokens: `{name}` `{index}` `{n}` `{preset}` `{w}` `{h}` `{date}` `{sku}`.","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}},{"name":"format","in":"query","required":false,"description":"Convert every rendered file.","schema":{"type":"string","enum":["png","jpeg","webp"]}},{"name":"pattern","in":"query","required":false,"description":"File-name pattern.","schema":{"default":"{name}","type":"string","maxLength":80}},{"name":"start","in":"query","required":false,"description":"First `{index}`.","schema":{"default":1,"type":"integer","minimum":0,"maximum":1000000}},{"name":"items","in":"query","required":false,"description":"Comma-separated photo ids; default: every finished photo.","schema":{"type":"string","maxLength":8000}},{"name":"optimize","in":"query","required":false,"description":"`marketplace` (default) stays under the preset's upload limit; `off` = as rendered, fastest.","schema":{"default":"marketplace","type":"string","enum":["marketplace","lossless","web","off"]}},{"name":"include","in":"query","required":false,"description":"Comma-separated `rendered`, `cutouts`, `originals`; more than one = a folder each.","schema":{"default":"rendered","type":"string","maxLength":40}},{"name":"presets","in":"query","required":false,"description":"Comma-separated preset ids to render for as well, a folder per preset.","schema":{"type":"string","maxLength":200}},{"name":"skus","in":"query","required":false,"description":"JSON array of SKUs aligned with `items`, for `{sku}`.","schema":{"type":"string","maxLength":16000}}],"responses":{"200":{"description":"The archive.","content":{"application/zip":{"schema":{"type":"string","format":"binary"}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"No finished photos yet (`CONFLICT`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/jobs/{id}/review":{"get":{"tags":["Review"],"operationId":"reviewQueue","summary":"Only the photos worth a second look","description":"Flagged by the automatic check (not charged) or failed. One line of reason each, a region when there is one, thumbnail links, and what can be done next. Read this instead of the whole batch.","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The queue.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewQueue"}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/jobs/{id}/events":{"get":{"tags":["Events"],"operationId":"streamEvents","summary":"Live progress as Server-Sent Events","description":"First a `snapshot` (the batch without photos), then one message per event: `job.started`, `item.done`, `item.needs_review`, `item.failed`, `job.paused`, `job.done`. `data` is a JobEvent. Ends after `job.done`, after ten minutes (`timeout`), or when you close it; a comment line every 15 s keeps the connection alive. Can be opened before /start.","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The stream.","content":{"text/event-stream":{"schema":{"type":"string","description":"SSE frames: `id`, `event`, `data` (JSON)."}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/jobs/{id}/webhooks":{"get":{"tags":["Events"],"operationId":"listWebhookDeliveries","summary":"What happened to this batch's webhook deliveries","description":"One row per event: attempts, delivered or given up after five tries, last status and error, and the body that was sent so a lost event can be replayed by hand.","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The deliveries.","content":{"application/json":{"schema":{"type":"object","properties":{"jobId":{"type":"string"},"webhookUrl":{"oneOf":[{"type":"string"},{"type":"null"}]},"events":{"oneOf":[{"oneOf":[{"type":"string","const":"all"},{"type":"array","items":{"type":"string","enum":["job.started","item.done","item.needs_review","item.failed","job.paused","job.done"]}}]},{"type":"null"}]},"maxAttempts":{"type":"integer"},"deliveries":{"type":"array","items":{"$ref":"#/components/schemas/Delivery"}}},"required":["jobId","webhookUrl","events","maxAttempts","deliveries"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/jobs/{id}/items/{itemId}":{"delete":{"tags":["Photos"],"operationId":"deleteItem","summary":"Remove one photo","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}},{"name":"itemId","in":"path","required":true,"description":"Photo id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The batch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Still processing (`CONFLICT`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/jobs/{id}/items/{itemId}/file":{"get":{"tags":["Files"],"operationId":"getItemFile","summary":"One file of a photo","description":"The current output by default; `variant` picks the cutout, the original or a thumbnail. `format` converts the output on the fly (JPEG flattens onto white). Every URL in a batch answer points here.","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}},{"name":"itemId","in":"path","required":true,"description":"Photo id.","schema":{"type":"string"}},{"name":"variant","in":"query","schema":{"type":"string","enum":["output","cutout","input","thumb","input-thumb"]},"description":"Default `output`."},{"name":"format","in":"query","schema":{"type":"string","enum":["png","jpeg","webp"]},"description":"Output only."},{"name":"optimize","in":"query","schema":{"type":"string","enum":["marketplace","lossless","web","off"]},"description":"Output only; default `marketplace` with `download=1`, `off` otherwise."},{"name":"download","in":"query","schema":{"type":"string"},"description":"Any value: `Content-Disposition: attachment`."}],"responses":{"200":{"description":"The file.","content":{"image/png":{"schema":{"type":"string","format":"binary"}},"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}},"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"No output yet (`CONFLICT`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/jobs/{id}/items/{itemId}/retry":{"post":{"tags":["Photos"],"operationId":"retryItem","summary":"Run one photo again, optionally with our strongest model","description":"1 credit; `tier: heavy` = 2 credits. The answer says what was charged.","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}},{"name":"itemId","in":"path","required":true,"description":"Photo id.","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemRetryRequest"}}}},"responses":{"202":{"description":"Queued.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Job"},{"type":"object","properties":{"charged":{"type":"integer"},"tier":{"type":"string","enum":["light","heavy"]}},"required":["charged","tier"],"additionalProperties":false}]}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"402":{"$ref":"#/components/responses/NoCredits"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Still running, waiting, or a sample photo (`CONFLICT`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/jobs/{id}/items/{itemId}/report":{"post":{"tags":["Review"],"operationId":"reportItem","summary":"Report a broken result","description":"The server checks the marked region against the pixels and refunds the credit only when the evidence agrees. No model call. At most two reports per photo.","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}},{"name":"itemId","in":"path","required":true,"description":"Photo id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportRequest"}}}},"responses":{"200":{"description":"The verdict and the batch.","content":{"application/json":{"schema":{"type":"object","properties":{"job":{"$ref":"#/components/schemas/Job"},"verdict":{"type":"object","properties":{"accepted":{"type":"boolean"},"reason":{"type":"string"},"region":{"$ref":"#/components/schemas/BBox"},"confidence":{"type":"number"},"evidence":{"type":"string","description":"One sentence with numbers."},"metrics":{"type":"object","additionalProperties":{"type":"number"}}},"required":["accepted","reason","region","confidence","evidence","metrics"],"additionalProperties":false}},"required":["job","verdict"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"`CONFLICT` with `reason` NOT_DONE, ALREADY_REFUNDED or NO_ATTEMPTS_LEFT.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/jobs/{id}/items/{itemId}/preview":{"post":{"tags":["Photos"],"operationId":"previewItem","summary":"Render one photo with different settings, without saving","parameters":[{"name":"id","in":"path","required":true,"description":"Batch id.","schema":{"type":"string"}},{"name":"itemId","in":"path","required":true,"description":"Photo id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewRequest"}}}},"responses":{"200":{"description":"The rendered image; `X-Output-Size` carries `WxH`.","content":{"image/png":{"schema":{"type":"string","format":"binary"}},"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Not finished yet (`CONFLICT`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/images":{"post":{"tags":["Single photo"],"operationId":"processImage","summary":"One photo in, one result out","description":"A one-photo batch is created and started for you; the connection waits up to `timeout` seconds. The answer is the image (with `X-Cutstack-Job-Id`, `X-Cutstack-Item-Id`, `X-Cutstack-Review`, `X-Cutstack-Charged`, `X-Cutstack-Score` headers) or, with `response=json`, its description and links. One credit, refunded when the automatic check flags it. The batch stays for two hours like any other.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"8–128 characters of your choice. A retry with the same key replays the first answer instead of running (and charging) twice; remembered for 24 h.","schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"},"settings":{"type":"string","description":"JSON, the same shape as a batch's `defaults`."},"response":{"default":"image","type":"string","enum":["image","json"]},"format":{"type":"string","enum":["png","jpeg","webp"]},"optimize":{"default":"marketplace","type":"string","enum":["marketplace","lossless","web","off"]},"timeout":{"default":60,"type":"integer","minimum":5,"maximum":60}},"required":["file"]}},"application/json":{"schema":{"$ref":"#/components/schemas/ImageRequest"}}}},"responses":{"200":{"description":"The result.","content":{"image/png":{"schema":{"type":"string","format":"binary"}},"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}},"application/json":{"schema":{"$ref":"#/components/schemas/ImageResult"}}}},"202":{"description":"Still processing when `timeout` ran out: ids and links; the credit is settled when the photo finishes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageResult"}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"402":{"$ref":"#/components/responses/NoCredits"},"409":{"description":"Too many batches running (`TOO_MANY_ACTIVE`) or the same Idempotency-Key still running (`IN_PROGRESS`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The photo could not be processed and it is the input's fault (`PROCESSING_FAILED`, `reason` INVALID_IMAGE, NO_SUBJECT, …). Nothing charged.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"description":"The model is unavailable (`SERVICE_UNAVAILABLE`) or failed on our side (`PROCESSING_FAILED`). Nothing charged.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"504":{"description":"The photo never started within `timeout` (`TIMEOUT`); the reservation was released.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/presets":{"get":{"tags":["Reference"],"operationId":"listPresets","summary":"The marketplace presets","description":"With the source each one was checked against and when.","responses":{"200":{"description":"The presets.","content":{"application/json":{"schema":{"type":"object","properties":{"presets":{"type":"array","items":{"$ref":"#/components/schemas/Preset"}}},"required":["presets"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/account":{"get":{"tags":["Account"],"operationId":"getAccount","summary":"Balance per pocket, plan and limits","responses":{"200":{"description":"The account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/credits/ledger":{"get":{"tags":["Account"],"operationId":"listLedger","summary":"Every credit movement, newest first","parameters":[{"name":"limit","in":"query","required":false,"schema":{"default":50,"type":"integer","minimum":1,"maximum":200}},{"name":"before","in":"query","required":false,"description":"ISO time; pass `nextBefore` to page.","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}}],"responses":{"200":{"description":"A page.","content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/LedgerEntry"}},"hasMore":{"type":"boolean"},"nextBefore":{"oneOf":[{"type":"string"},{"type":"null"}]}},"required":["entries","hasMore","nextBefore"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/Validation"},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/openapi.json":{"get":{"tags":["Reference"],"operationId":"getOpenApi","summary":"This document","security":[],"responses":{"200":{"description":"The OpenAPI 3.1 description of /v1.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"csk_live_…","description":"Your API key, created under Account → API keys. Keep it on a server: anyone who has it can spend your credits."}},"schemas":{"Problem":{"type":"object","description":"RFC 9457 problem details. `code` is stable; `detail` says what to do. Extra members depend on the code: `errors` (validation issues), `needed` and `balance` (NO_CREDITS), `retryAfter` (RATE_LIMITED), `jobId`/`itemId`/`reason` (PROCESSING_FAILED, TIMEOUT).","properties":{"type":{"type":"string","description":"Link to the docs entry for this code."},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string","enum":["UNAUTHENTICATED","INVALID_KEY","NOT_FOUND","VALIDATION","NOT_DRAFT","NOT_RUNNING","IN_PROGRESS","TOO_MANY_ACTIVE","NO_CREDITS","RATE_LIMITED","STORAGE_FULL","SERVICE_UNAVAILABLE","CONFLICT","UPLOAD_FAILED","PROCESSING_FAILED","TIMEOUT"]},"detail":{"type":"string"},"errors":{"type":"array","items":{"type":"object","additionalProperties":true}},"needed":{"type":"integer"},"balance":{"type":"integer"},"retryAfter":{"type":"integer","description":"Seconds."},"jobId":{"type":"string"},"itemId":{"type":"string"},"reason":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":true},"BBox":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"}},"required":["x","y","width","height"],"description":"A region in cutout pixels.","additionalProperties":false},"QualityFlag":{"type":"object","properties":{"code":{"type":"string","enum":["background-kept","hole-in-subject","low-confidence","subject-too-small","colour-spill","subject-touches-edge","multiple-objects","uncertain-edges","halo"]},"label":{"type":"string","description":"Human-readable label."},"bbox":{"oneOf":[{"$ref":"#/components/schemas/BBox"},{"type":"null"}]},"severity":{"type":"number","description":"0–1.","minimum":0,"maximum":1}},"required":["code","label","bbox","severity"],"description":"One thing the automatic check noticed.","additionalProperties":false},"Quality":{"type":"object","properties":{"score":{"type":"number","description":"0–100; lower = more likely broken. Only the `red` review level matters.","minimum":0,"maximum":100},"flags":{"type":"array","items":{"$ref":"#/components/schemas/QualityFlag"}}},"required":["score","flags"],"description":"The automatic diagnosis of a finished photo.","additionalProperties":false},"Settings":{"type":"object","properties":{"presetId":{"type":"string","description":"Marketplace preset id, `original`, or `custom`."},"customSize":{"type":"object","properties":{"width":{"type":"integer"},"height":{"type":"integer"}},"required":["width","height"],"additionalProperties":false},"background":{"type":"object","properties":{"mode":{"type":"string","enum":["transparent","white","solid","image"]},"color":{"type":"string","description":"Hex colour for `solid`."},"hasImage":{"type":"boolean","description":"Whether a background image is set (the image itself is never returned)."}},"required":["mode","hasImage"],"additionalProperties":false},"align":{"type":"string","enum":["center","top-left","top-right","bottom-left","bottom-right"]},"scale":{"type":"integer","enum":[1,2,4],"description":"Integer upscale of the whole canvas."},"fill":{"type":"number","description":"How much of the canvas the subject spans (0.5–1)."},"flip":{"type":"boolean"},"rotate":{"type":"integer","enum":[0,90,180,270]},"foregroundScale":{"type":"number","description":"Product drawn at this fraction of its framed size (0.25–1)."},"sharpen":{"type":"number"},"brightness":{"type":"number"},"contrast":{"type":"number"},"saturation":{"type":"number"}},"required":["presetId","background","align","scale","sharpen","brightness","contrast","saturation"],"description":"How a photo is rendered. Changing any of these never runs the model again.","additionalProperties":false},"Claim":{"type":"object","properties":{"reason":{"type":"string","enum":["background-kept","missing-part","hole","extra-object","rough-edges"]},"region":{"$ref":"#/components/schemas/BBox"},"verdict":{"type":"string","enum":["accepted","rejected"]},"confidence":{"type":"number"},"evidence":{"type":"string"},"at":{"type":"integer","description":"Server time, ms."}},"required":["reason","region","verdict","confidence","evidence","at"],"description":"A report on a photo and what the pixel check concluded.","additionalProperties":false},"ItemError":{"type":"object","properties":{"code":{"type":"string","enum":["INVALID_IMAGE","TOO_LARGE","REMOTE_NOT_CONFIGURED","REMOTE_AUTH","REMOTE_CREDIT","REMOTE_RATE_LIMIT","REMOTE_BAD_INPUT","REMOTE_UNAVAILABLE","PROCESSING_FAILED","NO_SUBJECT","CANCELLED"]},"message":{"type":"string"}},"required":["code","message"],"additionalProperties":false},"Timings":{"type":"object","properties":{"decode":{"type":"number"},"inference":{"type":"number"},"diagnose":{"type":"number"},"compose":{"type":"number"},"encode":{"type":"number"},"total":{"type":"number"}},"description":"Milliseconds per stage.","additionalProperties":false},"ItemMeta":{"type":"object","properties":{"timings":{"$ref":"#/components/schemas/Timings"},"output":{"type":"object","properties":{"width":{"type":"integer"},"height":{"type":"integer"},"format":{"type":"string","enum":["png","jpeg","webp"]},"bytes":{"type":"integer"}},"required":["width","height","format","bytes"],"additionalProperties":false},"source":{"type":"object","properties":{"width":{"type":"integer"},"height":{"type":"integer"},"format":{"type":"string"}},"required":["width","height"],"additionalProperties":false},"cutout":{"type":"object","properties":{"width":{"type":"integer"},"height":{"type":"integer"}},"required":["width","height"],"additionalProperties":false},"bbox":{"oneOf":[{"$ref":"#/components/schemas/BBox"},{"type":"null"}]},"subjectFill":{"oneOf":[{"type":"number"},{"type":"null"}]},"warnings":{"type":"array","items":{"type":"string"}},"presetId":{"type":"string"}},"description":"Measurements of a finished photo.","additionalProperties":false},"Item":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","description":"The file name it was uploaded with."},"status":{"type":"string","enum":["held","pending","processing","done","failed"],"description":"`held` = waiting (sample run or stopped batch), `pending` = queued, `processing` = at the model."},"error":{"$ref":"#/components/schemas/ItemError"},"outputName":{"type":"string"},"outputUrl":{"type":"string","description":"Current output. Append `&format=png|jpeg|webp` to convert, `&download=1` for an attachment. Send the same API key."},"pngUrl":{"type":"string","description":"Same output, guaranteed PNG."},"thumbUrl":{"type":"string","description":"≤ 512 px WebP of the output."},"inputThumbUrl":{"type":"string","description":"≤ 512 px WebP of the source photo, available before the run."},"cutoutUrl":{"type":"string","description":"Straight-alpha PNG cutout at working resolution."},"inputUrl":{"type":"string","description":"The original upload."},"quality":{"$ref":"#/components/schemas/Quality"},"review":{"type":"string","enum":["none","red"],"description":"`red` = needs a look; the credit was refunded."},"refunded":{"type":"boolean","description":"Not charged: flagged by the automatic check, or a report the pixel check confirmed."},"claims":{"type":"array","items":{"$ref":"#/components/schemas/Claim"}},"canReport":{"type":"boolean"},"canRerun":{"type":"boolean"},"tier":{"type":"string","enum":["light","heavy"],"description":"`heavy` = our strongest model (2 credits), chosen per photo on a re-run."},"credits":{"type":"integer","description":"What this photo costs (or cost)."},"settings":{"$ref":"#/components/schemas/Settings"},"rev":{"type":"integer","description":"Bumped on every render; cache-busts the file URLs."},"meta":{"$ref":"#/components/schemas/ItemMeta"},"stage":{"type":"string","enum":["decode","inference","diagnose","compose","encode"]},"stageStartedAt":{"type":"integer"},"startedAt":{"type":"integer"},"finishedAt":{"type":"integer"},"updatedAt":{"type":"integer","description":"Server clock of the last change; use as `since` for delta polls."},"attempts":{"type":"integer"}},"required":["id","name","status","inputUrl","review","refunded","claims","canReport","canRerun","tier","credits","settings","rev","updatedAt","attempts"],"description":"One photo of a batch.","additionalProperties":false},"Counts":{"type":"object","properties":{"total":{"type":"integer"},"held":{"type":"integer"},"pending":{"type":"integer"},"processing":{"type":"integer"},"done":{"type":"integer"},"failed":{"type":"integer"},"refunded":{"type":"integer","description":"Finished photos that were not charged."}},"required":["total","held","pending","processing","done","failed","refunded"],"additionalProperties":false},"Estimate":{"type":"object","properties":{"perImageMs":{"type":"integer"},"remainingMs":{"type":"integer","description":"Rough time to finish what is queued or in flight."},"heldMs":{"type":"integer","description":"Rough time the held photos would take once continued."},"now":{"type":"integer","description":"Server clock at serialisation."}},"required":["perImageMs","remainingMs","heldMs","now"],"additionalProperties":false},"Rejected":{"type":"object","properties":{"name":{"type":"string","description":"File name or link."},"reason":{"type":"string"}},"required":["name","reason"],"additionalProperties":false},"Job":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["draft","queued","running","paused","done","failed","cancelled"],"description":"`draft` = photos still being added, nothing charged. `paused` = queued photos finished, some still held. A stopped batch is `paused`."},"createdAt":{"type":"integer","description":"Server time, ms."},"updatedAt":{"type":"integer","description":"Server clock of the last change; pass it back as `since`."},"finishedAt":{"type":"integer"},"cancelRequestedAt":{"type":"integer"},"options":{"type":"object","properties":{"sample":{"type":"integer","description":"Photos run first by a sample start."},"defaults":{"$ref":"#/components/schemas/Settings"}},"required":["defaults"],"additionalProperties":false},"counts":{"$ref":"#/components/schemas/Counts"},"downloadUrl":{"oneOf":[{"type":"string","description":"`/v1/jobs/{id}/download` once a photo is finished."},{"type":"null"}]},"continueUrl":{"oneOf":[{"type":"string","description":"`/v1/jobs/{id}/continue` while the batch is paused with held photos."},{"type":"null"}]},"estimate":{"$ref":"#/components/schemas/Estimate"},"items":{"type":"array","items":{"$ref":"#/components/schemas/Item"},"description":"Every photo, or only those changed since `since` when `delta` is true."},"delta":{"type":"boolean","description":"True for a `since` response: merge `items` by id into what you have."},"rejected":{"type":"array","items":{"$ref":"#/components/schemas/Rejected"},"description":"Files and links refused at upload time."}},"required":["id","status","createdAt","updatedAt","options","counts","downloadUrl","continueUrl","estimate","items","rejected"],"description":"A batch with its photos.","additionalProperties":false},"JobSummary":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["draft","queued","running","paused","done","failed","cancelled"],"description":"`draft` = photos still being added, nothing charged. `paused` = queued photos finished, some still held. A stopped batch is `paused`."},"createdAt":{"type":"integer","description":"Server time, ms."},"updatedAt":{"type":"integer","description":"Server clock of the last change; pass it back as `since`."},"finishedAt":{"type":"integer"},"cancelRequestedAt":{"type":"integer"},"options":{"type":"object","properties":{"sample":{"type":"integer","description":"Photos run first by a sample start."},"defaults":{"$ref":"#/components/schemas/Settings"}},"required":["defaults"],"additionalProperties":false},"counts":{"$ref":"#/components/schemas/Counts"},"downloadUrl":{"oneOf":[{"type":"string","description":"`/v1/jobs/{id}/download` once a photo is finished."},{"type":"null"}]},"continueUrl":{"oneOf":[{"type":"string","description":"`/v1/jobs/{id}/continue` while the batch is paused with held photos."},{"type":"null"}]},"estimate":{"$ref":"#/components/schemas/Estimate"}},"required":["id","status","createdAt","updatedAt","options","counts","downloadUrl","continueUrl","estimate"],"description":"A batch without its photos.","additionalProperties":false},"JobCreated":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["draft","queued","running","paused","done","failed","cancelled"],"description":"`draft` = photos still being added, nothing charged. `paused` = queued photos finished, some still held. A stopped batch is `paused`."},"createdAt":{"type":"integer","description":"Server time, ms."},"updatedAt":{"type":"integer","description":"Server clock of the last change; pass it back as `since`."},"finishedAt":{"type":"integer"},"cancelRequestedAt":{"type":"integer"},"options":{"type":"object","properties":{"sample":{"type":"integer","description":"Photos run first by a sample start."},"defaults":{"$ref":"#/components/schemas/Settings"}},"required":["defaults"],"additionalProperties":false},"counts":{"$ref":"#/components/schemas/Counts"},"downloadUrl":{"oneOf":[{"type":"string","description":"`/v1/jobs/{id}/download` once a photo is finished."},{"type":"null"}]},"continueUrl":{"oneOf":[{"type":"string","description":"`/v1/jobs/{id}/continue` while the batch is paused with held photos."},{"type":"null"}]},"estimate":{"$ref":"#/components/schemas/Estimate"},"items":{"type":"array","items":{"$ref":"#/components/schemas/Item"},"description":"Every photo, or only those changed since `since` when `delta` is true."},"delta":{"type":"boolean","description":"True for a `since` response: merge `items` by id into what you have."},"rejected":{"type":"array","items":{"$ref":"#/components/schemas/Rejected"},"description":"Files and links refused at upload time."},"webhookUrl":{"type":"string"},"webhookSecret":{"type":"string","description":"Shown only in this answer. Sign check: `X-Cutstack-Signature: t=<unix>,v1=<hex>` where v1 = HMAC-SHA256(webhookSecret, `${t}.${rawBody}`)."},"webhookEvents":{"oneOf":[{"type":"string","const":"all"},{"type":"array","items":{"type":"string","enum":["job.started","item.done","item.needs_review","item.failed","job.paused","job.done"]}}]}},"required":["id","status","createdAt","updatedAt","options","counts","downloadUrl","continueUrl","estimate","items","rejected"],"description":"The new batch; with a webhook, its signing secret as well.","additionalProperties":false},"ReviewEntry":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["review","failed"],"description":"`review` = finished but flagged (not charged); `failed` = the model could not process it."},"reason":{"type":"string","description":"One line: the top flag, `Low overall score`, or the failure message."},"code":{"type":"string","description":"A quality flag code, `low-score`, or a failure code."},"severity":{"oneOf":[{"type":"number"},{"type":"null"}]},"score":{"oneOf":[{"type":"number"},{"type":"null"}]},"bbox":{"oneOf":[{"$ref":"#/components/schemas/BBox"},{"type":"null"}]},"flags":{"type":"array","items":{"$ref":"#/components/schemas/QualityFlag"}},"refunded":{"type":"boolean"},"credits":{"type":"integer"},"thumbUrl":{"type":"string"},"outputUrl":{"type":"string"},"cutoutUrl":{"type":"string"},"inputThumbUrl":{"type":"string"},"canReport":{"type":"boolean"},"canRerun":{"type":"boolean"},"attempts":{"type":"integer"}},"required":["id","name","kind","reason","code","severity","score","bbox","flags","refunded","credits","canReport","canRerun","attempts"],"additionalProperties":false},"ReviewQueue":{"type":"object","properties":{"jobId":{"type":"string"},"status":{"type":"string","enum":["draft","queued","running","paused","done","failed","cancelled"]},"counts":{"$ref":"#/components/schemas/Counts"},"total":{"type":"integer","description":"Photos in this list."},"review":{"type":"integer"},"failed":{"type":"integer"},"items":{"type":"array","items":{"$ref":"#/components/schemas/ReviewEntry"},"description":"Failures first, then the lowest scores."},"updatedAt":{"type":"integer"}},"required":["jobId","status","counts","total","review","failed","items","updatedAt"],"description":"Only the photos worth a second look.","additionalProperties":false},"Preset":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"width":{"type":"integer","description":"Canvas width; 0 = same as the source."},"height":{"type":"integer"},"fillPercent":{"type":"number"},"paddingPercent":{"type":"number"},"background":{"type":"string","enum":["white","transparent","inherit"]},"format":{"type":"string","enum":["png","jpeg","webp","auto"]},"quality":{"type":"integer"},"maxBytes":{"type":"integer","description":"Marketplace upload limit; optimized exports stay under it."},"align":{"type":"string","enum":["center","bottom"]},"verified":{"type":"boolean","description":"Checked against the marketplace's own documentation."},"source":{"type":"string"},"sourceUrl":{"type":"string"},"verifiedAt":{"type":"string","description":"ISO date of the last check."},"notes":{"type":"string"}},"required":["id","label","width","height","fillPercent","paddingPercent","background","format","quality","align","verified"],"additionalProperties":false},"License":{"type":"object","properties":{"tier":{"type":"integer"},"status":{"type":"string","enum":["purchased","active","deactivated","refunded"]},"allowance":{"type":"integer","description":"Photos per month."},"jobLimit":{"type":"integer"},"nextRefreshAt":{"oneOf":[{"type":"string"},{"type":"null"}]},"activatedAt":{"oneOf":[{"type":"string"},{"type":"null"}]}},"required":["tier","status","allowance","jobLimit","nextRefreshAt","activatedAt"],"additionalProperties":false},"Account":{"type":"object","properties":{"credits":{"type":"object","properties":{"total":{"oneOf":[{"type":"integer"},{"type":"null"}]},"plan":{"type":"integer"},"pack":{"type":"integer"},"planResetsInDays":{"oneOf":[{"type":"integer"},{"type":"null"}]},"expiring":{"oneOf":[{"type":"object","properties":{"credits":{"type":"integer"},"at":{"type":"string"},"inDays":{"type":"integer"}},"required":["credits","at","inDays"],"additionalProperties":false},{"type":"null"}]}},"required":["total","plan","pack","planResetsInDays","expiring"],"additionalProperties":false},"license":{"oneOf":[{"$ref":"#/components/schemas/License"},{"type":"null"}]},"spendOrder":{"type":"array","items":{"type":"string","enum":["plan","pack"]},"description":"Credits are spent plan first, then bought ones, whichever door starts the batch."},"limits":{"type":"object","properties":{"photosPerBatch":{"type":"integer"},"activeBatches":{"type":"integer","description":"Batches one account may have running at once."},"requestsPerMinute":{"type":"integer","description":"Per key."},"photosPerHour":{"type":"integer","description":"Per key."},"resultsKeptForHours":{"type":"integer"}},"required":["photosPerBatch","activeBatches","requestsPerMinute","photosPerHour","resultsKeptForHours"],"additionalProperties":false},"auth":{"type":"object","properties":{"via":{"type":"string","enum":["key","session"]},"key":{"oneOf":[{"type":"string","description":"The key's display prefix."},{"type":"null"}]}},"required":["via","key"],"additionalProperties":false}},"required":["credits","license","spendOrder","limits","auth"],"additionalProperties":false},"LedgerEntry":{"type":"object","properties":{"id":{"type":"integer"},"jobId":{"oneOf":[{"type":"string"},{"type":"null"}]},"itemId":{"oneOf":[{"type":"string"},{"type":"null"}]},"kind":{"type":"string","description":"reserve, commit, release, claim, grant, purchase, welcome, refresh, expire, adjust."},"pool":{"type":"string","enum":["plan","pack"]},"amount":{"type":"integer","description":"Signed movement."},"units":{"type":"integer"},"balanceAfter":{"type":"integer"},"reason":{"oneOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string"}},"required":["id","jobId","itemId","kind","pool","amount","units","balanceAfter","reason","createdAt"],"additionalProperties":false},"JobEvent":{"type":"object","properties":{"id":{"type":"integer","description":"Per-batch sequence."},"event":{"type":"string","enum":["job.started","item.done","item.needs_review","item.failed","job.paused","job.done"]},"at":{"type":"integer","description":"Server time, ms."},"jobId":{"type":"string"},"data":{"type":"object","description":"For `item.*`: itemId, name, status, review, score, credits, attempts, error, outputUrl, thumbUrl, inputThumbUrl. For `job.*`: status, counts, downloadUrl, reviewUrl, continueUrl.","additionalProperties":true}},"required":["id","event","at","jobId","data"],"description":"One batch event, as streamed and as POSTed to a webhook.","additionalProperties":false},"Delivery":{"type":"object","properties":{"id":{"type":"string"},"event":{"type":"string","enum":["job.started","item.done","item.needs_review","item.failed","job.paused","job.done"]},"status":{"type":"string","enum":["pending","delivered","given_up"]},"attempts":{"type":"integer"},"nextAttemptAt":{"oneOf":[{"type":"integer"},{"type":"null"}]},"deliveredAt":{"oneOf":[{"type":"integer"},{"type":"null"}]},"givenUpAt":{"oneOf":[{"type":"integer"},{"type":"null"}]},"lastStatus":{"oneOf":[{"type":"integer","description":"HTTP status of the last attempt."},{"type":"null"}]},"lastError":{"oneOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"integer"},"payload":{"$ref":"#/components/schemas/JobEvent"}},"required":["id","event","status","attempts","nextAttemptAt","deliveredAt","givenUpAt","lastStatus","lastError","createdAt","payload"],"additionalProperties":false},"ImageResult":{"type":"object","properties":{"jobId":{"type":"string"},"itemId":{"type":"string"},"status":{"type":"string","enum":["done","processing"]},"charged":{"type":"integer","description":"Credits charged: 1 for a clean result, 0 otherwise."},"review":{"type":"string","enum":["none","red"]},"refunded":{"type":"boolean"},"fileUrl":{"type":"string"},"statusUrl":{"type":"string"},"reviewUrl":{"type":"string"},"item":{"$ref":"#/components/schemas/Item"}},"required":["jobId","itemId","status","charged","review","refunded","fileUrl","statusUrl","reviewUrl","item"],"additionalProperties":false},"JobDefaults":{"type":"object","properties":{"presetId":{"default":"original","type":"string","minLength":1,"maxLength":64},"customSize":{"type":"object","properties":{"width":{"type":"integer","minimum":100,"maximum":8000},"height":{"type":"integer","minimum":100,"maximum":8000}},"required":["width","height"]},"background":{"default":{"mode":"transparent"},"type":"object","properties":{"mode":{"type":"string","enum":["transparent","white","solid","image"]},"color":{"type":"string","pattern":"^#?[0-9a-fA-F]{6}$"}},"required":["mode"]},"align":{"default":"center","type":"string","enum":["center","top-left","top-right","bottom-left","bottom-right"]},"scale":{"default":1,"anyOf":[{"type":"number","const":1},{"type":"number","const":2},{"type":"number","const":4}]},"fill":{"type":"number","minimum":0.5,"maximum":1},"flip":{"type":"boolean"},"rotate":{"anyOf":[{"type":"number","const":0},{"type":"number","const":90},{"type":"number","const":180},{"type":"number","const":270}]},"foregroundScale":{"type":"number","minimum":0.25,"maximum":1},"sharpen":{"default":0,"type":"number","minimum":0,"maximum":100},"brightness":{"default":0,"type":"number","minimum":-30,"maximum":30},"contrast":{"default":0,"type":"number","minimum":-30,"maximum":30},"saturation":{"default":0,"type":"number","minimum":-50,"maximum":50},"trial":{"type":"integer","minimum":1,"maximum":200}},"description":"The settings every photo starts with. Every field has a default."},"SettingsPatch":{"type":"object","properties":{"presetId":{"type":"string","minLength":1,"maxLength":64},"customSize":{"type":"object","properties":{"width":{"type":"integer","minimum":100,"maximum":8000},"height":{"type":"integer","minimum":100,"maximum":8000}},"required":["width","height"]},"background":{"type":"object","properties":{"mode":{"type":"string","enum":["transparent","white","solid","image"]},"color":{"type":"string","pattern":"^#?[0-9a-fA-F]{6}$"}},"required":["mode"]},"align":{"type":"string","enum":["center","top-left","top-right","bottom-left","bottom-right"]},"scale":{"anyOf":[{"type":"number","const":1},{"type":"number","const":2},{"type":"number","const":4}]},"fill":{"type":"number","minimum":0.5,"maximum":1},"flip":{"type":"boolean"},"rotate":{"anyOf":[{"type":"number","const":0},{"type":"number","const":90},{"type":"number","const":180},{"type":"number","const":270}]},"foregroundScale":{"type":"number","minimum":0.25,"maximum":1},"sharpen":{"type":"number","minimum":0,"maximum":100},"brightness":{"type":"number","minimum":-30,"maximum":30},"contrast":{"type":"number","minimum":-30,"maximum":30},"saturation":{"type":"number","minimum":-50,"maximum":50}},"description":"Fields to change; unspecified ones keep their value."},"CreateJobRequest":{"type":"object","properties":{"name":{"type":"string","maxLength":120},"defaults":{"$ref":"#/components/schemas/JobDefaults"},"webhookUrl":{"type":"string","maxLength":2000},"webhookEvents":{"minItems":1,"maxItems":6,"type":"array","items":{"type":"string","enum":["job.started","item.done","item.needs_review","item.failed","job.paused","job.done"]}}},"description":"JSON body of POST /v1/jobs."},"StartRequest":{"type":"object","properties":{"sample":{"type":"integer","minimum":1,"maximum":200},"trial":{"type":"integer","minimum":1,"maximum":200},"defaults":{"type":"object","properties":{"presetId":{"default":"original","type":"string","minLength":1,"maxLength":64},"customSize":{"type":"object","properties":{"width":{"type":"integer","minimum":100,"maximum":8000},"height":{"type":"integer","minimum":100,"maximum":8000}},"required":["width","height"]},"background":{"default":{"mode":"transparent"},"type":"object","properties":{"mode":{"type":"string","enum":["transparent","white","solid","image"]},"color":{"type":"string","pattern":"^#?[0-9a-fA-F]{6}$"}},"required":["mode"]},"align":{"default":"center","type":"string","enum":["center","top-left","top-right","bottom-left","bottom-right"]},"scale":{"default":1,"anyOf":[{"type":"number","const":1},{"type":"number","const":2},{"type":"number","const":4}]},"fill":{"type":"number","minimum":0.5,"maximum":1},"flip":{"type":"boolean"},"rotate":{"anyOf":[{"type":"number","const":0},{"type":"number","const":90},{"type":"number","const":180},{"type":"number","const":270}]},"foregroundScale":{"type":"number","minimum":0.25,"maximum":1},"sharpen":{"default":0,"type":"number","minimum":0,"maximum":100},"brightness":{"default":0,"type":"number","minimum":-30,"maximum":30},"contrast":{"default":0,"type":"number","minimum":-30,"maximum":30},"saturation":{"default":0,"type":"number","minimum":-50,"maximum":50}}}},"description":"`sample` runs a spread sample of N photos first (the rest wait for POST /continue); `trial` is the same field under its studio name."},"UrlItemsRequest":{"type":"object","properties":{"urls":{"default":[],"maxItems":200,"type":"array","items":{"type":"string","maxLength":2000}},"zipUrl":{"type":"string","maxLength":2000}},"description":"Photos by link: public http(s) hosts only, fetched server-side. Rejections come back in the batch's `rejected`."},"ApplyRequest":{"type":"object","properties":{"itemIds":{"anyOf":[{"type":"string","const":"all"},{"minItems":1,"maxItems":200,"type":"array","items":{"type":"string","minLength":1,"maxLength":64}}]},"settings":{"$ref":"#/components/schemas/SettingsPatch"}},"required":["itemIds","settings"],"description":"`itemIds` = `all` or a list. Free: re-renders from the stored cutouts."},"RetryRequest":{"type":"object","properties":{"itemIds":{"anyOf":[{"type":"string","const":"failed"},{"minItems":1,"maxItems":200,"type":"array","items":{"type":"string","minLength":1,"maxLength":64}}]}},"required":["itemIds"],"description":"`itemIds` = a list or `failed`. One credit per photo, reserved at once."},"ItemRetryRequest":{"type":"object","properties":{"tier":{"default":"light","type":"string","enum":["light","heavy"]}},"description":"`tier: heavy` sends the photo to our strongest model for 2 credits."},"ReportRequest":{"type":"object","properties":{"reason":{"type":"string","enum":["background-kept","missing-part","hole","extra-object","rough-edges"]},"region":{"type":"object","properties":{"x":{"type":"integer","minimum":0,"maximum":8192},"y":{"type":"integer","minimum":0,"maximum":8192},"width":{"type":"integer","minimum":8,"maximum":8192},"height":{"type":"integer","minimum":8,"maximum":8192}},"required":["x","y","width","height"]}},"required":["reason","region"],"description":"Where the result is wrong, in cutout pixels. The credit is refunded only when the pixel check agrees."},"DeleteItemsRequest":{"type":"object","properties":{"itemIds":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"string","minLength":1,"maxLength":64}}},"required":["itemIds"]},"PreviewRequest":{"type":"object","properties":{"settings":{"$ref":"#/components/schemas/SettingsPatch"},"maxSide":{"default":900,"type":"integer","minimum":64,"maximum":1600}},"required":["settings"],"description":"A settings patch to render once, nothing stored."},"ImageRequest":{"type":"object","properties":{"settings":{"type":"object","properties":{"presetId":{"default":"original","type":"string","minLength":1,"maxLength":64},"customSize":{"type":"object","properties":{"width":{"type":"integer","minimum":100,"maximum":8000},"height":{"type":"integer","minimum":100,"maximum":8000}},"required":["width","height"]},"background":{"default":{"mode":"transparent"},"type":"object","properties":{"mode":{"type":"string","enum":["transparent","white","solid","image"]},"color":{"type":"string","pattern":"^#?[0-9a-fA-F]{6}$"}},"required":["mode"]},"align":{"default":"center","type":"string","enum":["center","top-left","top-right","bottom-left","bottom-right"]},"scale":{"default":1,"anyOf":[{"type":"number","const":1},{"type":"number","const":2},{"type":"number","const":4}]},"fill":{"type":"number","minimum":0.5,"maximum":1},"flip":{"type":"boolean"},"rotate":{"anyOf":[{"type":"number","const":0},{"type":"number","const":90},{"type":"number","const":180},{"type":"number","const":270}]},"foregroundScale":{"type":"number","minimum":0.25,"maximum":1},"sharpen":{"default":0,"type":"number","minimum":0,"maximum":100},"brightness":{"default":0,"type":"number","minimum":-30,"maximum":30},"contrast":{"default":0,"type":"number","minimum":-30,"maximum":30},"saturation":{"default":0,"type":"number","minimum":-50,"maximum":50}}},"response":{"default":"image","type":"string","enum":["image","json"]},"format":{"type":"string","enum":["png","jpeg","webp"]},"optimize":{"default":"marketplace","type":"string","enum":["marketplace","lossless","web","off"]},"timeout":{"default":60,"type":"integer","minimum":5,"maximum":60},"url":{"type":"string","maxLength":2000}},"required":["url"],"description":"JSON body of POST /v1/images: a link to the photo plus the same options as the multipart form."}},"responses":{"Validation":{"description":"Invalid request (`VALIDATION`, with `errors`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Unauthenticated":{"description":"No key (`UNAUTHENTICATED`) or a wrong / revoked one (`INVALID_KEY`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"NoCredits":{"description":"Not enough credits (`NO_CREDITS`, with `needed` and `balance`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"NotFound":{"description":"No such batch or photo on this account (`NOT_FOUND`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"RateLimited":{"description":"Over the per-key limit (`RATE_LIMITED`, with `retryAfter` and `Retry-After`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Unavailable":{"description":"The model is not reachable right now (`SERVICE_UNAVAILABLE`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}