# Documentation (/docs) # DrapeItOn docs [#drapeiton-docs] DrapeItOn lets fashion brands and e-commerce platforms run **virtual try-on** in their own product: submit a shopper photo and a garment image, then receive a result image asynchronously. This site covers **how** to integrate and **why** the API is shaped the way it is. Field-level request and response schemas live in the live API reference. | Resource | What it is | | ---------------------------------------------------------------------- | ---------------------------------------------------------- | | **[Quickstart](/docs/getting-started/quickstart)** | End-to-end tutorial: first try-on request to result | | **[Guides](/docs/guides/authentication)** | Task-oriented how-tos (auth, uploads, webhooks, errors, …) | | **[Concepts](/docs/concepts/overview)** | Core ideas: accounts, generations, credits, categories | | **[API Reference](https://api.drapeiton.com/docs)** | Interactive OpenAPI / Scalar | | **[API Reference (Markdown)](https://api.drapeiton.com/reference.md)** | OpenAPI rendered as Markdown for LLMs / non-JS clients | | **[llms.txt](/llms.txt)** | Machine-readable docs index for LLMs | | **[llms-full.txt](/llms-full.txt)** | Full product docs text for LLMs | ## Where to start [#where-to-start] 1. Have an invite-only business account and an API key from the dashboard. 2. Follow the [Quickstart](/docs/getting-started/quickstart). 3. Use the [API Reference](https://api.drapeiton.com/docs) when you need exact request or response fields. Access is **invite-only beta** (no self-serve signup). Request access from the contact address in [Introduction](/docs/getting-started/introduction). # Categories (/docs/concepts/categories) # Categories [#categories] Every generation requires a **category** so the try-on model can treat the garment correctly. ## Allowed values [#allowed-values] | Value | Use for | | ------------ | ------------------------------------------------------ | | `tops` | Shirts, tops, jackets, and similar upper-body garments | | `bottoms` | Pants, skirts, shorts, and similar lower-body garments | | `one-pieces` | Dresses, jumpsuits, and similar full-body garments | These are the only accepted values on `POST /v1/generations`. Other strings fail validation. ## Why it matters [#why-it-matters] Passing the wrong category can degrade visual quality. Choose the category that best matches how the garment is worn on the body, not the product department name alone. ## Related [#related] * [Submitting generations](/docs/guides/submitting-generations) * [API Reference](https://api.drapeiton.com/docs) # Credits (/docs/concepts/credits) # Credits [#credits] **Credits** are the unit of try-on usage on DrapeItOn. ## New accounts [#new-accounts] When a business account is created, it receives **10 credits** to start with. ## Usage [#usage] When `POST /v1/generations` is **accepted**, **one credit** is reserved for that job. * Check remaining balance with `GET /v1/credits` (`balance` and `currency: "credits"`). * If balance is insufficient, the API rejects the request with an insufficient-credits error (see [Errors and retries](/docs/guides/errors-and-retries)). ## Buying more credits [#buying-more-credits] You **cannot** purchase or top up credits from the dashboard yet. During invite-only beta, request additional credits by contacting us at . ## Refunds [#refunds] If a generation **fails terminally**, the credit reserved for that job is **returned** to your balance. Successful jobs consume the reserved credit. ## Related [#related] * [Quickstart](/docs/getting-started/quickstart) * [API Reference — Credits](https://api.drapeiton.com/docs) # Generations (/docs/concepts/generations) # Generations [#generations] A **generation** is one virtual try-on job: person image + garment image + category → result image (or failure). ## Submitting [#submitting] `POST /v1/generations` accepts the job and returns **202** with an `id` and `status: "submitted"`. Work continues asynchronously. Required fields (see [API Reference](https://api.drapeiton.com/docs) for full schema): * `person_image_url` — public URL of the shopper / model photo * `garment_image_url` — public URL of the garment * `category` — `tops`, `bottoms`, or `one-pieces` Optional: `end_user_id`, `seed`, and quality-related parameters documented in the reference. ## Customer-facing statuses [#customer-facing-statuses] When you poll `GET /v1/generations/{id}` or list jobs, `status` is one of: | Status | Meaning for clients | | ------------ | ----------------------------------------------------------------------- | | `submitted` | Accepted; not finished yet | | `queued` | Waiting to run | | `processing` | Actively running (includes internal retry phases collapsed for clients) | | `succeeded` | Finished successfully; use `output_url` | | `failed` | Finished unsuccessfully; see `error` | Do not depend on internal pipeline names. Treat anything other than `succeeded` or `failed` as **in progress** and keep polling or wait for a webhook. ## Delivery of results [#delivery-of-results] 1. **Poll** — `GET /v1/generations/{id}` until terminal status. 2. **Webhook** — receive `generation.completed` or `generation.failed` if configured. How-to: [Handling results](/docs/guides/handling-results), [Webhooks](/docs/guides/webhooks). ## Retries and failures [#retries-and-failures] If a try-on fails transiently, the platform may **retry processing automatically**. The number of processing attempts is environment-specific and is **not** documented as a fixed public limit here. When a job ends in terminal failure, clients see `status: "failed"` (poll) or `generation.failed` (webhook). Credits reserved for that job are returned to your balance. See [Credits](/docs/concepts/credits) and [Errors and retries](/docs/guides/errors-and-retries). ## Listing jobs [#listing-jobs] `GET /v1/generations` returns a paginated history for your account (optional `status` filter). Field-level details: [API Reference](https://api.drapeiton.com/docs). # Overview (/docs/concepts/overview) # Concepts overview [#concepts-overview] This page defines the main ideas you will see across the Integration API and dashboard. Implementation details of hosting and internal systems are omitted on purpose. ## Business account (User) [#business-account-user] A **business account** is your brand or platform’s DrapeItOn account. It owns API keys, credits, webhook configuration, and optional end-user (shopper) limits. Accounts are **invite-only beta**; there is no public self-registration. See [Introduction](/docs/getting-started/introduction) to request access. ## API key [#api-key] An **API key** authenticates Integration API requests. Create keys in the dashboard. The full secret is shown **once** at creation; later you only see a masked form. You may have up to **10** active keys. Send the secret with each Integration API request as `X-API-Key` or `Authorization: Bearer`. Details: [Authentication](/docs/guides/authentication). If an administrator **blocks** the account, programmatic try-on and dashboard access are disabled until unblocked. ## End-user (shopper) [#end-user-shopper] An **end-user** is a shopper on *your* site or app. They do not create a DrapeItOn account. You may pass an optional `end_user_id` on generation requests so the platform can enforce per-shopper cooldown and monthly limits you configure in the dashboard. See [End-user limits](/docs/guides/end-user-limits). ## Generation [#generation] A **generation** (try-on job) takes a person image URL, a garment image URL, and a garment **category**, then produces a result image (or a failure). Jobs are asynchronous: you receive a job id immediately, then poll or wait for a webhook. Statuses and lifecycle: [Generations](/docs/concepts/generations). ## Credit [#credit] A **credit** is the unit of try-on usage. Submitting a generation reserves **one credit**. Balance is available via `GET /v1/credits`. Credits reserved for jobs that fail terminally are returned to your balance. See [Credits](/docs/concepts/credits). ## Webhook [#webhook] A **webhook** is an HTTPS endpoint *you* host. When a generation finishes, DrapeItOn can POST an event (`generation.completed` or `generation.failed`) so you do not have to poll. Configure URLs and secrets in the dashboard. See [Webhooks](/docs/guides/webhooks). ## Integration API vs dashboard [#integration-api-vs-dashboard] | | Integration API | Dashboard | | ----------- | -------------------------------------------------------------- | ----------------------------------- | | Auth | API key | Email / password session | | Typical use | Production try-on traffic | Keys, webhooks, limits, usage views | | Docs | [API Reference](https://api.drapeiton.com/docs) + these guides | Product UI | ## Related [#related] * [Introduction](/docs/getting-started/introduction) — product positioning * [Quickstart](/docs/getting-started/quickstart) — first request # Introduction (/docs/getting-started/introduction) # Introduction [#introduction] DrapeItOn is a **virtual try-on API** for fashion brands and e-commerce platforms. Your shoppers provide a photo; you provide a garment image; the platform returns a try-on result you can show in your storefront, app, or pipeline. ## Who it is for [#who-it-is-for] * Brands and retailers embedding try-on in product pages or fitting flows * Platforms building fashion tooling that needs try-on as a backend capability You integrate with a **server-side API key**. End shoppers do not hold DrapeItOn accounts. ## Integration API vs dashboard [#integration-api-vs-dashboard] | Surface | Purpose | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Integration API** | Programmatic try-on: upload, submit jobs, poll results, balance, webhooks. Authenticated with an **API key**. Documented at [api.drapeiton.com/docs](https://api.drapeiton.com/docs). | | **Dashboard** | Account administration: create API keys, configure webhooks, view usage and credits, set shopper limits. Sign in with email/password. | This documentation site focuses on **integration**. Use the dashboard for key and webhook setup; use the Integration API for production traffic. ## Access [#access] ### After you have an account [#after-you-have-an-account] 1. Sign in to the dashboard. 2. Create an API key (the secret is shown **once**). 3. Continue with the [Quickstart](/docs/getting-started/quickstart). ## Next [#next] * [Quickstart](/docs/getting-started/quickstart) — first try-on, step by step * [Concepts overview](/docs/concepts/overview) — domain vocabulary * [API Reference](https://api.drapeiton.com/docs) — OpenAPI schemas # Quickstart (/docs/getting-started/quickstart) # Quickstart [#quickstart] This tutorial walks through one complete try-on: obtain a public URL for a shopper photo, submit a generation, then fetch the result. **Prerequisites** * An invite-only beta business account (request access via [Introduction](/docs/getting-started/introduction) — no self-serve signup) * An **API key** created in the dashboard (copy the secret when it is shown — it is not shown again) * A person (shopper) image file and a garment image that is already reachable over HTTPS Base URL for the Integration API: ```text https://api.drapeiton.com ``` Replace `YOUR_API_KEY` and file paths below with your own values. *** ## 1. Authenticate [#1-authenticate] Every Integration API request must include your API key, either as: ```http X-API-Key: YOUR_API_KEY ``` or: ```http Authorization: Bearer YOUR_API_KEY ``` The examples use `X-API-Key`. *** ## 2. Get a presigned upload URL (person image) [#2-get-a-presigned-upload-url-person-image] Shopper photos are often not on a public CDN. Request a short-lived upload URL, then `PUT` the image bytes. ```bash curl -sS -X POST "https://api.drapeiton.com/v1/uploads/presigned" \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"content_type":"image/jpeg"}' ``` Example response: ```json { "upload_url": "https://…", "public_url": "https://…" } ``` Upload the file (same `Content-Type` as requested): ```bash curl -sS -X PUT "$UPLOAD_URL" \ -H "Content-Type: image/jpeg" \ --data-binary @./person.jpg ``` Save `public_url` as `PERSON_URL` for the next step. You will pass a **garment** image as a normal HTTPS URL (for example your product CDN). Both `person_image_url` and `garment_image_url` accept any publicly reachable URL; presign is only required when you need the platform to host the bytes. See [Uploading images](/docs/guides/uploading-images). *** ## 3. Submit a generation [#3-submit-a-generation] ```bash curl -sS -X POST "https://api.drapeiton.com/v1/generations" \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "person_image_url": "PERSON_URL", "garment_image_url": "https://cdn.example.com/products/shirt.jpg", "category": "tops" }' ``` Successful submit returns **202** with a job id and initial status: ```json { "id": "job_…", "status": "submitted", "created_at": "…" } ``` One **credit** is reserved when the job is accepted. See [Credits](/docs/concepts/credits). `category` must be one of: `tops`, `bottoms`, `one-pieces`. *** ## 4. Get the result [#4-get-the-result] ### Option A — Poll [#option-a--poll] ```bash curl -sS "https://api.drapeiton.com/v1/generations/JOB_ID" \ -H "X-API-Key: YOUR_API_KEY" ``` Poll until `status` is `succeeded` or `failed`. On success, use `output_url` for the result image. On failure, inspect `error`. Statuses and recommended client behavior: [Handling results](/docs/guides/handling-results). ### Option B — Webhook [#option-b--webhook] If you configured a webhook URL in the dashboard, the platform POSTs `generation.completed` or `generation.failed` when the job finishes. Verify the signature before trusting the body. See [Webhooks](/docs/guides/webhooks) and the [API Reference — Webhooks](https://api.drapeiton.com/docs). *** ## 5. Check balance (optional) [#5-check-balance-optional] ```bash curl -sS "https://api.drapeiton.com/v1/credits" \ -H "X-API-Key: YOUR_API_KEY" ``` *** ## Next steps [#next-steps] * [Authentication](/docs/guides/authentication) * [Webhooks](/docs/guides/webhooks) * [Errors and retries](/docs/guides/errors-and-retries) * [API Reference](https://api.drapeiton.com/docs) # Authentication (/docs/guides/authentication) # Authentication [#authentication] The Integration API authenticates **business accounts** with an **API key**. Do not use dashboard session cookies for try-on traffic. ## Create an API key [#create-an-api-key] 1. Sign in to the dashboard (invite-only account). 2. Open API keys and create a key. 3. Copy the secret **immediately**. It is shown **once**; later list views only show a masked form. 4. You may hold up to **10** active keys. Revoke unused keys in the dashboard. ## Send the key on every request [#send-the-key-on-every-request] Use either header (equivalent): ```http X-API-Key: YOUR_API_KEY ``` ```http Authorization: Bearer YOUR_API_KEY ``` Example: ```bash curl -sS "https://api.drapeiton.com/v1/credits" \ -H "X-API-Key: YOUR_API_KEY" ``` Missing or invalid keys receive an unauthorized error in the [standard error envelope](/docs/guides/errors-and-retries). ## Blocked accounts [#blocked-accounts] If an administrator blocks your account, Integration API try-on and dashboard access are refused until the account is unblocked. ## Security tips [#security-tips] * Store keys only on trusted servers; never ship production keys in mobile or browser apps that end users can extract. * Rotate keys by creating a new key, deploying it, then revoking the old one. * Prefer separate keys for staging and production if you use multiple environments. ## Related [#related] * [Quickstart](/docs/getting-started/quickstart) * [API Reference](https://api.drapeiton.com/docs) # End-user limits (/docs/guides/end-user-limits) # End-user limits [#end-user-limits] Optional controls let you rate-limit **shoppers** (end-users) without creating DrapeItOn accounts for them. ## `end_user_id` [#end_user_id] On `POST /v1/generations`, you may send: ```json "end_user_id": "your-stable-shopper-id" ``` * Optional string, max length **100** * Opaque to DrapeItOn — use your own customer or session id * If omitted, cooldown and monthly limits for shoppers do not apply to that request ## Dashboard settings [#dashboard-settings] In the dashboard (limits / settings), you can configure for your account: | Control | Effect | | ----------------- | ------------------------------------------------------------------------------------ | | **Cooldown** | Minimum seconds between successive try-on **submissions** for the same `end_user_id` | | **Monthly limit** | Maximum try-ons allowed per `end_user_id` per calendar month (or unlimited) | Exact UI labels may vary; values are stored on the business account and enforced on Integration API submit when `end_user_id` is present. ## API errors [#api-errors] | Situation | Code (typical) | | --------------------- | ----------------------------------- | | Cooldown still active | `COOLDOWN_ACTIVE` (HTTP 429) | | Monthly cap reached | `MONTHLY_LIMIT_EXCEEDED` (HTTP 429) | Handle these in your shopper UX (wait / upgrade / block further tries). See [Errors and retries](/docs/guides/errors-and-retries). ## Related [#related] * [Submitting generations](/docs/guides/submitting-generations) * [Concepts overview](/docs/concepts/overview) # Errors and retries (/docs/guides/errors-and-retries) # Errors and retries [#errors-and-retries] ## Error envelope [#error-envelope] Failed Integration API responses use a consistent JSON body: ```json { "error": { "code": "ERROR_CODE", "message": "Human-readable message", "status": 400, "details": [{ "path": "field", "message": "…" }] } } ``` `details` is optional (used for validation issues). Always branch on `error.code` / HTTP status in clients; do not parse free-text `message` as a contract. ## Common codes [#common-codes] | Code | Typical HTTP | When | | ------------------------ | ------------ | ---------------------------------------------- | | `UNAUTHORIZED` | 401 | Missing or invalid API key | | `VALIDATION_ERROR` | 400 | Invalid or parameters failed validation | | `NOT_FOUND` | 404 | Resource missing (e.g. unknown generation id) | | `INSUFFICIENT_CREDITS` | 402 | Not enough credits to accept a generation | | `RATE_LIMIT_EXCEEDED` | 429 | Too many requests for this API key | | `COOLDOWN_ACTIVE` | 429 | Shopper cooldown (when using `end_user_id`) | | `MONTHLY_LIMIT_EXCEEDED` | 429 | Shopper monthly cap (when using `end_user_id`) | | `FORBIDDEN` | 403 | Not allowed (e.g. blocked account contexts) | | `SERVICE_UNAVAILABLE` | 503 | Temporary inability to complete the request | | `INTERNAL_ERROR` | 500 | Unexpected server error | Additional codes may appear; treat unknown codes as generic failures. ## Rate limiting [#rate-limiting] Integration routes are **rate-limited per API key** and split into separate buckets by HTTP method class: * **Read routes** (`GET`, `HEAD`): Sized for polling job status and fetching resources. * **Write routes** (`POST`, `DELETE`, etc.): Separate tighter budget reserved for state-changing operations and GPU generation triggers. Exhausting your budget on read routes will not block write requests, and vice versa. When limited, responses use `RATE_LIMIT_EXCEEDED` (HTTP 429) and include standard rate-limiting headers: * `X-RateLimit-Limit` — Max capacity for the route class * `X-RateLimit-Remaining` — Capacity remaining in the current window * `X-RateLimit-Reset` — Unix timestamp (seconds) when the window resets * `Retry-After` — Exact seconds to wait before retrying Published numeric limits are environment-specific and respect the response headers when present. ## Generation processing [#generation-processing] If try-on processing fails transiently, the platform may **retry the job automatically**. Do not assume a fixed number of processing attempts in client logic unless you have a separate public SLA. When a job ends as failed, poll/webhook surfaces `failed` / `generation.failed`, and reserved credits are returned. See [Credits](/docs/concepts/credits). ## Webhook delivery retries [#webhook-delivery-retries] Outbound webhooks to **your** URL are retried with backoff on network errors and most non-2xx responses. Certain client HTTP statuses stop delivery retries immediately (`400`, `401`, `403`, `404`, `410`, `501`). Details: [Webhooks](/docs/guides/webhooks) and [API Reference — Webhooks](https://api.drapeiton.com/docs). ## Client recommendations [#client-recommendations] 1. Retry idempotent GETs with backoff on `503` / network errors. 2. Do not blindly retry `POST /v1/generations` without your own idempotency strategy — each accept reserves a credit. 3. For webhooks, process idempotently and return 2xx after durable accept. ## Related [#related] * [API Reference](https://api.drapeiton.com/docs) # Handling results (/docs/guides/handling-results) # Handling results [#handling-results] Generations are **asynchronous**. After `POST /v1/generations` returns **202**, wait for a terminal status before showing a result to a shopper. ## Customer-facing statuses [#customer-facing-statuses] | Status | Client action | | ------------ | ------------------------------------------------------------ | | `submitted` | In progress — wait | | `queued` | In progress — wait | | `processing` | In progress — wait | | `succeeded` | Use `output_url` | | `failed` | Read `error.code` / `error.message`; do not use `output_url` | ## Option A — Polling [#option-a--polling] ```bash curl -sS "https://api.drapeiton.com/v1/generations/JOB_ID" \ -H "X-API-Key: YOUR_API_KEY" ``` Poll on an interval appropriate for your UX (for example every few seconds) until `status` is `succeeded` or `failed`. Back off if you poll aggressively; the API is rate-limited per API key (see [Errors and retries](/docs/guides/errors-and-retries)). On success, fields of interest include `output_url`, `category`, and timestamps. On failure, `error` is present. ## Option B — Webhooks [#option-b--webhooks] If a webhook is configured for the account, the platform POSTs when a job finishes: * `generation.completed` — success (`data.status` is `succeeded`, includes `output_url`) * `generation.failed` — failure (`data.status` is `failed`, includes `error`) Verify signatures and return **2xx** quickly. Full payload schemas and delivery behavior: [Webhooks](/docs/guides/webhooks) and [API Reference — Webhooks](https://api.drapeiton.com/docs). ## Combining both [#combining-both] Common pattern: register a webhook for production, and use polling as a fallback (e.g. timeout if no webhook, or for tools/scripts). ## Related [#related] * [Generations concept](/docs/concepts/generations) * [Submitting generations](/docs/guides/submitting-generations) # Submitting generations (/docs/guides/submitting-generations) # Submitting generations [#submitting-generations] ## Create a job [#create-a-job] ```bash curl -sS -X POST "https://api.drapeiton.com/v1/generations" \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "person_image_url": "https://…/person.jpg", "garment_image_url": "https://…/garment.jpg", "category": "tops", "end_user_id": "shopper-optional-id" }' ``` ### Required fields [#required-fields] | Field | Description | | ------------------- | ---------------------------------- | | `person_image_url` | Public URL of the person image | | `garment_image_url` | Public URL of the garment image | | `category` | `tops`, `bottoms`, or `one-pieces` | ### Optional fields [#optional-fields] | Field | Description | | --------------------------------- | --------------------------------------------------------------------- | | `end_user_id` | Your shopper id (string, max 100). Enables cooldown / monthly limits. | | `seed` | Integer seed for reproducibility (range documented in API reference) | | `num_timesteps`, `guidance_scale` | Quality-related parameters (defaults and bounds in API reference) | Full schemas: [API Reference](https://api.drapeiton.com/docs). ### Response [#response] **202 Accepted** with: ```json { "id": "job_…", "status": "submitted", "created_at": "…" } ``` One **credit** is reserved on accept. Continue with [Handling results](/docs/guides/handling-results). ## List jobs [#list-jobs] ```bash curl -sS "https://api.drapeiton.com/v1/generations?limit=20&page=1" \ -H "X-API-Key: YOUR_API_KEY" ``` Optional query: `status` filter using customer-facing statuses (`submitted`, `queued`, `processing`, `succeeded`, `failed`). Pagination fields are documented in the API reference. ## Get one job [#get-one-job] ```bash curl -sS "https://api.drapeiton.com/v1/generations/JOB_ID" \ -H "X-API-Key: YOUR_API_KEY" ``` ## Related [#related] * [Uploading images](/docs/guides/uploading-images) * [Categories](/docs/concepts/categories) * [End-user limits](/docs/guides/end-user-limits) # Uploading images (/docs/guides/uploading-images) # Uploading images [#uploading-images] A generation requires two **publicly reachable** image URLs: | Field | Meaning | | ------------------- | -------------------------- | | `person_image_url` | Shopper / model photograph | | `garment_image_url` | Garment product image | Both are required on `POST /v1/generations` and must be valid URLs. The API does **not** require either URL to come from DrapeItOn hosting. ## Presigned upload (`POST /v1/uploads/presigned`) [#presigned-upload-post-v1uploadspresigned] Use this when you need the platform to host image bytes and give you a stable `public_url`. **Contract (enforced by the API):** 1. `POST /v1/uploads/presigned` with JSON body `{ "content_type": "…" }`. 2. Allowed `content_type` values: `image/png`, `image/jpeg`, `image/jpg`, `image/webp`. 3. Response includes: * `upload_url` — perform an HTTP **PUT** of the raw file bytes here * `public_url` — use this URL later as `person_image_url` or `garment_image_url` 4. The PUT must use the **same** `Content-Type` you requested. There is **no** separate “person” vs “garment” upload endpoint. The same presign + PUT flow produces a public URL you may assign to either generation field. ### Example [#example] ```bash # 1) Request URLs RESP=$(curl -sS -X POST "https://api.drapeiton.com/v1/uploads/presigned" \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"content_type":"image/jpeg"}') UPLOAD_URL=$(echo "$RESP" | jq -r .upload_url) PUBLIC_URL=$(echo "$RESP" | jq -r .public_url) # 2) Upload bytes curl -sS -X PUT "$UPLOAD_URL" \ -H "Content-Type: image/jpeg" \ --data-binary @./person.jpg # 3) Use $PUBLIC_URL as person_image_url (or garment_image_url) on submit ``` ## When to use which source [#when-to-use-which-source] | Situation | Approach | | ----------------------------------------------- | -------------------------------------------------------------- | | Shopper photo only on the device / your backend | Presign → PUT → use `public_url` as `person_image_url` | | Garment already on your product CDN | Pass that HTTPS URL as `garment_image_url` directly | | You want a platform-hosted URL for a garment | Same presign endpoint; use `public_url` as `garment_image_url` | | Both images already public | Skip presign; pass both URLs on submit | ## Limits [#limits] Supported MIME types for **presign** are listed above. Keep images reasonably sized for e-commerce use; use formats the presign endpoint accepts. ## Related [#related] * [Quickstart](/docs/getting-started/quickstart) * [Submitting generations](/docs/guides/submitting-generations) * [API Reference — Uploads](https://api.drapeiton.com/docs) # Webhooks (/docs/guides/webhooks) # Webhooks [#webhooks] Webhooks notify **your** HTTPS endpoint when a generation finishes, so you do not have to poll continuously. ## Setup [#setup] 1. In the dashboard, add a webhook URL (HTTPS recommended). 2. Store the webhook **secret** shown for that endpoint (used for signature verification). 3. Ensure your endpoint accepts `POST` and returns **2xx** after you have accepted the event. Webhook URLs are not configured via the Integration API; use the dashboard. ## Events [#events] | `X-DrapeItOn-Event` / `event_type` | Meaning | | ---------------------------------- | ------------------------ | | `generation.completed` | Try-on succeeded | | `generation.failed` | Try-on failed terminally | Envelope shape (customer body after delivery): * `job_id` * `user_id` * `event_type` * `data` — job snapshot (includes `output_url` on success, `error` on failure) **Exact field schemas** for both events: [API Reference — Webhooks](https://api.drapeiton.com/docs). Prefer that page as the schema source of truth. ## Headers [#headers] | Header | Purpose | | ----------------------- | ------------------------------------------------------------------------- | | `Content-Type` | `application/json` | | `X-DrapeItOn-Event` | Event name | | `X-DrapeItOn-Signature` | `sha256=` HMAC of the **raw request body** using your webhook secret | | `User-Agent` | `DrapeItOn-Webhook/1.0` | ## Verify the signature [#verify-the-signature] Compute HMAC-SHA256 over the **raw body bytes** with your webhook secret, hex-encode the digest, and compare to the value after `sha256=` in `X-DrapeItOn-Signature`. Use a constant-time comparison. Example (Node.js): ```js import { createHmac, timingSafeEqual } from "node:crypto"; function verifyDrapeItOnSignature(rawBody, signatureHeader, secret) { const expected = createHmac("sha256", secret).update(rawBody).digest("hex"); const match = /^sha256=([a-f0-9]+)$/i.exec(signatureHeader || ""); if (!match) return false; const a = Buffer.from(expected, "hex"); const b = Buffer.from(match[1], "hex"); if (a.length !== b.length) return false; return timingSafeEqual(a, b); } ``` Reject requests that fail verification. ## Delivery behavior [#delivery-behavior] * Acknowledge with **HTTP 2xx** as soon as you have safely accepted the event (process heavy work asynchronously if needed). * Failed deliveries are **retried automatically with backoff**. Exact retry counts and timing may change; the [API Reference — Webhooks](https://api.drapeiton.com/docs) description states the current public detail. * Delivery **stops without further retries** if your endpoint responds with one of: **`400`**, **`401`**, **`403`**, **`404`**, **`410`**, **`501`**. * Other non-2xx responses and network failures are treated as retryable until the platform stops retrying. * Deliveries may be **at-least-once** — make handlers idempotent on `job_id` + `event_type`. ## Related [#related] * [Handling results](/docs/guides/handling-results) * [API Reference](https://api.drapeiton.com/docs)