{"openapi":"3.1.2","jsonSchemaDialect":"https:\/\/json-schema.org\/draft\/2020-12\/schema","info":{"title":"Capturewell API","version":"1.0.0","description":"Create images and fixed A4 PDFs, queue capture batches, deliver signed terminal webhooks or retained files to storage you control, retry failed captures, and manage recipes, watermarks, templates, and schedules. All authenticated v1 operations require a server-side Capturewell API key and default to 60 requests per minute; batch creation and storage re-delivery document lower additional limits. Request throttling and credit quota exhaustion both use HTTP 429 but have different response bodies. Retry only responses that explicitly set error.retryable to true, or wait for Retry-After after request throttling. Screenshot creation has no idempotency key, so do not blindly replay an ambiguous request.","termsOfService":"https:\/\/capturewell.app\/terms","contact":{"name":"Capturewell","url":"https:\/\/capturewell.app\/","email":"feedback@capturewell.app"}},"servers":[{"url":"https:\/\/api.capturewell.app","description":"Capturewell API"}],"externalDocs":{"description":"Capturewell API documentation","url":"https:\/\/capturewell.app\/docs"},"tags":[{"name":"Account","description":"Inspect the authenticated account and its current credit balance."},{"name":"Screenshots","description":"Create, batch, poll, retry, list, deliver, delete, and unlock retained image or PDF captures."},{"name":"Webhooks","description":"Configure the account endpoint that receives signed terminal capture events and dashboard test delivery."},{"name":"Recipes","description":"Manage account-owned natural-language browser-action recipes."},{"name":"Watermarks","description":"Manage account-owned image watermarks and their placement settings."},{"name":"Templates","description":"Manage reusable screenshot settings and queue captures from them."},{"name":"Schedules","description":"Manage recurring capture schedules for templates."}],"security":[{"bearerAuth":[]}],"paths":{"\/v1\/account":{"get":{"tags":["Account"],"summary":"Get the current account","description":"Returns the authenticated user and current monthly and purchased credit availability, including credits reserved by queued or processing captures.","operationId":"getAccount","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Current account and credit balance.","content":{"application\/json":{"schema":{"type":"object","required":["user","credits"],"properties":{"user":{"$ref":"#\/components\/schemas\/AccountUser"},"credits":{"$ref":"#\/components\/schemas\/CreditBalance"}},"example":{"user":{"id":42,"name":"Mason Capture","email":"mason@example.com","avatar":"https:\/\/capturewell.test\/storage\/avatars\/mason.webp"},"credits":{"monthly":{"used":12,"reserved":2,"limit":100,"remaining":86},"purchased":{"balance":50,"reserved":1,"available":49},"total_available":135}}}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"429":{"$ref":"#\/components\/responses\/Throttled"}}}},"\/v1\/webhook-endpoint":{"get":{"tags":["Webhooks"],"summary":"Get the webhook endpoint","description":"Returns the account's configured endpoint. The signing secret is never returned after creation or rotation.","operationId":"getWebhookEndpoint","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Configured endpoint.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/WebhookEndpoint"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"404":{"$ref":"#\/components\/responses\/NotFound"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"put":{"tags":["Webhooks"],"summary":"Create or replace the webhook endpoint","description":"Stores one public HTTPS endpoint and rotates its signing secret. The returned base64url secret is shown exactly once; replacing the endpoint affects new captures only.","operationId":"putWebhookEndpoint","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/WebhookEndpointWriteRequest"}}}},"responses":{"200":{"description":"Endpoint saved and a new signing secret issued.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/WebhookEndpointWithSecret"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"delete":{"tags":["Webhooks"],"summary":"Delete the webhook endpoint","description":"Removes the current endpoint. Existing captures retain their encrypted snapshot until delivery reaches a terminal state.","operationId":"deleteWebhookEndpoint","security":[{"bearerAuth":[]}],"responses":{"204":{"description":"Endpoint removed or already absent."},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"429":{"$ref":"#\/components\/responses\/Throttled"}}}},"\/v1\/screenshot-batches":{"post":{"tags":["Screenshots"],"summary":"Queue a screenshot batch","description":"Atomically reserves credits and creates 1\u201310 independent queued captures with shared options, including fixed A4 PDF. Duplicate URLs remain separate ordered items. PDF has a two-credit base and follows the same incompatible-field and required-brand-removal rules as asynchronous single capture. Each item uses the ordinary capture queue, retry, retention, and settlement lifecycle. Webhooks, delivery to your storage, templates, schedules, and per-item overrides are not supported. This action also has a five-requests-per-minute limit.","operationId":"createScreenshotBatch","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/CaptureBatchRequest"}}}},"responses":{"202":{"description":"The complete batch was created and queued.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/CaptureBatch"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/ThrottledOrQuota"},"503":{"$ref":"#\/components\/responses\/BatchDispatchDeferred"}}}},"\/v1\/screenshot-batches\/{captureBatch}":{"parameters":[{"$ref":"#\/components\/parameters\/CaptureBatchId"}],"get":{"tags":["Screenshots"],"summary":"Get a screenshot batch","description":"Returns derived aggregate state and every item in original request order. Poll while queued or processing. Deleted items remain as minimal historical entries without signed file URLs. A batch owned by another account is indistinguishable from a missing batch.","operationId":"getScreenshotBatch","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Current batch and ordered item state.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/CaptureBatch"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"404":{"$ref":"#\/components\/responses\/NotFound"},"429":{"$ref":"#\/components\/responses\/Throttled"}}}},"\/v1\/screenshots":{"get":{"tags":["Screenshots"],"summary":"List screenshots","description":"Returns the authenticated account's captures newest first, 20 per page. A recognized status filters the collection. An unknown status is currently ignored and returns the unfiltered collection.","operationId":"listScreenshots","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#\/components\/parameters\/Page"},{"$ref":"#\/components\/parameters\/CaptureStatus"}],"responses":{"200":{"description":"Paginated captures.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/CapturePaginator"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"post":{"tags":["Screenshots"],"summary":"Create a screenshot synchronously","description":"Creates and renders an image before responding. A standard viewport capture starts at one credit; full-page mode starts at two, higher density tiers add credits, and configured watermark features may add credits. Recipe-assisted captures and format=pdf are async-only; PDF returns 422 with error.code pdf_requires_async before any capture or credit reservation is created. This operation has no idempotency key, so do not blindly replay it after an ambiguous network failure.","operationId":"createScreenshot","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ScreenshotRequest"},"example":{"url":"https:\/\/example.com","format":"png","preset":"desktop","full_page":true}}}},"responses":{"201":{"description":"The image completed. Signed file, image, and download URLs remain valid until expires_at; clients should trust that field rather than assume a fixed retention duration.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Capture"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"422":{"$ref":"#\/components\/responses\/ValidationOrRendererFailure"},"429":{"$ref":"#\/components\/responses\/ThrottledOrQuota"},"503":{"$ref":"#\/components\/responses\/RendererUnavailable"}}}},"\/v1\/screenshots\/async":{"post":{"tags":["Screenshots"],"summary":"Queue a screenshot","description":"Creates a queued image or fixed A4 PDF and returns immediately. Poll the capture with exponential backoff until status is completed or failed. PDF costs two base credits, uses screen media and background graphics, and requires quality, full_page, device_scale_factor, and watermark_id to be omitted. Queued and processing are non-terminal; completed and failed are terminal. Set webhook to true to snapshot the configured endpoint and signing secret. Optionally provide a short-lived public HTTPS delivery_url that accepts one PUT with Content-Type and Content-Length. Delivery to your storage is at least once and independent of capture status, credits, webhook delivery, and local result retention.","operationId":"createScreenshotAsync","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/AsyncScreenshotRequest"},"example":{"url":"https:\/\/example.com","format":"pdf","preset":"desktop","recipe_id":"01J00000000000000000000001","remove_branding":true,"webhook":true,"delivery_url":"https:\/\/storage.example.com\/captures\/result.pdf?signature=replace-me"}}}},"responses":{"202":{"description":"The screenshot was queued.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Capture"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/ThrottledOrQuota"}}}},"\/v1\/screenshots\/estimate":{"post":{"tags":["Screenshots"],"summary":"Estimate screenshot credits","description":"Validates screenshot options and returns their current credit cost without creating a capture, reserving credits, or starting a render. Async-only delivery and webhook fields are accepted but do not affect the estimate.","operationId":"estimateScreenshotCredits","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/AsyncScreenshotRequest"},"example":{"url":"https:\/\/example.com","format":"png","preset":"desktop","full_page":true,"device_scale_factor":2}}}},"responses":{"200":{"description":"Estimated credit cost at current pricing.","content":{"application\/json":{"schema":{"type":"object","required":["credits"],"properties":{"credits":{"type":"integer","minimum":1}},"example":{"credits":3}}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/Throttled"}}}},"\/v1\/screenshots\/{capture}":{"parameters":[{"$ref":"#\/components\/parameters\/CaptureId"}],"get":{"tags":["Screenshots"],"summary":"Get a screenshot","description":"Returns one account-owned capture. Completed, unexpired captures with retained files include signed file and download URLs; image_url is populated only for image formats. Other states and expired captures return null URLs. A capture owned by another account is indistinguishable from a missing capture.","operationId":"getScreenshot","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Capture details.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Capture"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"404":{"$ref":"#\/components\/responses\/NotFound"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"delete":{"tags":["Screenshots"],"summary":"Delete a screenshot","description":"Cancels a queued capture or deletes a completed or failed capture and its retained files. Processing captures cannot be deleted. Historical credit usage remains. Retry a storage cleanup failure only when error.retryable is true.","operationId":"deleteScreenshot","security":[{"bearerAuth":[]}],"responses":{"204":{"description":"The capture was deleted. The response has no body."},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"404":{"$ref":"#\/components\/responses\/NotFound"},"409":{"$ref":"#\/components\/responses\/CaptureConflict"},"429":{"$ref":"#\/components\/responses\/Throttled"},"503":{"$ref":"#\/components\/responses\/CaptureCleanupUnavailable"}}}},"\/v1\/screenshots\/{capture}\/retry":{"parameters":[{"$ref":"#\/components\/parameters\/CaptureId"}],"post":{"tags":["Screenshots"],"summary":"Retry a failed screenshot","description":"Creates a new queued capture from the saved options of an account-owned failed capture. The failed capture remains unchanged, and the new capture reserves credits at current pricing. Repeated calls create separate captures. Webhook and storage delivery requests are not copied.","operationId":"retryScreenshot","security":[{"bearerAuth":[]}],"responses":{"202":{"description":"A new screenshot was queued.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Capture"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"404":{"$ref":"#\/components\/responses\/NotFound"},"409":{"$ref":"#\/components\/responses\/CaptureRetryConflict"},"429":{"$ref":"#\/components\/responses\/ThrottledOrQuota"}}}},"\/v1\/screenshots\/{capture}\/delivery":{"parameters":[{"$ref":"#\/components\/parameters\/CaptureId"}],"post":{"tags":["Screenshots"],"summary":"Deliver a retained screenshot to storage you control","description":"Queues a new at-least-once PUT of the current retained capture bytes to a short-lived public HTTPS URL. The capture must be owned, completed, unexpired, present locally, and not already pending delivery. Re-delivery does not re-render, consume credits, extend retention, or delete any object in your storage. A required Capturewell watermark is included until the clean original has been unlocked.","operationId":"deliverScreenshotToCustomerStorage","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/CaptureDeliveryRequest"}}}},"responses":{"202":{"description":"Delivery to your storage was queued.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Capture"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"404":{"$ref":"#\/components\/responses\/NotFound"},"409":{"$ref":"#\/components\/responses\/CaptureDeliveryConflict"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/Throttled"}}}},"\/v1\/screenshots\/{capture}\/remove-watermark":{"parameters":[{"$ref":"#\/components\/parameters\/CaptureId"}],"post":{"tags":["Screenshots"],"summary":"Unlock the clean original","description":"Permanently switches an eligible retained capture from its Capturewell-branded file to the clean original without re-rendering or extending expiry. Repeating a successful unlock is idempotent and costs no additional credits.","operationId":"removeScreenshotWatermark","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The current capture details. watermarked is false after a successful unlock.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Capture"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"404":{"$ref":"#\/components\/responses\/NotFound"},"409":{"$ref":"#\/components\/responses\/CaptureWatermarkConflict"},"429":{"$ref":"#\/components\/responses\/ThrottledOrQuota"}}}},"\/v1\/recipes":{"get":{"tags":["Recipes"],"summary":"List recipes","description":"Returns the authenticated account's active recipes ordered by most recently updated, 20 per page.","operationId":"listRecipes","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#\/components\/parameters\/Page"}],"responses":{"200":{"description":"Paginated recipes.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/RecipePaginator"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"post":{"tags":["Recipes"],"summary":"Create a recipe","description":"Creates an account-owned natural-language recipe. Recipe-assisted screenshots must use the asynchronous screenshot endpoint and may be subject to a feature gate.","operationId":"createRecipe","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/RecipeWriteRequest"},"example":{"name":"Dismiss cookie banner","instructions":"Accept the cookie banner, then finish."}}}},"responses":{"201":{"description":"The recipe was created.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Recipe"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/Throttled"}}}},"\/v1\/recipes\/{recipe}":{"parameters":[{"$ref":"#\/components\/parameters\/RecipeId"}],"get":{"tags":["Recipes"],"summary":"Get a recipe","description":"Returns one account-owned recipe. Recipes owned by other accounts return 404.","operationId":"getRecipe","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Recipe details.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Recipe"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"404":{"$ref":"#\/components\/responses\/NotFound"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"put":{"tags":["Recipes"],"summary":"Replace a recipe","description":"Replaces the writable recipe fields. Both name and instructions are required. Updating a recipe owned by another account currently returns 403, while an unknown identifier returns 404.","operationId":"replaceRecipe","security":[{"bearerAuth":[]}],"requestBody":{"$ref":"#\/components\/requestBodies\/RecipeWrite"},"responses":{"200":{"$ref":"#\/components\/responses\/RecipeOk"},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"patch":{"tags":["Recipes"],"summary":"Update a recipe with a complete payload","description":"PATCH currently has the same complete-payload validation as PUT: both name and instructions are required. Updating a recipe owned by another account currently returns 403, while an unknown identifier returns 404.","operationId":"updateRecipe","security":[{"bearerAuth":[]}],"requestBody":{"$ref":"#\/components\/requestBodies\/RecipeWrite"},"responses":{"200":{"$ref":"#\/components\/responses\/RecipeOk"},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"delete":{"tags":["Recipes"],"summary":"Delete a recipe","description":"Soft-deletes an account-owned recipe. Existing capture snapshots remain unchanged. Recipes owned by other accounts return 404.","operationId":"deleteRecipe","security":[{"bearerAuth":[]}],"responses":{"204":{"description":"The recipe was deleted. The response has no body."},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"404":{"$ref":"#\/components\/responses\/NotFound"},"429":{"$ref":"#\/components\/responses\/Throttled"}}}},"\/v1\/watermarks":{"get":{"tags":["Watermarks"],"summary":"List watermarks","description":"Returns the authenticated account's image watermarks newest first, 20 per page.","operationId":"listWatermarks","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#\/components\/parameters\/Page"}],"responses":{"200":{"description":"Paginated watermarks.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/WatermarkPaginator"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"post":{"tags":["Watermarks"],"summary":"Create a watermark","description":"Uploads an account-owned image watermark. Send multipart\/form-data. Images may be JPG\/JPEG, PNG, or WebP, at most 512 KiB and 4096 by 4096 pixels.","operationId":"createWatermark","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"multipart\/form-data":{"schema":{"$ref":"#\/components\/schemas\/WatermarkCreateRequest"},"encoding":{"image":{"contentType":"image\/jpeg, image\/png, image\/webp"}}}}},"responses":{"201":{"description":"The watermark was created.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Watermark"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/Throttled"}}}},"\/v1\/watermarks\/{watermark}":{"parameters":[{"$ref":"#\/components\/parameters\/WatermarkId"}],"get":{"tags":["Watermarks"],"summary":"Get a watermark","description":"Returns one account-owned watermark and its authenticated image URL. Watermarks owned by other accounts return 404.","operationId":"getWatermark","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Watermark details.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Watermark"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"404":{"$ref":"#\/components\/responses\/NotFound"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"put":{"tags":["Watermarks"],"summary":"Replace watermark settings","description":"Replaces every writable setting. The image cannot be replaced. Updating a watermark owned by another account currently returns 403, while an unknown identifier returns 404.","operationId":"replaceWatermark","security":[{"bearerAuth":[]}],"requestBody":{"$ref":"#\/components\/requestBodies\/WatermarkUpdate"},"responses":{"200":{"$ref":"#\/components\/responses\/WatermarkOk"},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"patch":{"tags":["Watermarks"],"summary":"Update watermark settings with a complete payload","description":"PATCH currently has the same complete-payload validation as PUT. Send name, position, opacity_percent, scale_percent, and margin; image replacement is prohibited. Cross-account updates currently return 403.","operationId":"updateWatermark","security":[{"bearerAuth":[]}],"requestBody":{"$ref":"#\/components\/requestBodies\/WatermarkUpdate"},"responses":{"200":{"$ref":"#\/components\/responses\/WatermarkOk"},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"delete":{"tags":["Watermarks"],"summary":"Delete a watermark","description":"Deletes an account-owned watermark unless it is referenced by a template or an active queued or processing capture.","operationId":"deleteWatermark","security":[{"bearerAuth":[]}],"responses":{"204":{"description":"The watermark was deleted. The response has no body."},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"404":{"$ref":"#\/components\/responses\/NotFound"},"409":{"$ref":"#\/components\/responses\/WatermarkConflict"},"429":{"$ref":"#\/components\/responses\/Throttled"}}}},"\/v1\/watermarks\/{watermark}\/image":{"parameters":[{"$ref":"#\/components\/parameters\/WatermarkId"}],"get":{"tags":["Watermarks"],"summary":"Download a watermark image","description":"Returns the authenticated account-owned watermark image as binary data. The response is privately cacheable for five minutes.","operationId":"getWatermarkImage","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The stored watermark image.","headers":{"Cache-Control":{"description":"Private five-minute cache policy.","schema":{"type":"string","example":"private, max-age=300"}},"X-Content-Type-Options":{"description":"Prevents MIME sniffing.","schema":{"type":"string","const":"nosniff"}}},"content":{"image\/jpeg":{"schema":{"type":"string","format":"binary"}},"image\/png":{"schema":{"type":"string","format":"binary"}},"image\/webp":{"schema":{"type":"string","format":"binary"}},"application\/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"404":{"$ref":"#\/components\/responses\/NotFound"},"429":{"$ref":"#\/components\/responses\/Throttled"}}}},"\/v1\/templates":{"get":{"tags":["Templates"],"summary":"List templates","description":"Returns the authenticated account's templates ordered by most recently updated, 20 per page.","operationId":"listTemplates","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#\/components\/parameters\/Page"}],"responses":{"200":{"description":"Paginated templates.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TemplatePaginator"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"post":{"tags":["Templates"],"summary":"Create a template","description":"Creates a reusable screenshot template. The owned watermark_id and recipe_id fields are subject to the same feature gates and ownership rules as screenshot creation. capture_options stores normalized options without url.","operationId":"createTemplate","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TemplateWriteRequest"},"example":{"name":"Homepage desktop","url":"https:\/\/example.com","format":"png","preset":"desktop","full_page":true}}}},"responses":{"201":{"description":"The template was created.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Template"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/Throttled"}}}},"\/v1\/templates\/{template}":{"parameters":[{"$ref":"#\/components\/parameters\/TemplateId"}],"get":{"tags":["Templates"],"summary":"Get a template","description":"Returns one account-owned template. Templates owned by other accounts return 404.","operationId":"getTemplate","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Template details.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Template"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"404":{"$ref":"#\/components\/responses\/NotFound"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"put":{"tags":["Templates"],"summary":"Replace a template","description":"Replaces the template's writable representation. name and url are required; omitted optional capture settings are normalized back to defaults. Updating a template owned by another account currently returns 403.","operationId":"replaceTemplate","security":[{"bearerAuth":[]}],"requestBody":{"$ref":"#\/components\/requestBodies\/TemplateWrite"},"responses":{"200":{"$ref":"#\/components\/responses\/TemplateOk"},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"patch":{"tags":["Templates"],"summary":"Update a template with a complete payload","description":"PATCH currently has the same complete-payload behavior as PUT. Send name, url, and every optional setting that should remain non-default; omitted optional settings reset to defaults. Cross-account updates currently return 403.","operationId":"updateTemplate","security":[{"bearerAuth":[]}],"requestBody":{"$ref":"#\/components\/requestBodies\/TemplateWrite"},"responses":{"200":{"$ref":"#\/components\/responses\/TemplateOk"},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"delete":{"tags":["Templates"],"summary":"Delete a template","description":"Deletes an account-owned template. Existing captures remain and their template_id becomes null.","operationId":"deleteTemplate","security":[{"bearerAuth":[]}],"responses":{"204":{"description":"The template was deleted. The response has no body."},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"404":{"$ref":"#\/components\/responses\/NotFound"},"429":{"$ref":"#\/components\/responses\/Throttled"}}}},"\/v1\/templates\/{template}\/screenshots":{"parameters":[{"$ref":"#\/components\/parameters\/TemplateId"}],"post":{"tags":["Templates"],"summary":"Queue a screenshot from a template","description":"Queues an asynchronous screenshot using the template's normalized settings and current owned recipe or watermark snapshot. Poll the returned capture through the screenshots endpoint.","operationId":"createTemplateScreenshot","security":[{"bearerAuth":[]}],"responses":{"202":{"description":"The template screenshot was queued.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Capture"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/ThrottledOrQuota"}}}},"\/v1\/schedules":{"get":{"tags":["Schedules"],"summary":"List schedules","description":"Returns the authenticated account's schedules ordered by most recently updated, 20 per page.","operationId":"listSchedules","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#\/components\/parameters\/Page"}],"responses":{"200":{"description":"Paginated schedules.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/SchedulePaginator"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"post":{"tags":["Schedules"],"summary":"Create a schedule","description":"Creates a recurring schedule for an owned template. daily, weekly, and monthly schedules require time; weekly also requires weekday 1 through 7, and monthly requires month_day 1 through 28.","operationId":"createSchedule","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ScheduleWriteRequest"},"example":{"template_id":42,"enabled":true,"frequency":"weekly","time":"09:00","timezone":"Europe\/London","weekday":1,"month_day":null}}}},"responses":{"201":{"description":"The schedule was created.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Schedule"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/Throttled"}}}},"\/v1\/schedules\/{schedule}":{"parameters":[{"$ref":"#\/components\/parameters\/ScheduleId"}],"get":{"tags":["Schedules"],"summary":"Get a schedule","description":"Returns one account-owned schedule. Schedules owned by other accounts return 404.","operationId":"getSchedule","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Schedule details.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Schedule"}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"404":{"$ref":"#\/components\/responses\/NotFound"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"put":{"tags":["Schedules"],"summary":"Replace a schedule","description":"Replaces every writable schedule field, including conditional fields for the selected frequency. Updating a schedule owned by another account currently returns 403.","operationId":"replaceSchedule","security":[{"bearerAuth":[]}],"requestBody":{"$ref":"#\/components\/requestBodies\/ScheduleWrite"},"responses":{"200":{"$ref":"#\/components\/responses\/ScheduleOk"},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"patch":{"tags":["Schedules"],"summary":"Update a schedule with a complete payload","description":"PATCH currently has the same complete-payload validation as PUT. Send template_id, enabled, frequency, timezone, and the conditional time, weekday, or month_day fields required by that frequency. Cross-account updates currently return 403.","operationId":"updateSchedule","security":[{"bearerAuth":[]}],"requestBody":{"$ref":"#\/components\/requestBodies\/ScheduleWrite"},"responses":{"200":{"$ref":"#\/components\/responses\/ScheduleOk"},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/Throttled"}}},"delete":{"tags":["Schedules"],"summary":"Delete a schedule","description":"Deletes an account-owned schedule without deleting its template.","operationId":"deleteSchedule","security":[{"bearerAuth":[]}],"responses":{"204":{"description":"The schedule was deleted. The response has no body."},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"404":{"$ref":"#\/components\/responses\/NotFound"},"429":{"$ref":"#\/components\/responses\/Throttled"}}}}},"webhooks":{"captureTerminal":{"post":{"summary":"Receive a terminal capture event","description":"Capturewell sends the exact compact JSON bytes described here. Parse X-Capturewell-Signature as t={unix-seconds},v1={hex-hmac}; reject timestamps outside a five-minute tolerance and compare HMAC-SHA256(signing_secret, t + '.' + raw_request_body) in constant time. Return any 2xx response to acknowledge the event and deduplicate retries by X-Capturewell-Event-Id. Delivery never follows redirects and makes at most five attempts with 10, 60, 300, and 900 second backoff after transport failures or HTTP 408, 409, 425, 429, and 5xx responses.","parameters":[{"name":"X-Capturewell-Event-Id","in":"header","required":true,"schema":{"type":"string"},"example":"capture:01J00000000000000000000000:completed"},{"name":"X-Capturewell-Event","in":"header","required":true,"schema":{"type":"string","enum":["capture.completed","capture.failed"]},"example":"capture.completed"},{"name":"X-Capturewell-Signature","in":"header","required":true,"schema":{"type":"string"},"example":"t=1784550896,v1=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/CaptureWebhookEvent"},"example":{"id":"capture:01J00000000000000000000000:completed","type":"capture.completed","created_at":"2026-07-20T12:34:56Z","data":{"capture":{"id":"01J00000000000000000000000","status":"completed","source":"api","target_url":"https:\/\/example.com","options":{"url":"https:\/\/example.com","format":"png","quality":null,"full_page":false,"preset":"desktop","viewport":{"width":1440,"height":900,"device_scale_factor":1,"mobile":false},"delay_ms":0,"timeout_ms":30000,"wait_until":"networkidle2","wait_for_selector":null,"dark_mode":false,"reduced_motion":true,"remove_branding":false},"file_url":"https:\/\/example.com\/captures\/01J00000000000000000000000\/file?expires=1784203200&signature=fake","image_url":"https:\/\/example.com\/captures\/01J00000000000000000000000\/file?expires=1784203200&signature=fake","download_url":"https:\/\/example.com\/captures\/01J00000000000000000000000\/download?expires=1784203200&signature=fake","expires_at":"2026-07-21T12:34:56Z","credits_used":1,"watermarked":false,"watermark_removal":{"eligible":false,"credits":1,"removed_at":null},"recipe":null,"webhook":{"status":"pending","attempts":1,"delivered_at":null,"last_error_code":null},"external_delivery":null,"created_at":"2026-07-20T12:34:00Z","metadata":{"width":1440,"height":900,"format":"png","bytes":128000,"duration_ms":840},"error":null}}}}}},"responses":{"200":{"description":"Event accepted. Any 2xx response is treated as successful delivery."}}}},"endpointTest":{"post":{"summary":"Receive a dashboard webhook test event","description":"The dashboard Send test action makes one synchronous, non-retried delivery using the currently configured endpoint and signing secret. Verify the exact raw JSON bytes with the same five-minute timestamp tolerance and constant-time HMAC comparison as terminal events. A destination 2xx is shown as success; a guarded transport failure or non-2xx response is shown as failure in the dashboard.","parameters":[{"name":"X-Capturewell-Event-Id","in":"header","required":true,"schema":{"type":"string","pattern":"^test:[0-9A-HJKMNP-TV-Z]{26}$"},"example":"test:01J00000000000000000000011"},{"name":"X-Capturewell-Event","in":"header","required":true,"schema":{"type":"string","const":"webhook.test"},"example":"webhook.test"},{"name":"X-Capturewell-Signature","in":"header","required":true,"schema":{"type":"string"},"example":"t=1784550896,v1=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/WebhookTestEvent"},"example":{"id":"test:01J00000000000000000000011","type":"webhook.test","created_at":"2026-07-22T09:30:00Z","data":{"message":"Capturewell webhook test"}}}}},"responses":{"200":{"description":"Test event accepted. Any 2xx response is shown as successful delivery."}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"cw_\u2026","description":"Send a server-side Capturewell API key as Authorization: Bearer $CAPTUREWELL_API_KEY. Missing, malformed, revoked, and unknown keys return the same unauthenticated response."}},"parameters":{"Page":{"name":"page","in":"query","description":"One-indexed result page. Collections contain 20 records per page.","required":false,"schema":{"type":"integer","minimum":1,"default":1},"example":1},"CaptureStatus":{"name":"status","in":"query","description":"Optional capture status filter. An unknown value is silently ignored rather than rejected.","required":false,"schema":{"type":"string","enum":["queued","processing","completed","failed"]},"example":"completed"},"CaptureId":{"name":"capture","in":"path","description":"Capture string identifier.","required":true,"schema":{"type":"string"},"example":"01J00000000000000000000000"},"CaptureBatchId":{"name":"captureBatch","in":"path","description":"Capture batch ULID.","required":true,"schema":{"type":"string"},"example":"01J00000000000000000000010"},"RecipeId":{"name":"recipe","in":"path","description":"Recipe public ULID.","required":true,"schema":{"type":"string"},"example":"01J00000000000000000000001"},"WatermarkId":{"name":"watermark","in":"path","description":"Watermark public ULID.","required":true,"schema":{"type":"string"},"example":"01J00000000000000000000002"},"TemplateId":{"name":"template","in":"path","description":"Template integer identifier.","required":true,"schema":{"type":"integer","format":"int64","minimum":1},"example":42},"ScheduleId":{"name":"schedule","in":"path","description":"Schedule integer identifier.","required":true,"schema":{"type":"integer","format":"int64","minimum":1},"example":84}},"requestBodies":{"RecipeWrite":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/RecipeWriteRequest"},"example":{"name":"Open pricing details","instructions":"Open the annual pricing disclosure, then finish."}}}},"WatermarkUpdate":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/WatermarkUpdateRequest"},"example":{"name":"Product logo","position":"bottom-right","opacity_percent":80,"scale_percent":20,"margin":24}}}},"TemplateWrite":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TemplateWriteRequest"},"example":{"name":"Homepage mobile","url":"https:\/\/example.com","format":"png","preset":"iphone_16","full_page":true}}}},"ScheduleWrite":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ScheduleWriteRequest"},"example":{"template_id":42,"enabled":true,"frequency":"daily","time":"09:00","timezone":"Europe\/London","weekday":null,"month_day":null}}}}},"responses":{"Unauthenticated":{"description":"The Bearer key is missing, malformed, revoked, or unknown.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorEnvelope"},"example":{"error":{"code":"unauthenticated","message":"A valid API key is required."}}}}},"Forbidden":{"description":"The authenticated account is not authorized for this operation. Cross-account resource updates currently use this response.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/FrameworkError"},"example":{"message":"This action is unauthorized."}}}},"NotFound":{"description":"The identifier was not found or is not visible to the authenticated account.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/FrameworkError"},"example":{"message":"Not Found"}}}},"ValidationFailed":{"description":"Laravel validation failed. Do not retry unchanged input.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ValidationError"},"example":{"message":"The url field is required.","errors":{"url":["The url field is required."]}}}}},"ValidationOrRendererFailure":{"description":"Validation failed, a synchronous recipe was rejected, or the renderer returned a non-retryable failure.","content":{"application\/json":{"schema":{"oneOf":[{"$ref":"#\/components\/schemas\/ValidationError"},{"$ref":"#\/components\/schemas\/ErrorEnvelope"},{"$ref":"#\/components\/schemas\/SynchronousRendererFailure"}]},"examples":{"validation":{"value":{"message":"The url field is required.","errors":{"url":["The url field is required."]}}},"recipe_requires_async":{"value":{"error":{"code":"recipe_requires_async","message":"Recipe captures must use the asynchronous endpoint."}}},"renderer_failure":{"value":{"id":"01J00000000000000000000000","status":"failed","error":{"code":"navigation_failed","message":"The target page could not be rendered.","retryable":false}}}}}}},"Throttled":{"description":"An applicable request limit was exceeded. Authenticated v1 operations default to 60 requests per minute; specific actions may document a lower additional limit. Wait for Retry-After before retrying.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests in the current window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer","example":0}},"Retry-After":{"description":"Seconds to wait before another request.","schema":{"type":"integer","minimum":0,"example":42}},"X-RateLimit-Reset":{"description":"Unix timestamp when the limiter resets.","schema":{"type":"integer","example":1784203242}}},"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/FrameworkError"},"example":{"message":"Too Many Attempts."}}}},"ThrottledOrQuota":{"description":"Either an applicable request limit was exceeded or the account lacks enough credits. Authenticated v1 operations default to 60 requests per minute; specific actions may document a lower additional limit. A quota_exceeded response does not include Retry-After and is not rescued synchronously by auto recharge; retry only after the balance has actually increased.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests in the current window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer","example":37}},"Retry-After":{"description":"Present only when the request limiter, rather than the credit quota, caused the response.","schema":{"type":"integer","minimum":0,"example":42}},"X-RateLimit-Reset":{"description":"Present when the request limiter supplies a reset timestamp.","schema":{"type":"integer","example":1784203242}}},"content":{"application\/json":{"schema":{"oneOf":[{"$ref":"#\/components\/schemas\/FrameworkError"},{"$ref":"#\/components\/schemas\/QuotaErrorEnvelope"}]},"examples":{"request_throttled":{"value":{"message":"Too Many Attempts."}},"quota_exceeded":{"value":{"error":{"code":"quota_exceeded","message":"This capture needs more credits than are currently available.","limit":100,"used":100,"requested":2,"monthly_available":0,"purchased_available":1,"available":1}}}}}}},"RendererUnavailable":{"description":"The synchronous renderer failed with a retryable error. Retry only when error.retryable is true, bearing in mind that screenshot creation has no idempotency key.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/SynchronousRendererFailure"},"example":{"id":"01J00000000000000000000000","status":"failed","error":{"code":"renderer_unavailable","message":"The renderer is currently unavailable.","retryable":true}}}}},"BatchDispatchDeferred":{"description":"The batch was committed but one or more ordinary render jobs could not be dispatched immediately. The response is retryable for status retrieval; queued-capture recovery dispatches stale items automatically. Do not repeat creation unless a second batch is intended.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/BatchDispatchDeferredError"},"example":{"batch_id":"01J00000000000000000000010","error":{"code":"batch_dispatch_deferred","message":"The batch was created and its queued captures will be retried automatically.","retryable":true}}}}},"CaptureConflict":{"description":"The capture is processing and cannot be deleted.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorEnvelope"},"example":{"error":{"code":"capture_not_deletable","message":"This capture cannot be deleted while it is processing."}}}}},"CaptureRetryConflict":{"description":"The capture is not failed, or its saved watermark or recipe is no longer available under the current account configuration.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorEnvelope"},"example":{"error":{"code":"capture_not_retryable","message":"Only failed captures can be retried."}}}}},"CaptureDeliveryConflict":{"description":"Delivery to your storage is already pending for this capture.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorEnvelope"},"example":{"error":{"code":"external_delivery_pending","message":"This capture already has a pending external delivery."}}}}},"CaptureWatermarkConflict":{"description":"The clean original cannot be unlocked because the capture is incomplete, expired, legacy, already lacks an eligible original, or no retained original remains.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorEnvelope"},"example":{"error":{"code":"capture_watermark_not_removable","message":"This capture does not have an eligible retained clean original."}}}}},"CaptureCleanupUnavailable":{"description":"Retained capture storage could not be cleaned up. This response is explicitly retryable.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorEnvelope"},"example":{"error":{"code":"capture_storage_cleanup_failed","message":"Capture storage cleanup failed.","retryable":true}}}}},"WatermarkConflict":{"description":"The watermark is referenced by a template or an active queued or processing capture.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorEnvelope"},"example":{"error":{"code":"watermark_not_deletable","message":"Remove this watermark from templates before deleting it."}}}}},"RecipeOk":{"description":"The updated recipe.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Recipe"}}}},"WatermarkOk":{"description":"The updated watermark.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Watermark"}}}},"TemplateOk":{"description":"The updated template.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Template"}}}},"ScheduleOk":{"description":"The updated schedule.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Schedule"}}}}},"schemas":{"AccountUser":{"type":"object","required":["id","name","email","avatar"],"properties":{"id":{"type":"integer","minimum":1},"name":{"type":"string"},"email":{"type":"string","format":"email"},"avatar":{"type":"string"}},"example":{"id":42,"name":"Mason Capture","email":"mason@example.com","avatar":"https:\/\/capturewell.test\/storage\/avatars\/mason.webp"}},"CreditBalance":{"type":"object","required":["monthly","purchased","total_available"],"properties":{"monthly":{"type":"object","required":["used","reserved","limit","remaining"],"properties":{"used":{"type":"integer","minimum":0},"reserved":{"type":"integer","minimum":0},"limit":{"type":"integer","minimum":0},"remaining":{"type":"integer","minimum":0}}},"purchased":{"type":"object","required":["balance","reserved","available"],"properties":{"balance":{"type":"integer"},"reserved":{"type":"integer","minimum":0},"available":{"type":"integer","minimum":0}}},"total_available":{"type":"integer","minimum":0}},"example":{"monthly":{"used":12,"reserved":2,"limit":100,"remaining":86},"purchased":{"balance":50,"reserved":1,"available":49},"total_available":135}},"FrameworkError":{"type":"object","required":["message"],"properties":{"message":{"type":"string"}}},"ValidationError":{"type":"object","required":["message","errors"],"properties":{"message":{"type":"string","description":"Summary of the first validation error and any additional error count."},"errors":{"type":"object","description":"Field names map to one or more validation messages. Nested keys use dot notation.","additionalProperties":{"type":"array","items":{"type":"string"}}}}},"ErrorEnvelope":{"type":"object","required":["error"],"properties":{"error":{"$ref":"#\/components\/schemas\/ErrorDetail"}}},"ErrorDetail":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable error identifier. Renderer error codes are extensible strings rather than a closed enum. Known examples include navigation_failed, renderer_unavailable, watermark_unavailable, recipe_not_configured, recipe_planning_failed, recipe_action_not_found, recipe_action_rejected, and recipe_action_limit."},"message":{"type":"string"},"retryable":{"type":"boolean","description":"When present, retry automatically only when true."}}},"QuotaErrorEnvelope":{"type":"object","required":["error"],"properties":{"error":{"$ref":"#\/components\/schemas\/QuotaErrorDetail"}}},"QuotaErrorDetail":{"type":"object","required":["code","message","limit","used","requested","monthly_available","purchased_available","available"],"properties":{"code":{"type":"string","const":"quota_exceeded"},"message":{"type":"string"},"limit":{"type":"integer"},"used":{"type":"integer"},"requested":{"type":"integer","minimum":0},"monthly_available":{"type":"integer","minimum":0},"purchased_available":{"type":"integer","minimum":0},"available":{"type":"integer","minimum":0}}},"SynchronousRendererFailure":{"type":"object","required":["id","status","error"],"properties":{"id":{"type":"string"},"status":{"type":"string","const":"failed"},"error":{"allOf":[{"$ref":"#\/components\/schemas\/ErrorDetail"},{"type":"object","required":["retryable"]}]}}},"BatchDispatchDeferredError":{"type":"object","required":["batch_id","error"],"properties":{"batch_id":{"type":"string"},"error":{"type":"object","required":["code","message","retryable"],"properties":{"code":{"type":"string","const":"batch_dispatch_deferred"},"message":{"type":"string"},"retryable":{"type":"boolean","const":true}}}}},"CaptureBatchRequest":{"type":"object","required":["urls"],"properties":{"urls":{"type":"array","minItems":1,"maxItems":10,"description":"Public HTTP or HTTPS targets in preserved request order. Duplicate URLs create separate captures.","items":{"type":"string","format":"uri","maxLength":2048}},"format":{"type":"string","enum":["png","jpeg","webp","avif","pdf"],"default":"png"},"quality":{"type":"integer","minimum":1,"maximum":100,"description":"Shared JPEG, WebP, or AVIF quality. Omit for PDF."},"full_page":{"type":"boolean","default":false},"preset":{"type":"string","enum":["desktop","desktop_hd","laptop","tablet","tablet_landscape","iphone_16","pixel_10","social_card","open_graph"],"default":"desktop"},"viewport":{"$ref":"#\/components\/schemas\/RequestedViewport"},"device_scale_factor":{"type":"number","minimum":1,"maximum":3},"delay_ms":{"type":"integer","minimum":0,"maximum":10000,"default":0},"timeout_ms":{"type":"integer","minimum":1000,"maximum":60000,"default":30000},"wait_until":{"type":"string","enum":["load","domcontentloaded","networkidle0","networkidle2"],"default":"networkidle2"},"wait_for_selector":{"type":["string","null"],"maxLength":500,"default":null},"dark_mode":{"type":"boolean","default":false},"reduced_motion":{"type":"boolean","default":true},"remove_branding":{"type":"boolean","default":false,"description":"For PDF under required Capturewell branding, this must be explicitly true and adds the configured removal credit up front."},"watermark_id":{"type":["string","null"],"description":"Owned watermark public ULID shared by every item. Requires remove_branding and enabled watermarking. Omit for PDF."},"recipe_id":{"type":["string","null"],"description":"Owned active recipe public ULID shared by every item."}},"allOf":[{"if":{"required":["format"],"properties":{"format":{"const":"pdf"}}},"then":{"properties":{"quality":false,"full_page":false,"device_scale_factor":false,"watermark_id":false}}}],"example":{"urls":["https:\/\/example.com","https:\/\/example.org"],"format":"webp","full_page":true,"preset":"desktop"}},"CaptureBatchCounts":{"type":"object","required":["queued","processing","completed","failed","deleted"],"properties":{"queued":{"type":"integer","minimum":0},"processing":{"type":"integer","minimum":0},"completed":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"deleted":{"type":"integer","minimum":0}}},"DeletedBatchCapture":{"type":"object","required":["id","batch_position","target_url","status"],"additionalProperties":false,"properties":{"id":{"type":"string"},"batch_position":{"type":"integer","minimum":0,"maximum":9},"target_url":{"type":"string","format":"uri"},"status":{"type":"string","const":"deleted"}}},"CaptureBatch":{"type":"object","required":["id","status","total","created_at","counts","credits_reserved","credits_used","captures"],"properties":{"id":{"type":"string"},"status":{"type":"string","enum":["queued","processing","completed","completed_with_failures","failed"]},"total":{"type":"integer","minimum":1,"maximum":10},"created_at":{"type":["string","null"],"format":"date-time"},"counts":{"$ref":"#\/components\/schemas\/CaptureBatchCounts"},"credits_reserved":{"type":"integer","minimum":0},"credits_used":{"type":"integer","minimum":0},"captures":{"type":"array","minItems":1,"maxItems":10,"items":{"oneOf":[{"$ref":"#\/components\/schemas\/Capture"},{"$ref":"#\/components\/schemas\/DeletedBatchCapture"}]}}},"example":{"id":"01J00000000000000000000010","status":"queued","total":1,"created_at":"2026-07-21T12:00:00Z","counts":{"queued":1,"processing":0,"completed":0,"failed":0,"deleted":0},"credits_reserved":1,"credits_used":0,"captures":[{"id":"01J00000000000000000000011","status":"queued","source":"api","target_url":"https:\/\/example.com","options":{"url":"https:\/\/example.com","format":"png","quality":null,"full_page":false,"preset":"desktop","viewport":{"width":1440,"height":900,"device_scale_factor":1,"mobile":false},"delay_ms":0,"timeout_ms":30000,"wait_until":"networkidle2","wait_for_selector":null,"dark_mode":false,"reduced_motion":true,"remove_branding":false},"file_url":null,"image_url":null,"download_url":null,"expires_at":"2026-07-22T12:00:00Z","credits_used":1,"watermarked":false,"watermark_removal":{"eligible":false,"credits":1,"removed_at":null},"recipe":null,"webhook":null,"external_delivery":null,"batch_id":"01J00000000000000000000010","batch_position":0,"created_at":"2026-07-21T12:00:00Z","metadata":null,"error":null}]}},"ScreenshotRequest":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","maxLength":2048,"description":"Required public HTTP or HTTPS URL. Private, loopback, link-local, and reserved targets are rejected."},"format":{"type":"string","enum":["png","jpeg","webp","avif","pdf"],"default":"png","description":"Output format. PDF is asynchronous-only and produces a fixed portrait A4 document from screen media with backgrounds and zero margins."},"quality":{"type":"integer","minimum":1,"maximum":100,"description":"JPEG, WebP, or AVIF quality. Those formats default to 82; PNG normalizes quality to null. Omit this field for PDF."},"full_page":{"type":"boolean","default":false,"description":"Capture the complete document height. Omit for PDF, which always paginates the full prepared document."},"preset":{"type":"string","enum":["desktop","desktop_hd","laptop","tablet","tablet_landscape","iphone_16","pixel_10","social_card","open_graph"],"default":"desktop","description":"Named viewport preset. The preset continues to supply mobile behavior and default density when viewport dimensions are overridden."},"viewport":{"$ref":"#\/components\/schemas\/RequestedViewport"},"device_scale_factor":{"type":"number","minimum":1,"maximum":3,"description":"Pixel density. Defaults to the selected preset. Omit for PDF, which uses density 1 while preserving the responsive viewport."},"delay_ms":{"type":"integer","minimum":0,"maximum":10000,"default":0,"description":"Additional delay after page readiness."},"timeout_ms":{"type":"integer","minimum":1000,"maximum":60000,"default":30000,"description":"Renderer navigation timeout."},"wait_until":{"type":"string","enum":["load","domcontentloaded","networkidle0","networkidle2"],"default":"networkidle2","description":"Browser readiness event."},"wait_for_selector":{"type":["string","null"],"maxLength":500,"default":null,"description":"Optional CSS selector to await before capture."},"dark_mode":{"type":"boolean","default":false,"description":"Prefer the dark color scheme."},"reduced_motion":{"type":"boolean","default":true,"description":"Prefer reduced motion while rendering."},"remove_branding":{"type":"boolean","default":false,"description":"Request clean output at creation time. When image branding is required, PDF requires this field to be explicitly true and charges the configured removal credit up front."},"watermark_id":{"type":["string","null"],"description":"Owned watermark public ULID. A non-null value is allowed only when remove_branding is true and watermarking is enabled. Omit for PDF."},"recipe_id":{"type":["string","null"],"description":"Owned active recipe public ULID. Recipe capture must be enabled and the asynchronous screenshot endpoint must be used."}},"allOf":[{"if":{"required":["format"],"properties":{"format":{"const":"pdf"}}},"then":{"properties":{"quality":false,"full_page":false,"device_scale_factor":false,"watermark_id":false}}}],"example":{"url":"https:\/\/example.com","format":"png","preset":"desktop","full_page":true}},"AsyncScreenshotRequest":{"allOf":[{"$ref":"#\/components\/schemas\/ScreenshotRequest"},{"type":"object","properties":{"webhook":{"type":"boolean","default":false,"description":"Deliver a signed terminal event using the endpoint configuration snapshotted when this capture is created. Requires a configured webhook endpoint."},"delivery_url":{"type":"string","format":"uri","maxLength":2048,"description":"Short-lived public HTTPS presigned URL for one PUT of the final retained capture bytes. It must accept Capturewell's exact Content-Type and Content-Length headers. Credentials, fragments, custom headers, multipart uploads, and private destinations are rejected. The URL and query are encrypted at rest and never returned."}}}],"example":{"url":"https:\/\/example.com","format":"pdf","preset":"desktop","remove_branding":true,"webhook":true,"delivery_url":"https:\/\/storage.example.com\/captures\/result.pdf?signature=replace-me"}},"CaptureDeliveryRequest":{"type":"object","required":["delivery_url"],"additionalProperties":false,"properties":{"delivery_url":{"type":"string","format":"uri","maxLength":2048,"description":"Replacement short-lived public HTTPS presigned URL for one PUT of the current retained capture bytes. The value is encrypted at rest and never returned."}},"example":{"delivery_url":"https:\/\/storage.example.com\/captures\/result.webp?signature=replace-me"}},"WebhookEndpointWriteRequest":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","pattern":"^[Hh][Tt][Tt][Pp][Ss]:\/\/","maxLength":2048,"description":"Resolvable public HTTPS destination without credentials or a fragment. Every resolved address must be public. Query parameters are encrypted at rest and treated as secrets."}},"example":{"url":"https:\/\/hooks.example.com\/capturewell"}},"WebhookEndpoint":{"type":"object","required":["id","url"],"properties":{"id":{"type":"string"},"url":{"type":"string","format":"uri","pattern":"^[Hh][Tt][Tt][Pp][Ss]:\/\/"}},"example":{"id":"01J00000000000000000000009","url":"https:\/\/hooks.example.com\/capturewell"}},"WebhookEndpointWithSecret":{"allOf":[{"$ref":"#\/components\/schemas\/WebhookEndpoint"},{"type":"object","required":["signing_secret"],"properties":{"signing_secret":{"type":"string","minLength":43,"maxLength":43,"pattern":"^[A-Za-z0-9_-]{43}$","description":"New 32-byte base64url signing secret. This value is returned once and cannot be retrieved later."}}}],"example":{"id":"01J00000000000000000000009","url":"https:\/\/hooks.example.com\/capturewell","signing_secret":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"}},"CaptureWebhook":{"type":"object","required":["status","attempts","delivered_at","last_error_code"],"properties":{"status":{"type":"string","enum":["pending","delivered","failed"]},"attempts":{"type":"integer","minimum":0},"delivered_at":{"type":["string","null"],"format":"date-time"},"last_error_code":{"type":["string","null"]}}},"CaptureExternalDelivery":{"type":"object","required":["status","attempts","delivered_at","etag","last_error_code"],"properties":{"status":{"type":"string","enum":["pending","delivered","failed","skipped"]},"attempts":{"type":"integer","minimum":0},"delivered_at":{"type":["string","null"],"format":"date-time"},"etag":{"type":["string","null"],"maxLength":255,"description":"A bounded, syntactically safe ETag returned by the destination, when available."},"last_error_code":{"type":["string","null"]}}},"CaptureWebhookEvent":{"type":"object","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","description":"Deterministic event ID. Retain it through the retry window and use it to deduplicate at-least-once delivery."},"type":{"type":"string","enum":["capture.completed","capture.failed"]},"created_at":{"type":"string","format":"date-time","description":"The capture terminal timestamp, not the delivery attempt timestamp."},"data":{"type":"object","required":["capture"],"properties":{"capture":{"$ref":"#\/components\/schemas\/Capture"}}}}},"WebhookTestEvent":{"type":"object","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","pattern":"^test:[0-9A-HJKMNP-TV-Z]{26}$","description":"A new event ID generated for this dashboard test attempt."},"type":{"type":"string","const":"webhook.test"},"created_at":{"type":"string","format":"date-time","description":"The UTC time at which the dashboard test was sent."},"data":{"type":"object","required":["message"],"properties":{"message":{"type":"string","const":"Capturewell webhook test"}}}}},"RequestedViewport":{"type":"object","description":"Optional custom dimensions. Either dimension may be supplied; omitted dimensions retain the selected preset value.","additionalProperties":false,"properties":{"width":{"type":"integer","minimum":320,"maximum":3840},"height":{"type":"integer","minimum":240,"maximum":2160}}},"Capture":{"type":"object","required":["id","status","source","target_url","options","file_url","image_url","download_url","expires_at","credits_used","watermarked","watermark_removal","recipe","webhook","external_delivery","created_at","metadata","error"],"properties":{"id":{"type":"string"},"batch_id":{"type":"string","description":"Present only when this capture belongs to an API batch."},"batch_position":{"type":"integer","minimum":0,"maximum":9,"description":"Zero-based request order, present only for a batch capture."},"status":{"type":"string","enum":["queued","processing","completed","failed"]},"source":{"type":"string","enum":["api","dashboard","template","schedule"]},"target_url":{"type":"string","format":"uri"},"options":{"$ref":"#\/components\/schemas\/CaptureOptions"},"file_url":{"type":["string","null"],"format":"uri","description":"Signed inline URL for any retained completed output, including PDF."},"image_url":{"type":["string","null"],"format":"uri","description":"Signed inline image URL while a completed image remains retained. This is null for PDF; use file_url for format-neutral clients."},"download_url":{"type":["string","null"],"format":"uri","description":"Signed attachment URL while a completed file remains retained."},"expires_at":{"type":["string","null"],"format":"date-time","description":"Configured retention expiry. The usual default is 24 hours, but clients must trust this timestamp."},"credits_used":{"type":"integer","minimum":0},"watermarked":{"type":"boolean","description":"Whether the separate Capturewell watermark is currently present."},"watermark_removal":{"$ref":"#\/components\/schemas\/WatermarkRemoval"},"recipe":{"oneOf":[{"$ref":"#\/components\/schemas\/CaptureRecipeSummary"},{"type":"null"}]},"webhook":{"oneOf":[{"$ref":"#\/components\/schemas\/CaptureWebhook"},{"type":"null"}],"description":"Delivery state when this asynchronous capture requested a webhook; otherwise null. Destination and signing secret are never returned."},"external_delivery":{"oneOf":[{"$ref":"#\/components\/schemas\/CaptureExternalDelivery"},{"type":"null"}],"description":"Storage delivery state when a presigned URL was requested; otherwise null. The destination URL is never returned. Delivery is independent of capture success, credits, webhooks, retention, and deletion of the object in your storage."},"created_at":{"type":["string","null"],"format":"date-time"},"metadata":{"oneOf":[{"$ref":"#\/components\/schemas\/CaptureMetadata"},{"type":"null"}]},"error":{"oneOf":[{"$ref":"#\/components\/schemas\/CaptureStoredError"},{"type":"null"}]}},"example":{"id":"01J00000000000000000000000","status":"completed","source":"api","target_url":"https:\/\/example.com","options":{"url":"https:\/\/example.com","format":"png","quality":null,"full_page":false,"preset":"desktop","viewport":{"width":1440,"height":900,"device_scale_factor":1,"mobile":false},"delay_ms":0,"timeout_ms":30000,"wait_until":"networkidle2","wait_for_selector":null,"dark_mode":false,"reduced_motion":true,"remove_branding":false},"file_url":"https:\/\/example.com\/captures\/01J00000000000000000000000\/file?expires=1784203200&signature=fake","image_url":"https:\/\/example.com\/captures\/01J00000000000000000000000\/file?expires=1784203200&signature=fake","download_url":"https:\/\/example.com\/captures\/01J00000000000000000000000\/download?expires=1784203200&signature=fake","expires_at":"2026-07-17T12:00:00+00:00","credits_used":1,"watermarked":true,"watermark_removal":{"eligible":true,"credits":1,"removed_at":null},"recipe":null,"webhook":null,"external_delivery":null,"created_at":"2026-07-16T12:00:00+00:00","metadata":{"width":1440,"height":900,"format":"png","bytes":128000,"duration_ms":840},"error":null}},"CaptureOptions":{"type":"object","required":["url","format","quality","full_page","preset","viewport","delay_ms","timeout_ms","wait_until","wait_for_selector","dark_mode","reduced_motion","remove_branding"],"properties":{"url":{"type":"string","format":"uri"},"format":{"type":"string","enum":["png","jpeg","webp","avif","pdf"],"description":"PDF options are normalized to quality null, full_page true, and device_scale_factor 1."},"quality":{"type":["integer","null"],"minimum":1,"maximum":100,"description":"Always null for PNG and PDF."},"full_page":{"type":"boolean","description":"Always true for PDF."},"preset":{"type":"string","enum":["desktop","desktop_hd","laptop","tablet","tablet_landscape","iphone_16","pixel_10","social_card","open_graph"]},"viewport":{"$ref":"#\/components\/schemas\/CaptureViewport"},"delay_ms":{"type":"integer"},"timeout_ms":{"type":"integer"},"wait_until":{"type":"string","enum":["load","domcontentloaded","networkidle0","networkidle2"]},"wait_for_selector":{"type":["string","null"]},"dark_mode":{"type":"boolean"},"reduced_motion":{"type":"boolean"},"remove_branding":{"type":"boolean"},"watermark":{"$ref":"#\/components\/schemas\/CustomWatermarkSnapshot"}}},"CaptureViewport":{"type":"object","required":["width","height","device_scale_factor","mobile"],"properties":{"width":{"type":"integer"},"height":{"type":"integer"},"device_scale_factor":{"type":"number","description":"Normalized to 1 for PDF."},"mobile":{"type":"boolean"}}},"CustomWatermarkSnapshot":{"type":"object","required":["id","name","position","opacity_percent","scale_percent","margin"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"position":{"type":"string","enum":["top-left","top-center","top-right","center-left","center","center-right","bottom-left","bottom-center","bottom-right"]},"opacity_percent":{"type":"integer"},"scale_percent":{"type":"integer"},"margin":{"type":"integer"}}},"CaptureMetadata":{"type":"object","required":["width","height","format","bytes","duration_ms"],"properties":{"width":{"type":["integer","null"],"description":"Raster width for images; measured source document width in CSS pixels for PDF."},"height":{"type":["integer","null"],"description":"Raster height for images; measured source document height in CSS pixels for PDF."},"format":{"type":"string","enum":["png","jpeg","webp","avif","pdf"]},"bytes":{"type":["integer","null"]},"duration_ms":{"type":["integer","null"]}}},"WatermarkRemoval":{"type":"object","required":["eligible","credits","removed_at"],"properties":{"eligible":{"type":"boolean"},"credits":{"type":"integer","minimum":0},"removed_at":{"type":["string","null"],"format":"date-time"}}},"CaptureRecipeSummary":{"type":"object","required":["name","action_count","fallback"],"properties":{"name":{"type":"string","maxLength":80},"action_count":{"type":["integer","null"],"minimum":0,"maximum":5},"fallback":{"oneOf":[{"$ref":"#\/components\/schemas\/CaptureRecipeFallback"},{"type":"null"}]}}},"CaptureRecipeFallback":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}},"CaptureStoredError":{"type":"object","required":["code","message"],"properties":{"code":{"type":["string","null"]},"message":{"type":["string","null"]}}},"CaptureHistoryItem":{"type":"object","required":["id","url","source","status","format","options","width","height","file_size","duration_ms","credits","watermarked","custom_watermarked","watermark_removal","recipe","error_code","error_message","created_at","expires_at","file_url","preview_url","thumbnail_url","download_url"],"properties":{"id":{"type":"string"},"url":{"type":"string","format":"uri"},"source":{"type":"string","enum":["api","dashboard","template","schedule"]},"status":{"type":"string","enum":["queued","processing","completed","failed"]},"format":{"type":"string","enum":["png","jpeg","webp","avif","pdf"]},"options":{"$ref":"#\/components\/schemas\/CaptureOptions"},"width":{"type":["integer","null"]},"height":{"type":["integer","null"]},"file_size":{"type":["integer","null"]},"duration_ms":{"type":["integer","null"]},"credits":{"type":"integer"},"watermarked":{"type":"boolean"},"custom_watermarked":{"type":"boolean"},"watermark_removal":{"$ref":"#\/components\/schemas\/WatermarkRemoval"},"recipe":{"oneOf":[{"$ref":"#\/components\/schemas\/CaptureRecipeSummary"},{"type":"null"}]},"error_code":{"type":["string","null"]},"error_message":{"type":["string","null"]},"created_at":{"type":["string","null"],"format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"},"file_url":{"type":["string","null"],"format":"uri","description":"Signed inline URL for any retained completed output."},"preview_url":{"type":["string","null"],"format":"uri","description":"Signed image preview URL. This is null for PDF."},"thumbnail_url":{"type":["string","null"],"format":"uri"},"download_url":{"type":["string","null"],"format":"uri"}}},"RecipeWriteRequest":{"type":"object","required":["name","instructions"],"properties":{"name":{"type":"string","maxLength":80},"instructions":{"type":"string","maxLength":2000}}},"Recipe":{"type":"object","required":["id","name","instructions","created_at","updated_at"],"properties":{"id":{"type":"string","description":"Public ULID."},"name":{"type":"string"},"instructions":{"type":"string"},"created_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"}},"example":{"id":"01J00000000000000000000001","name":"Dismiss cookie banner","instructions":"Accept the cookie banner, then finish.","created_at":"2026-07-16T12:00:00+00:00","updated_at":"2026-07-16T12:00:00+00:00"}},"WatermarkCreateRequest":{"type":"object","required":["name","image","position","opacity_percent","scale_percent","margin"],"properties":{"name":{"type":"string","maxLength":80},"image":{"type":"string","format":"binary","description":"JPG\/JPEG, PNG, or WebP image, at most 512 KiB and 4096 by 4096 pixels."},"position":{"type":"string","enum":["top-left","top-center","top-right","center-left","center","center-right","bottom-left","bottom-center","bottom-right"]},"opacity_percent":{"type":"integer","minimum":10,"maximum":100},"scale_percent":{"type":"integer","minimum":5,"maximum":50},"margin":{"type":"integer","minimum":0,"maximum":200}},"example":{"name":"Product logo","image":"@product-logo.png","position":"bottom-right","opacity_percent":80,"scale_percent":20,"margin":24}},"WatermarkUpdateRequest":{"type":"object","required":["name","position","opacity_percent","scale_percent","margin"],"properties":{"name":{"type":"string","maxLength":80},"position":{"type":"string","enum":["top-left","top-center","top-right","center-left","center","center-right","bottom-left","bottom-center","bottom-right"]},"opacity_percent":{"type":"integer","minimum":10,"maximum":100},"scale_percent":{"type":"integer","minimum":5,"maximum":50},"margin":{"type":"integer","minimum":0,"maximum":200}},"description":"The image field is intentionally absent because image replacement is prohibited."},"Watermark":{"type":"object","required":["id","name","position","opacity_percent","scale_percent","margin","preview_url","created_at","updated_at"],"properties":{"id":{"type":"string","description":"Public ULID."},"name":{"type":"string"},"position":{"type":"string","enum":["top-left","top-center","top-right","center-left","center","center-right","bottom-left","bottom-center","bottom-right"]},"opacity_percent":{"type":"integer"},"scale_percent":{"type":"integer"},"margin":{"type":"integer"},"preview_url":{"type":"string","format":"uri","description":"Authenticated binary image endpoint."},"created_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"}},"example":{"id":"01J00000000000000000000002","name":"Product logo","position":"bottom-right","opacity_percent":80,"scale_percent":20,"margin":24,"preview_url":"https:\/\/api.example.com\/v1\/watermarks\/01J00000000000000000000002\/image","created_at":"2026-07-16T12:00:00+00:00","updated_at":"2026-07-16T12:00:00+00:00"}},"TemplateWriteRequest":{"type":"object","required":["name","url"],"properties":{"name":{"type":"string","maxLength":80},"url":{"type":"string","format":"uri","maxLength":2048,"description":"Required public HTTP or HTTPS URL."},"format":{"type":"string","enum":["png","jpeg","webp","avif","pdf"],"default":"png","description":"PDF stores a fixed asynchronous paginated A4 template."},"quality":{"type":"integer","minimum":1,"maximum":100,"description":"JPEG, WebP, and AVIF default to 82; PNG normalizes quality to null. Omit for PDF."},"full_page":{"type":"boolean","default":false},"preset":{"type":"string","enum":["desktop","desktop_hd","laptop","tablet","tablet_landscape","iphone_16","pixel_10","social_card","open_graph"],"default":"desktop"},"viewport":{"$ref":"#\/components\/schemas\/RequestedViewport"},"device_scale_factor":{"type":"number","minimum":1,"maximum":3},"delay_ms":{"type":"integer","minimum":0,"maximum":10000,"default":0},"timeout_ms":{"type":"integer","minimum":1000,"maximum":60000,"default":30000},"wait_until":{"type":"string","enum":["load","domcontentloaded","networkidle0","networkidle2"],"default":"networkidle2"},"wait_for_selector":{"type":["string","null"],"maxLength":500,"default":null},"dark_mode":{"type":"boolean","default":false},"reduced_motion":{"type":"boolean","default":true},"remove_branding":{"type":"boolean","default":false,"description":"Required explicitly for PDF when Capturewell image branding is configured as required."},"watermark_id":{"type":["string","null"],"description":"Owned watermark public ULID. Requires remove_branding=true and the watermark feature. Omit for PDF."},"recipe_id":{"type":["string","null"],"description":"Owned recipe public ULID. Subject to the recipe feature gate."}},"allOf":[{"if":{"required":["format"],"properties":{"format":{"const":"pdf"}}},"then":{"properties":{"quality":false,"full_page":false,"device_scale_factor":false,"watermark_id":false}}}]},"TemplateCaptureOptions":{"type":"object","required":["format","quality","full_page","preset","viewport","delay_ms","timeout_ms","wait_until","wait_for_selector","dark_mode","reduced_motion","remove_branding"],"properties":{"format":{"type":"string","enum":["png","jpeg","webp","avif","pdf"],"description":"PDF templates retain the normalized fixed A4 document contract."},"quality":{"type":["integer","null"],"description":"Null for PNG and PDF."},"full_page":{"type":"boolean","description":"Always true for PDF."},"preset":{"type":"string","enum":["desktop","desktop_hd","laptop","tablet","tablet_landscape","iphone_16","pixel_10","social_card","open_graph"]},"viewport":{"$ref":"#\/components\/schemas\/CaptureViewport"},"delay_ms":{"type":"integer"},"timeout_ms":{"type":"integer"},"wait_until":{"type":"string","enum":["load","domcontentloaded","networkidle0","networkidle2"]},"wait_for_selector":{"type":["string","null"]},"dark_mode":{"type":"boolean"},"reduced_motion":{"type":"boolean"},"remove_branding":{"type":"boolean"},"watermark_id":{"type":"string","description":"Stored public ULID when a custom image watermark is selected. Never present for PDF."}}},"TemplateRecipeSummary":{"type":"object","required":["id","name","deleted"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"deleted":{"type":"boolean"}}},"Template":{"type":"object","required":["id","name","url","capture_options","recipe","latest_capture"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"capture_options":{"$ref":"#\/components\/schemas\/TemplateCaptureOptions"},"recipe":{"oneOf":[{"$ref":"#\/components\/schemas\/TemplateRecipeSummary"},{"type":"null"}]},"latest_capture":{"oneOf":[{"$ref":"#\/components\/schemas\/CaptureHistoryItem"},{"type":"null"}]}},"example":{"id":42,"name":"Homepage desktop","url":"https:\/\/example.com","capture_options":{"format":"png","quality":null,"full_page":true,"preset":"desktop","viewport":{"width":1440,"height":900,"device_scale_factor":1,"mobile":false},"delay_ms":0,"timeout_ms":30000,"wait_until":"networkidle2","wait_for_selector":null,"dark_mode":false,"reduced_motion":true,"remove_branding":false},"recipe":null,"latest_capture":null}},"ScheduleWriteRequest":{"type":"object","required":["template_id","enabled","frequency","timezone"],"properties":{"template_id":{"type":"integer","format":"int64","minimum":1,"description":"Owned template identifier."},"enabled":{"type":"boolean"},"frequency":{"type":"string","enum":["hourly","daily","weekly","monthly"]},"time":{"type":["string","null"],"pattern":"^([01][0-9]|2[0-3]):[0-5][0-9]$","description":"Required for daily, weekly, and monthly schedules. Omit or send null for hourly."},"timezone":{"type":"string","description":"Valid timezone identifier, for example Europe\/London."},"weekday":{"type":["integer","null"],"minimum":1,"maximum":7,"description":"ISO weekday 1 through 7. Required only for weekly schedules."},"month_day":{"type":["integer","null"],"minimum":1,"maximum":28,"description":"Required only for monthly schedules."}},"oneOf":[{"properties":{"frequency":{"const":"hourly"},"time":{"type":"null"},"weekday":{"type":"null"},"month_day":{"type":"null"}}},{"required":["time"],"properties":{"frequency":{"const":"daily"},"time":{"type":"string"},"weekday":{"type":"null"},"month_day":{"type":"null"}}},{"required":["time","weekday"],"properties":{"frequency":{"const":"weekly"},"time":{"type":"string"},"weekday":{"type":"integer"},"month_day":{"type":"null"}}},{"required":["time","month_day"],"properties":{"frequency":{"const":"monthly"},"time":{"type":"string"},"weekday":{"type":"null"},"month_day":{"type":"integer"}}}]},"ScheduleTemplateSummary":{"type":"object","required":["id","name","url"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"url":{"type":"string","format":"uri"}}},"Schedule":{"type":"object","required":["id","enabled","frequency","time","timezone","weekday","month_day","next_run_at","last_run_at","last_error","template","latest_capture"],"properties":{"id":{"type":"integer","format":"int64"},"enabled":{"type":"boolean"},"frequency":{"type":"string","enum":["hourly","daily","weekly","monthly"]},"time":{"type":["string","null"],"pattern":"^([01][0-9]|2[0-3]):[0-5][0-9]$"},"timezone":{"type":"string"},"weekday":{"type":["integer","null"],"minimum":1,"maximum":7},"month_day":{"type":["integer","null"],"minimum":1,"maximum":28},"next_run_at":{"type":["string","null"],"format":"date-time"},"last_run_at":{"type":["string","null"],"format":"date-time"},"last_error":{"type":["string","null"]},"template":{"oneOf":[{"$ref":"#\/components\/schemas\/ScheduleTemplateSummary"},{"type":"null"}]},"latest_capture":{"oneOf":[{"$ref":"#\/components\/schemas\/CaptureHistoryItem"},{"type":"null"}]}},"example":{"id":84,"enabled":true,"frequency":"daily","time":"09:00","timezone":"Europe\/London","weekday":null,"month_day":null,"next_run_at":"2026-07-17T08:00:00+00:00","last_run_at":null,"last_error":null,"template":{"id":42,"name":"Homepage desktop","url":"https:\/\/example.com"},"latest_capture":null}},"PaginatorLink":{"type":"object","required":["url","label","active"],"properties":{"url":{"type":["string","null"],"format":"uri"},"label":{"type":"string"},"active":{"type":"boolean"}}},"PaginatorMetadata":{"type":"object","required":["current_page","first_page_url","from","last_page","last_page_url","links","next_page_url","path","per_page","prev_page_url","to","total"],"properties":{"current_page":{"type":"integer"},"first_page_url":{"type":"string","format":"uri"},"from":{"type":["integer","null"]},"last_page":{"type":"integer"},"last_page_url":{"type":"string","format":"uri"},"links":{"type":"array","items":{"$ref":"#\/components\/schemas\/PaginatorLink"}},"next_page_url":{"type":["string","null"],"format":"uri"},"path":{"type":"string","format":"uri"},"per_page":{"type":"integer","const":20},"prev_page_url":{"type":["string","null"],"format":"uri"},"to":{"type":["integer","null"]},"total":{"type":"integer"}}},"CapturePaginator":{"allOf":[{"$ref":"#\/components\/schemas\/PaginatorMetadata"},{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Capture"}}}}],"example":{"current_page":1,"first_page_url":"https:\/\/api.example.com\/v1\/screenshots?page=1","from":null,"last_page":1,"last_page_url":"https:\/\/api.example.com\/v1\/screenshots?page=1","links":[],"next_page_url":null,"path":"https:\/\/api.example.com\/v1\/screenshots","per_page":20,"prev_page_url":null,"to":null,"total":0,"data":[]}},"RecipePaginator":{"allOf":[{"$ref":"#\/components\/schemas\/PaginatorMetadata"},{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Recipe"}}}}],"example":{"current_page":1,"first_page_url":"https:\/\/api.example.com\/v1\/recipes?page=1","from":null,"last_page":1,"last_page_url":"https:\/\/api.example.com\/v1\/recipes?page=1","links":[],"next_page_url":null,"path":"https:\/\/api.example.com\/v1\/recipes","per_page":20,"prev_page_url":null,"to":null,"total":0,"data":[]}},"WatermarkPaginator":{"allOf":[{"$ref":"#\/components\/schemas\/PaginatorMetadata"},{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Watermark"}}}}],"example":{"current_page":1,"first_page_url":"https:\/\/api.example.com\/v1\/watermarks?page=1","from":null,"last_page":1,"last_page_url":"https:\/\/api.example.com\/v1\/watermarks?page=1","links":[],"next_page_url":null,"path":"https:\/\/api.example.com\/v1\/watermarks","per_page":20,"prev_page_url":null,"to":null,"total":0,"data":[]}},"TemplatePaginator":{"allOf":[{"$ref":"#\/components\/schemas\/PaginatorMetadata"},{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Template"}}}}],"example":{"current_page":1,"first_page_url":"https:\/\/api.example.com\/v1\/templates?page=1","from":null,"last_page":1,"last_page_url":"https:\/\/api.example.com\/v1\/templates?page=1","links":[],"next_page_url":null,"path":"https:\/\/api.example.com\/v1\/templates","per_page":20,"prev_page_url":null,"to":null,"total":0,"data":[]}},"SchedulePaginator":{"allOf":[{"$ref":"#\/components\/schemas\/PaginatorMetadata"},{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Schedule"}}}}],"example":{"current_page":1,"first_page_url":"https:\/\/api.example.com\/v1\/schedules?page=1","from":null,"last_page":1,"last_page_url":"https:\/\/api.example.com\/v1\/schedules?page=1","links":[],"next_page_url":null,"path":"https:\/\/api.example.com\/v1\/schedules","per_page":20,"prev_page_url":null,"to":null,"total":0,"data":[]}}}}}