openapi: 3.1.0 info: title: Undress API description: API for undressing images, face swaps, and animations. Premium v3 lives under its own `/api/v3/undress` namespace; everything else is served from `/api/v1/...`. version: 2.0.0 contact: name: DeepStrip url: https://deepstrip.com/ servers: - url: https://deepstrip.com components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: API key description: "Opaque API key issued at /api/documentation. Sent as `Authorization: Bearer `." schemas: UndressRequest: type: object required: - style properties: source_image: type: string description: Base64 encoded source image in jpeg, png, or webp format (max 12 MB). Required unless `parent` is supplied. mask: type: string description: "Base64 encoded mask image in png format (max 1 MB). Contains two colors: white for undressing regions, black for the rest. Only honored when style is `premium_v2` and `automask` is not `true`; ignored for all other styles." automask: type: boolean description: When `true`, the server generates the mask. Only meaningful for `premium_v2`; `standard` and `video` always auto-mask server-side regardless of this field. parent: type: string description: ID of a previous `video` Undress to continue with the next clothing layer. Style and source are inherited; the parent must be less than 24 hours old. style: type: string description: The model for undressing. `premium_v3` is served from a dedicated endpoint (`POST /api/v3/undress`) and is not accepted here. enum: [standard, premium_v2, video] body_shape: type: string description: Body shape adjustment (only for premium_v2 style). enum: ["null", fat, skinny, athletic, old] boobs: type: string description: Breast size adjustment (only for premium_v2 style). enum: ["null", small, large] hair: type: string description: Pubic hair style (only for premium_v2 style). enum: ["null", hairy, shaved] UndressV3Request: type: object required: - image_url - person_id properties: image_url: type: string format: uri description: HTTPS URL of the source image (jpeg, png, or webp, max 12 MB). The same URL the caller submitted to `POST /api/v1/persons/analyze`. person_id: type: string description: Identifier returned by `GET /api/v1/persons/analyze/{id}` for the specific person to undress. Must belong to an analysis of the same `image_url`, owned by the caller, and still within the 3-hour cache window. person_gender: type: string description: Override the detector's gender for this person. Use when the detector misclassifies and you want to force the opposite workflow. Case-insensitive. When omitted, the detector's gender is used. enum: [male, female] PersonsAnalyzeRequest: type: object required: - image_url properties: image_url: type: string format: uri description: HTTPS URL of the image to analyze. The detector service fetches it directly. PersonsAnalyzeResponse: type: object properties: id: type: string description: Identifier for the analysis job. Poll with `GET /api/v1/persons/analyze/{id}`. PersonSchema: type: object properties: id: type: string description: Stable identifier for this person within the analysis result. Pass as `person_id` to `POST /api/v3/undress`. bbox: type: array description: Bounding box in source-image pixel coordinates, `[x1, y1, x2, y2]`. items: type: number minItems: 4 maxItems: 4 age: type: number description: Estimated age. Persons without a recognized age are not returned. gender: type: string description: Detected gender. Persons without a recognized gender are not returned. enum: [male, female] score: type: number description: Detector confidence for the person box. PersonsAnalysisStatusResponse: type: object properties: status: type: string enum: [pending, completed, failed] persons: type: array description: Only present when `status` is `completed`. May be an empty array when the detector finds no recognized persons in the image. items: $ref: "#/components/schemas/PersonSchema" details: type: string description: Failure reason. Only present when `status` is `failed`. enum: [detector_failed] FaceSwapRequest: type: object required: - image - face properties: image: type: string description: Base64 encoded image. face: type: string description: Base64 encoded face image. version: type: string description: Version of the face swap model. enum: [v1, v2] UndressResponse: type: object properties: id: type: string description: Identifier for the job. FaceSwapResponse: type: object properties: id: type: string description: Identifier for the job. ErrorResponse: type: object properties: error: type: string errors: type: array items: type: string UndressResultResponse: type: object properties: status: type: string description: Status of the undress job. enum: [pending, completed, failed] image: type: string description: URL of the generated image, if the job is completed. DEPRECATED — use `result`. result: type: string description: URL of the generated result, if the job is completed. For `video` style this is an mp4 URL; otherwise an image URL. details: type: string description: Failure reason. Only present when `status` is `failed`. enum: [analysis_failed, system_error] FaceSwapResultResponse: type: object properties: status: type: string description: Status of the face swap job. enum: [pending, completed, failed] image: type: string description: URL of the generated image, if the job is completed. FaceSwapVideoAnalyzeRequest: type: object required: - video_url properties: video_url: type: string description: HTTPS URL of the video to analyze. preview: type: boolean description: Whether to create a preview (shorter) version. version: type: string description: Version of the face swap model. enum: [v1, v2] FaceSwapVideoAnalyzeResponse: type: object properties: price: type: number description: Calculated price for the face swap video, in credits. duration: type: integer description: Detected video duration in seconds. FaceSwapVideoRequest: type: object properties: video_url: type: string description: HTTPS URL of the video to process. face_url: type: string description: HTTPS URL of the face image. preview: type: boolean description: Whether to create a preview version. version: type: string description: Version of the face swap model. enum: [v1, v2] FaceSwapVideoResponse: type: object properties: id: type: string description: Identifier for the face swap video job. status: type: string description: Initial status of the job. message: type: string description: Additional information about the job. FaceSwapVideoStatusResponse: type: object properties: id: type: string description: Identifier for the face swap video job. status: type: string description: Status of the face swap video job. enum: [initial, sent, processing, completed, failed] progress: type: number description: Progress percentage of the processing. step: type: string description: Current processing step. enum: [queued, downloading, fps, analysing, working, sound, reencoding_step_1, reencoding_step_2, postprocessing, uploading] result_url: type: string description: URL of the processed video, if completed. error_details: type: object description: Error information if the job failed. created_at: type: string format: date-time description: When the job was created. updated_at: type: string format: date-time description: When the job was last updated. AnimationRequest: type: object properties: source_image: type: string description: Base64 encoded data URI in jpeg, png, or webp format (e.g., data:image/jpeg;base64,/9j/4AAQ...). Required unless `parent_id` is supplied; ignored when `parent_id` is supplied (the parent's last video frame is always used as input). template_id: type: integer description: ID of the animation template to use. Get available templates from /animation_templates endpoint. Combo templates cost 14 credits instead of 7. Optional when `parent_id` is supplied (defaults to the parent's template; pass a different one to switch styles); otherwise required. preset_id: type: integer description: "Deprecated: use template_id instead. ID of the animation template." parent_id: type: string description: ID of a previous Animation to continue. The new clip is concatenated to the parent's video. The parent's last video frame is always used as the source (any `source_image` is ignored). `template_id` is optional and defaults to the parent's template. Parent must be less than 24 hours old and have a saved last frame. undress_before_animation: type: boolean description: "When `true`, the photo is first undressed (Premium v3, 3 credits, charged separately and history-visible) and the animation runs on the undressed result. Only honored for templates whose `undress_before_animation` flag is `true` (see `/api/v1/animation_templates`), and only on a fresh animation (ignored when `parent_id` is supplied). Requires `image_url` + `person_id` instead of `source_image` — see the Persons Analysis API." image_url: type: string format: uri description: "Required when `undress_before_animation` is `true`. HTTPS URL of the source image (jpeg, png, or webp, max 12 MB) — the same URL submitted to `POST /api/v1/persons/analyze`. Replaces `source_image` for the undress-before-animation flow; `source_image` is ignored when `image_url`/`person_id` are present." person_id: type: string description: "Required when `undress_before_animation` is `true`. Identifier of the person to undress, taken from a `completed` `GET /api/v1/persons/analyze/{id}` result owned by the caller and still within the 3-hour cache window. Must belong to an analysis of the same `image_url`." person_gender: type: string description: "Override the detector's gender for the undressed person. Only used in the undress-before-animation flow. Case-insensitive." enum: [male, female] body_shape: type: string description: "Body figure for the undress step (female persons only). Only used in the undress-before-animation flow. `as_in_photo` lets the AI keep what it sees." enum: [as_in_photo, fat, skinny, athletic] boobs: type: string description: "Breast size for the undress step (female persons only). Only used in the undress-before-animation flow. `as_in_photo` lets the AI decide." enum: [as_in_photo, small, large, huge] AnimationResponse: type: object properties: id: type: string description: Identifier for the animation job. AnimationResultResponse: type: object properties: status: type: string description: Status of the animation job. enum: [pending, completed, failed] result: type: string description: URL of the generated video, if the job is completed. error_details: type: object description: Error information when the animation failed due to image analysis. Only present when status is "failed" and the failure was caused by content analysis (child detected or no face found). properties: code: type: string description: Error code indicating the failure reason. enum: [face.child, no_face_found] underage_persons: type: array description: Detected underage persons with age and bounding box coordinates. Only present when code is "face.child". items: type: object properties: age: type: number description: Estimated age of the detected person. face: type: object description: Bounding box coordinates of the detected face. properties: x1: type: integer x2: type: integer y1: type: integer y2: type: integer body: type: object description: Bounding box coordinates of the detected body. properties: x1: type: integer x2: type: integer y1: type: integer y2: type: integer AnimationTemplateListResponse: type: array items: type: object properties: id: type: integer description: Template ID to use with the animation API. name: type: string description: English name of the template. name_de: type: string description: German name (falls back to English if not set). name_es: type: string description: Spanish name (falls back to English if not set). name_pt: type: string description: Portuguese name (falls back to English if not set). name_fr: type: string description: French name (falls back to English if not set). name_ru: type: string description: Russian name (falls back to English if not set). name_zh: type: string description: Chinese name (falls back to English if not set). combo: type: boolean description: Whether this is a combo template (combines two templates). price: type: integer description: Credit cost for this template (7 for standard, 14 for combo). undress_before_animation: type: boolean description: "Whether this template supports the optional \"undress before animation\" step. When `true`, you may pass `undress_before_animation: true` (with `image_url` + `person_id`) to `POST /api/v1/animations`." UndressFaceSwapVideoRequest: type: object required: - undress_id properties: undress_id: type: string description: ID of a completed `video`-style Undress owned by the caller. UndressFaceSwapVideoResponse: type: object properties: id: type: string description: Identifier of the UndressFaceSwapVideo record. face_swap_video_id: type: string description: Identifier of the underlying face swap video job; poll `/face_swap_videos/{id}` for processing status. undress_id: type: string description: Identifier of the source video-style Undress. undress_result_id: type: string nullable: true description: Identifier of the resulting Undress once the face swap completes. `null` while processing. security: - bearerAuth: [] paths: /api/v1/undress: post: summary: Create an undress job operationId: createUndress requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UndressRequest" responses: "201": description: Job created successfully. content: application/json: schema: $ref: "#/components/schemas/UndressResponse" "400": description: Invalid parameters, no credits, expired parent, or too many retries. content: application/json: schema: type: object properties: error: type: string enum: [no_credits, invalid_params, too_many_retries, parent_expired, internal_server_error] errors: type: array description: Validation error messages. Only present when `error` is `invalid_params`. items: type: string /api/v1/persons/analyze: post: summary: Queue a person-detection analysis for an image URL description: "Detects persons on the image at `image_url` and returns an analysis id. Rate limited to 15 requests per minute per API key. Results are cached for 3 hours. Poll `GET /api/v1/persons/analyze/{id}` for the outcome." operationId: createPersonsAnalysis requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PersonsAnalyzeRequest" responses: "201": description: Analysis queued. content: application/json: schema: $ref: "#/components/schemas/PersonsAnalyzeResponse" "400": description: "Invalid parameters (missing `image_url`, non-HTTPS URL, or malformed URL)." content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "429": description: Rate limit exceeded (more than 15 analyses per minute for this API key). content: application/json: schema: type: object properties: error: type: string example: rate_limited retry_after: type: integer description: Seconds until the next minute window, after which new requests will succeed. /api/v1/persons/analyze/{id}: get: summary: Get a persons-analysis result description: "Returns `pending` while the detector is running, `completed` with the persons list when done, or `failed` with a `details` code. A `completed` response with an empty `persons` array means the image had no recognized persons (not a failure). Returns 404 after the 3-hour cache TTL expires or if the id was not created by the caller." operationId: getPersonsAnalysis parameters: - name: id in: path required: true schema: type: string description: Analysis id returned by `POST /api/v1/persons/analyze`. responses: "200": description: Current status of the analysis. content: application/json: schema: $ref: "#/components/schemas/PersonsAnalysisStatusResponse" "404": description: Analysis not found, expired, or not owned by the caller. content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v3/undress: post: summary: Create a premium v3 undress job (explicit person selection) description: "Premium v3 — 5 credits, always auto-masks, always requires an explicit person selected via `POST /api/v1/persons/analyze`. Pass back the exact `image_url` you analyzed plus the `person_id` from the analysis result." operationId: createUndressV3 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UndressV3Request" responses: "201": description: Job created successfully. content: application/json: schema: $ref: "#/components/schemas/UndressResponse" "400": description: "Invalid parameters, invalid/expired/foreign person_id, image URL unreachable, underage subject, or insufficient credits." content: application/json: schema: type: object properties: error: type: string enum: [invalid_params, invalid_person_id, image_fetch_failed, under_age, no_credits] errors: type: array description: Validation error messages. Only present when `error` is `invalid_params`. items: type: string /api/v3/undress/{id}: get: summary: Get the result of a premium v3 undress job operationId: getUndressV3Result parameters: - name: id in: path required: true schema: type: string description: Identifier of the undress job. responses: "200": description: Status or result of the undress job (same shape as `GET /api/v1/undress/{id}`). content: application/json: schema: $ref: "#/components/schemas/UndressResultResponse" "404": description: Job not found. content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v3/undress/{id}/regenerate: post: summary: Regenerate a premium v3 undress for free (once per parent, 24 hours) description: "Creates a new premium v3 undress using the same source image and selected person as the parent, with a different random seed. Completely free — no credits are charged. Exactly one free regeneration is allowed per parent. The parent must be a completed premium v3 undress less than 24 hours old. Poll the returned id via `GET /api/v3/undress/{id}`." operationId: regenerateUndressV3 parameters: - name: id in: path required: true schema: type: string description: Identifier of the parent premium v3 undress. responses: "201": description: Regeneration job created successfully. content: application/json: schema: $ref: "#/components/schemas/UndressResponse" "400": description: Regeneration not available for this parent. content: application/json: schema: type: object properties: error: type: string enum: [already_regenerated, parent_expired, parent_not_completed, not_v3, invalid_params] "404": description: Parent not found, or created by a different API key. content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/face_swap_videos/analyze: post: summary: Analyze a video for face swap processing operationId: analyzeFaceSwapVideo requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/FaceSwapVideoAnalyzeRequest" responses: "200": description: Analysis completed successfully. content: application/json: schema: $ref: "#/components/schemas/FaceSwapVideoAnalyzeResponse" "400": description: Invalid parameters or URL. content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Analysis failed due to video constraints. content: application/json: schema: type: object properties: error: type: string example: "ANALYSIS_FAILED" details: type: string example: "too_large" "500": description: Internal server error. /api/v1/face_swap_videos: post: summary: Create a face swap video job operationId: createFaceSwapVideo requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/FaceSwapVideoRequest" multipart/form-data: schema: $ref: "#/components/schemas/FaceSwapVideoRequest" responses: "201": description: Job created successfully. content: application/json: schema: $ref: "#/components/schemas/FaceSwapVideoResponse" "400": description: Invalid parameters, files, or URLs. content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error. /api/v1/face_swap_videos/{id}: get: summary: Get the status of a face swap video job operationId: getFaceSwapVideoStatus parameters: - name: id in: path required: true schema: type: string description: Identifier of the face swap video job. responses: "200": description: Current status of the face swap video job. content: application/json: schema: $ref: "#/components/schemas/FaceSwapVideoStatusResponse" "404": description: Job not found. content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error. /api/v1/undress/{id}: get: summary: Get the result of an undress job operationId: getUndressResult parameters: - name: id in: path required: true schema: type: string description: Identifier of the undress job. responses: "200": description: Status or result of the undress job. content: application/json: schema: $ref: "#/components/schemas/UndressResultResponse" "404": description: Job not found. content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/undress_face_swap_videos: post: summary: Run a free face swap over a completed video-style undress description: Applies only to completed `video`-style Undresses. Improves face consistency in the animated result; typically completes in 60–120 seconds. Poll `/undress_face_swap_videos/{id}` for status, then fetch the resulting video via `/undress/{undress_result_id}`. operationId: createUndressFaceSwapVideo requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UndressFaceSwapVideoRequest" responses: "201": description: Job created successfully. content: application/json: schema: $ref: "#/components/schemas/UndressFaceSwapVideoResponse" "404": description: Undress not found, not owned by the caller, or not a `video`-style undress. content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Service failed to enqueue the face swap job. content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/undress_face_swap_videos/{id}: get: summary: Get the status of an undress face swap video job operationId: getUndressFaceSwapVideo parameters: - name: id in: path required: true schema: type: string description: Identifier of the UndressFaceSwapVideo record. responses: "200": description: While processing, `undress_result_id` is `null`. Once populated, fetch the swapped result via `/undress/{undress_result_id}`. content: application/json: schema: $ref: "#/components/schemas/UndressFaceSwapVideoResponse" "404": description: Record not found or not owned by the caller. content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/face_swaps: post: summary: Create a face swap job operationId: createFaceSwap requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/FaceSwapRequest" responses: "201": description: Job created successfully. content: application/json: schema: $ref: "#/components/schemas/FaceSwapResponse" "400": description: Invalid parameters or no credits. content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error. /api/v1/face_swaps/{id}: get: summary: Get the result of a face swap job operationId: getFaceSwapResult parameters: - name: id in: path required: true schema: type: string description: Identifier of the face swap job. responses: "200": description: Status or result of the face swap job. content: application/json: schema: $ref: "#/components/schemas/FaceSwapResultResponse" "404": description: Job not found. content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/animations: post: summary: Create an animation job operationId: createAnimation requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/AnimationRequest" responses: "201": description: Job created successfully. content: application/json: schema: $ref: "#/components/schemas/AnimationResponse" "400": description: "Invalid parameters, no credits, expired parent, analysis failed (child detected, no face found), or (undress-before-animation only) invalid person, image fetch failure, or underage subject." content: application/json: schema: type: object properties: error: type: string enum: [invalid_params, no_credits, analysis_failed, parent_expired, internal_server_error, invalid_person_id, image_fetch_failed, under_age] errors: type: array items: type: string error_details: type: object description: Analysis failure details. Only present when error is "analysis_failed". properties: code: type: string enum: [face.child, no_face_found] underage_persons: type: array description: Detected underage persons. Only present when code is "face.child". items: type: object properties: age: type: number face: type: object properties: x1: type: integer x2: type: integer y1: type: integer y2: type: integer body: type: object properties: x1: type: integer x2: type: integer y1: type: integer y2: type: integer /api/v1/animations/{id}: get: summary: Get the result of an animation job operationId: getAnimationResult parameters: - name: id in: path required: true schema: type: string description: Identifier of the animation job. responses: "200": description: Status or result of the animation job. content: application/json: schema: $ref: "#/components/schemas/AnimationResultResponse" "404": description: Job not found. content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/animation_templates: get: summary: List available animation templates operationId: listAnimationTemplates security: [] responses: "200": description: List of available animation templates. content: application/json: schema: $ref: "#/components/schemas/AnimationTemplateListResponse" /api/v1/animation_presets: get: summary: "Deprecated: use /api/v1/animation_templates instead" operationId: listAnimationPresets deprecated: true security: [] responses: "200": description: List of available animation templates (deprecated endpoint). content: application/json: schema: $ref: "#/components/schemas/AnimationTemplateListResponse"