{"openapi":"3.1.0","info":{"title":"Designelier API","version":"1.0.0","summary":"Plan, confirm, and download one recommended animated artwork pack from a public website URL.","description":"The v1 API is asynchronous and deliberately narrow. Planning does not spend credits. Confirmation requires the current immutable quote and exact credit amount, reserves those credits atomically, and queues generation. Every business response is private and non-cacheable."},"servers":[{"url":"https://app.designelier.com","description":"Production"}],"externalDocs":{"description":"Quickstart and curl examples","url":"https://app.designelier.com/docs/api"},"tags":[{"name":"Account","description":"Credit availability for the authenticated account."},{"name":"Artwork packs","description":"The asynchronous URL-to-pack workflow."},{"name":"Documentation","description":"Machine-readable API contract."}],"security":[{"bearerAuth":[]}],"paths":{"/v1/openapi.json":{"get":{"operationId":"getOpenApiDocument","summary":"Get the OpenAPI document","tags":["Documentation"],"security":[],"responses":{"200":{"description":"This OpenAPI 3.1 document.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/v1/account":{"get":{"operationId":"getAccount","summary":"Get available credits","tags":["Account"],"responses":{"200":{"description":"Total, reserved, and currently available credits.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"},"example":{"credits":{"total":20,"reserved":9,"available":11}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/v1/artwork-packs":{"post":{"operationId":"planArtworkPack","summary":"Plan an artwork pack without spending credits","description":"Creates an asynchronous planning job from one public HTTP(S) URL. Poll the Location resource until it reaches `awaiting_confirmation`, `failed`, or another terminal state. Only one active generation is allowed per account.","tags":["Artwork packs"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"description":"JSON only; at most 4096 bytes. Unknown fields are rejected.","x-max-bytes":4096,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanArtworkPackRequest"}}}},"responses":{"202":{"description":"The request was accepted. The response is the current complete pack resource.","headers":{"Location":{"$ref":"#/components/headers/Location"},"Idempotency-Replayed":{"$ref":"#/components/headers/IdempotencyReplayed"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArtworkPack"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"$ref":"#/components/responses/Conflict"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/v1/artwork-packs/{id}":{"get":{"operationId":"getArtworkPack","summary":"Get planning or generation status","description":"Returns a single pack; responses are not paginated. A quote is immutable once issued. Assets remain empty until every file has been verified and the pack succeeds.","tags":["Artwork packs"],"parameters":[{"$ref":"#/components/parameters/PackId"}],"responses":{"200":{"description":"The current complete pack resource.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArtworkPack"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/v1/artwork-packs/{id}/confirm":{"post":{"operationId":"confirmArtworkPack","summary":"Confirm the exact quote and spend credits on success","description":"The quote ID must be current and unexpired, and `confirmed_credits` must exactly equal the quote. Confirmation atomically reserves credits and queues generation. A successful job converts the reservation to one debit; a terminal failure releases it without charging.","tags":["Artwork packs"],"parameters":[{"$ref":"#/components/parameters/PackId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"description":"JSON only; at most 4096 bytes. Unknown fields are rejected.","x-max-bytes":4096,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmArtworkPackRequest"}}}},"responses":{"202":{"description":"The request was accepted. The response is the current complete pack resource.","headers":{"Location":{"$ref":"#/components/headers/Location"},"Idempotency-Replayed":{"$ref":"#/components/headers/IdempotencyReplayed"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArtworkPack"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/v1/artwork-packs/{id}/assets/{asset_id}/content":{"get":{"operationId":"getArtworkPackAssetContent","summary":"Download one verified asset","description":"Available only after success. The signed object is immutable, has the manifest SHA-256 digest, and is at most 8388608 bytes.","tags":["Artwork packs"],"parameters":[{"$ref":"#/components/parameters/PackId"},{"$ref":"#/components/parameters/AssetId"}],"responses":{"303":{"description":"Authorized redirect to a short-lived private object URL. Do not forward the API Authorization header to the redirect host.","headers":{"Location":{"description":"Short-lived HTTPS URL for the immutable object.","required":true,"schema":{"type":"string","format":"uri"}},"Cache-Control":{"description":"The redirect response is not cacheable.","schema":{"type":"string","example":"private, no-store"}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/v1/artwork-packs/{id}/download":{"get":{"operationId":"downloadArtworkPack","summary":"Download the verified pack archive","description":"Available only after success. The archive contains every SVG at its manifest path, plus the manifest and a relative-reference placement plan, and is at most 67108864 bytes. Automated installers should prefer the per-file manifest so every digest is verified.","tags":["Artwork packs"],"parameters":[{"$ref":"#/components/parameters/PackId"}],"responses":{"303":{"description":"Authorized redirect to a short-lived private object URL. Do not forward the API Authorization header to the redirect host.","headers":{"Location":{"description":"Short-lived HTTPS URL for the immutable object.","required":true,"schema":{"type":"string","format":"uri"}},"Cache-Control":{"description":"The redirect response is not cacheable.","schema":{"type":"string","example":"private, no-store"}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"dsg_live_…","description":"A Studio API key. Send it only to app.designelier.com and never put it in a URL."}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"description":"A caller-generated key scoped to the credential and operation. Repeating a completed request with the same key and canonically identical JSON replays its original status and body. Reusing it with a different canonical body returns 409. JSON whitespace and object-key order are insignificant.","schema":{"type":"string","minLength":8,"maxLength":128,"pattern":"^[\\x21-\\x7E]+$","example":"plan_019fcbd2-106e-7d33-8608-63df57f70e4d"}},"PackId":{"name":"id","in":"path","required":true,"description":"Artwork pack UUID.","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"}},"AssetId":{"name":"asset_id","in":"path","required":true,"description":"Generated asset UUID from the successful pack manifest.","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"}}},"headers":{"RequestId":{"description":"Server-generated request UUID. Include it when contacting support.","required":true,"schema":{"type":"string","format":"uuid"}},"RetryAfter":{"description":"Suggested seconds before polling again. Present while work is in progress or throttled.","schema":{"type":"integer","minimum":1,"example":2}},"Location":{"description":"Relative URL of the artwork pack resource.","required":true,"schema":{"type":"string","format":"uri-reference","pattern":"^/v1/artwork-packs/[0-9a-f-]{36}$"}},"IdempotencyReplayed":{"description":"True only when this status and body were replayed from an earlier request.","schema":{"type":"boolean","default":false}}},"responses":{"BadRequest":{"description":"Malformed JSON, invalid headers, or a missing Idempotency-Key.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Unauthorized":{"description":"The Bearer key is missing, invalid, or revoked.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"PaymentRequired":{"description":"Available credits do not cover the exact quote.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"NotFound":{"description":"The resource does not exist for this account. Cross-account resources are also reported as 404.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Conflict":{"description":"The idempotency key has a different body, the account already has an active generation, the quote is stale or mismatched, or the pack is in the wrong state.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"PayloadTooLarge":{"description":"The request body exceeds 4096 bytes.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"UnprocessableEntity":{"description":"The JSON shape is invalid or the public website cannot be read safely.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"TooManyRequests":{"description":"The account, key, or source IP exceeded a planning limit.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"InternalError":{"description":"An unexpected server error occurred. The message contains no internal details.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"ServiceUnavailable":{"description":"A required worker or private-storage dependency is temporarily unavailable.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"schemas":{"PlanArtworkPackRequest":{"type":"object","additionalProperties":false,"required":["url"],"properties":{"url":{"type":"string","format":"uri","maxLength":2048,"pattern":"^https?://[^\\s/@#]+(?:[/?][^\\s#]*)?$","description":"Public website URL. Credentials and fragments are not accepted.","example":"https://example.com/"},"name":{"type":"string","minLength":1,"maxLength":80,"pattern":"\\S","description":"Optional display name. The server derives one from the site when omitted.","example":"Example launch pack"}}},"ConfirmArtworkPackRequest":{"type":"object","additionalProperties":false,"required":["quote_id","confirmed_credits"],"properties":{"quote_id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"confirmed_credits":{"type":"integer","minimum":1,"maximum":16,"description":"Must exactly equal the current quote's credits.","example":9}}},"Account":{"type":"object","additionalProperties":false,"required":["credits"],"properties":{"credits":{"type":"object","additionalProperties":false,"required":["total","reserved","available"],"description":"`available` always equals `total - reserved`.","properties":{"total":{"type":"integer","minimum":0},"reserved":{"type":"integer","minimum":0},"available":{"type":"integer","minimum":0}}}}},"ArtworkPackState":{"type":"string","enum":["queued","analyzing","awaiting_confirmation","generating","succeeded","failed"],"description":"`queued` precedes a worker attempt; `analyzing` plans; `awaiting_confirmation` has a quote; `generating` follows confirmation; `succeeded` exposes all verified assets; `failed` exposes none."},"ArtworkPackQuote":{"type":"object","additionalProperties":false,"required":["id","credits","expires_at"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"credits":{"type":"integer","minimum":1,"maximum":16},"expires_at":{"type":"string","format":"date-time"}}},"ArtworkPackAsset":{"type":"object","additionalProperties":false,"required":["id","path","media_type","bytes","sha256","content_url"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"path":{"type":"string","maxLength":240,"pattern":"^public/designelier/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/[A-Za-z0-9][A-Za-z0-9._-]{0,79}\\.svg$","description":"Unique repository-relative install path under `public/designelier/{pack-id}/`. It never contains parent segments, backslashes, or an absolute path."},"media_type":{"type":"string","const":"image/svg+xml"},"bytes":{"type":"integer","minimum":1,"maximum":8388608},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$"},"content_url":{"type":"string","format":"uri-reference","maxLength":240,"pattern":"^/v1/artwork-packs/[0-9a-f-]{36}/assets/[0-9a-f-]{36}/content$"}}},"ArtworkPackFailure":{"type":"object","additionalProperties":false,"required":["code","message"],"properties":{"code":{"type":"string","enum":["page_unreachable","planning_failed","generation_failed","verification_failed","storage_failed"]},"message":{"type":"string","minLength":1,"maxLength":240}}},"ArtworkPack":{"type":"object","additionalProperties":false,"required":["id","state","name","url","created_at","updated_at","quote","assets","error"],"x-max-response-bytes":262144,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"state":{"$ref":"#/components/schemas/ArtworkPackState"},"name":{"type":"string","minLength":1,"maxLength":80},"url":{"type":"string","format":"uri","maxLength":2048},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"quote":{"oneOf":[{"$ref":"#/components/schemas/ArtworkPackQuote"},{"type":"null"}]},"assets":{"type":"array","maxItems":16,"uniqueItems":true,"description":"The sum of declared asset bytes is capped at 67108864.","items":{"$ref":"#/components/schemas/ArtworkPackAsset"}},"error":{"oneOf":[{"$ref":"#/components/schemas/ArtworkPackFailure"},{"type":"null"}]}},"allOf":[{"if":{"properties":{"state":{"enum":["awaiting_confirmation","generating","succeeded"]}}},"then":{"properties":{"quote":{"$ref":"#/components/schemas/ArtworkPackQuote"}}}},{"if":{"properties":{"state":{"const":"succeeded"}}},"then":{"properties":{"assets":{"minItems":1},"error":{"type":"null"}}},"else":{"properties":{"assets":{"maxItems":0}}}},{"if":{"properties":{"state":{"const":"failed"}}},"then":{"properties":{"error":{"$ref":"#/components/schemas/ArtworkPackFailure"}}},"else":{"properties":{"error":{"type":"null"}}}}]},"ErrorEnvelope":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"object","additionalProperties":false,"required":["code","message","request_id"],"properties":{"code":{"type":"string","enum":["malformed_json","invalid_request","missing_idempotency_key","unauthorized","insufficient_credits","not_found","idempotency_conflict","active_generation","quote_mismatch","quote_expired","invalid_state","payload_too_large","rate_limited","internal_error","service_unavailable"]},"message":{"type":"string","minLength":1,"maxLength":240},"request_id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"details":{"type":"object","maxProperties":32,"additionalProperties":true,"description":"Optional safe, bounded machine-readable context. Never contains credentials or fetched content."}}}},"example":{"error":{"code":"quote_mismatch","message":"Confirm the current quote and exact credit amount.","request_id":"019fcbd2-106e-7d33-8608-63df57f70e4d"}}}}}}