Face Swap API Documentation
The Prospolabs FaceSwap API lets you seamlessly swap faces in images using state-of-the-art AI models. Integrate realistic, cartoon, or fast face swaps into your applications with just a few lines of code. All endpoints return JSON and accept base64-encoded images or image URLs.
Authentication
All API requests require a Bearer token in the Authorization header. You can generate API keys from your Dashboard. Keep your keys secret and never expose them in client-side code.
1Authorization: Bearer prsp-your-api-key
Quick Start
Get started with a face swap in under a minute. Choose your preferred language below to see a complete working example.
1curl -X POST https://api.prospolabs.com/v1/swap/realistic \2 -H "Authorization: Bearer prsp-your-api-key" \3 -H "Content-Type: application/json" \4 -d '{5 "source_image": "base64_encoded_source...",6 "target_image": "base64_encoded_target...",7 "output_format": "jpeg",8 "output_quality": 959 }'
Model Endpoints
/v1/swap/realisticRealisticPerform a photorealistic face swap between the source and target images. Produces high-fidelity output suitable for professional use cases.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
source_image | string (base64 or URL) | Yes | Base64-encoded source face image or image URL |
target_image | string (base64 or URL) | Yes | Base64-encoded target image or image URL |
prompt | string | null | No | Optional text prompt to guide the face swap (default: null) |
output_format | "jpeg" | "png" | "webp" | No | Output image format (default: "jpeg") |
output_quality | integer (10–100) | No | Output image quality (default: 95) |
Response
| Field | Type | Required | Description |
|---|---|---|---|
request_id | string | Yes | Unique request identifier (UUID) |
status | "completed" | "failed" | Yes | Inference result status |
model | "realistic" | "cartoon" | "fast" | "cartoon-lite" | Yes | Model used for inference |
result_url | string | null | Yes | Pre-signed URL of the result image (expires after 24 hours by default) |
inference_time | number | null | Yes | Processing time in seconds |
Response Example
1{2 "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",3 "status": "completed",4 "model": "realistic",5 "result_url": "https://storage.example.com/results/a1b2c3d4.jpeg?token=...",6 "inference_time": 2.057}
/v1/swap/cartoonCartoonPerform a cartoon-style face swap, ideal for fun, creative, and social media content. Applies stylized transformations for an animated look.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
source_image | string (base64 or URL) | Yes | Base64-encoded source face image or image URL |
target_image | string (base64 or URL) | Yes | Base64-encoded target image or image URL |
prompt | string | null | No | Optional text prompt to guide the face swap (default: null) |
cartoon_strength | number (0–2) | No | Controls cartoon stylization intensity (default: 0.8) |
output_format | "jpeg" | "png" | "webp" | No | Output image format (default: "jpeg") |
output_quality | integer (10–100) | No | Output image quality (default: 95) |
Response
| Field | Type | Required | Description |
|---|---|---|---|
request_id | string | Yes | Unique request identifier (UUID) |
status | "completed" | "failed" | Yes | Inference result status |
model | "realistic" | "cartoon" | "fast" | "cartoon-lite" | Yes | Model used for inference |
result_url | string | null | Yes | Pre-signed URL of the result image (expires after 24 hours by default) |
inference_time | number | null | Yes | Processing time in seconds |
Response Example
1{2 "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",3 "status": "completed",4 "model": "cartoon",5 "result_url": "https://storage.example.com/results/a1b2c3d4.jpeg?token=...",6 "inference_time": 2.057}
/v1/swap/fastFastFast face swap optimized for speed. Produces quality results in 5-10 seconds with automatic face detection and CodeFormer restoration.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
source_image | string (base64 or URL) | Yes | Base64-encoded source face image or image URL |
target_image | string (base64 or URL) | Yes | Base64-encoded target image or image URL |
input_faces_order | "left-right" | "right-left" | "top-bottom" | "bottom-top" | "small-large" | "large-small" | No | Order used to index detected faces in the target image (default: "left-right") |
target_faces_index | string | No | Comma-separated indices of faces to replace in the target image (default: "0") |
source_faces_index | string | No | Comma-separated indices of faces to use from the source image (default: "0") |
output_format | "jpeg" | "png" | "webp" | No | Output image format (default: "jpeg") |
output_quality | integer (10–100) | No | Output image quality (default: 95) |
Response
| Field | Type | Required | Description |
|---|---|---|---|
request_id | string | Yes | Unique request identifier (UUID) |
status | "completed" | "failed" | Yes | Inference result status |
model | "realistic" | "cartoon" | "fast" | "cartoon-lite" | Yes | Model used for inference |
result_url | string | null | Yes | Pre-signed URL of the result image (expires after 24 hours by default) |
inference_time | number | null | Yes | Processing time in seconds |
Response Example
1{2 "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",3 "status": "completed",4 "model": "fast",5 "result_url": "https://storage.example.com/results/a1b2c3d4.jpeg?token=...",6 "inference_time": 2.057}
/v1/swap/cartoon-liteCartoon LiteComic and illustration-style face swap powered by a ComfyUI diffusion pipeline. Supports optional mask drawing for precise face region control, with adjustable face strength, style strength, and CFG parameters.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
source_image | string (base64 or URL) | Yes | Base64-encoded source face image or image URL |
target_image | string (base64 or URL) | Yes | Base64-encoded target image or image URL |
mask_image | string (base64 or URL) | null | No | Optional mask image defining the face region. If omitted, the pipeline determines the region automatically |
prompt | string | null | No | Optional text prompt to guide the output style (default: "") |
negative_prompt | string | null | No | Negative prompt to suppress unwanted content (default: "") |
face_strength | number (0–2) | No | Controls how strongly the source face identity is applied (default: 0.82) |
style_strength | number (0–2) | No | Controls how strongly the target comic style is preserved (default: 0.9) |
cfg | number (0–10) | No | Classifier-free guidance scale (default: 1.6) |
grow_mask | integer (0–100) | No | Pixels to expand the mask region (default: 0) |
seed | integer | null | No | Seed for reproducibility (default: random) |
steps | integer (1–20) | No | Number of inference steps (default: 8) |
output_format | "jpeg" | "png" | "webp" | No | Output image format (default: "jpeg") |
output_quality | integer (10–100) | No | Output image quality (default: 95) |
Response
| Field | Type | Required | Description |
|---|---|---|---|
request_id | string | Yes | Unique request identifier (UUID) |
status | "completed" | "failed" | Yes | Inference result status |
model | "realistic" | "cartoon" | "fast" | "cartoon-lite" | Yes | Model used for inference |
result_url | string | null | Yes | Pre-signed URL of the result image (expires after 24 hours by default) |
inference_time | number | null | Yes | Processing time in seconds |
Response Example
1{2 "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",3 "status": "completed",4 "model": "cartoon-lite",5 "result_url": "https://storage.example.com/results/a1b2c3d4.jpeg?token=...",6 "inference_time": 2.057}
Sync vs Async API
Use the standard endpoint for synchronous processing, or append /async to the path for asynchronous processing (e.g. /v1/swap/realistic/async).
POST /v1/swap/realisticThe request blocks until processing completes. The response includes the result directly with status completed. Best for interactive applications and playgrounds.
Timeout: 120 seconds max. If processing exceeds this, use async mode.
Response
1{2 "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",3 "status": "completed",4 "model": "realistic",5 "result_url": "https://storage.example.com/results/a1b2c3d4.jpeg?token=...",6 "inference_time": 2.057}
POST /v1/swap/realistic/asyncReturns a request_id immediately with status queued. Poll GET /v1/jobs/{request_id} or use a webhook to receive the result.
Initial Response
1{2 "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",3 "status": "queued",4 "model": "realistic",5 "created_at": "2026-02-19T14:32:15.000Z",6 "poll_url": "https://api.prospolabs.com/v1/jobs/a1b2c3d4-e5f6-7890-abcd-ef1234567890"7}
Polling for Status
1// GET /v1/jobs/{request_id}23// When queued:4{ "request_id": "a1b2c3d4-...", "status": "queued", "model": "realistic" }56// When processing:7{ "request_id": "a1b2c3d4-...", "status": "processing", "model": "realistic" }89// When completed:10{11 "request_id": "a1b2c3d4-...",12 "status": "completed",13 "model": "realistic",14 "result_url": "https://storage.example.com/results/a1b2c3d4.jpeg?token=...",15 "inference_time": 2.0516}1718// When failed:19{20 "request_id": "a1b2c3d4-...",21 "status": "failed",22 "model": "realistic"23}
Alternatively, provide a webhook_url in the request body to receive a callback when the job completes. See the Webhooks section.
Webhooks
Webhooks allow you to receive real-time notifications when events occur in your account. Configure a webhook URL in your dashboard or pass it per-request via the webhook_url field.
Event Types
| Event | Description |
|---|---|
inference.completed | Face swap completed successfully. Includes result_url. |
inference.failed | Face swap processing failed. Includes error details. |
Payload Format
1{2 "event": "inference.completed",3 "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",4 "data": {5 "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",6 "model": "realistic",7 "result_url": "https://storage.example.com/results/a1b2c3d4.jpeg?token=...",8 "processing_time_ms": 20509 },10 "timestamp": "2026-02-19T14:32:27.000Z"11}
Verifying Webhook Signatures
Every webhook includes an X-Prospo-Signature header containing an HMAC-SHA256 signature. Verify it against your webhook secret to ensure the request is authentic.
1import crypto from 'crypto';23function verifyWebhook(payload, signature, secret) {4 const expected = crypto5 .createHmac('sha256', secret)6 .update(payload)7 .digest('hex');8 return crypto.timingSafeEqual(9 Buffer.from(signature),10 Buffer.from(expected)11 );12}1314// In your webhook handler:15app.post('/api/webhook', (req, res) => {16 const signature = req.headers['x-prospo-signature'];17 const isValid = verifyWebhook(18 JSON.stringify(req.body),19 signature,20 process.env.WEBHOOK_SECRET21 );22 if (!isValid) return res.status(401).send('Invalid signature');2324 const { event, data } = req.body;25 if (event === 'inference.completed') {26 console.log('Result ready:', data.result_url);27 }28 res.status(200).send('OK');29});
Retry Policy
If your endpoint returns a non-2xx status code, we'll retry delivery with exponential backoff:
- 1First retry: 30 seconds after initial attempt
- 2Second retry: 2 minutes after first retry
- 3Third retry: 10 minutes after second retry
- 4Final retry: 1 hour after third retry
- 5After 4 failed attempts, the webhook is marked as failed
Rate Limits
The Prospolabs API is built for high-throughput workloads. Monitor your current usage via the response headers X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset.
We support very high request volumes. If you need custom rate limits, dedicated throughput, or SLA guarantees for your use case, reach out and we'll work with you directly.
Contact us for higher limits →Error Handling
The API uses standard HTTP status codes to indicate the outcome of requests. All error responses include a JSON body with a machine-readable code and a human-readable message.
| Status | Name | Description |
|---|---|---|
| 400 | Bad Request | Invalid request body, missing required fields, or unprocessable image |
| 401 | Unauthorized | Missing or invalid API key / Bearer token |
| 403 | Forbidden | Insufficient credits or account suspended |
| 404 | Not Found | Job not found (for polling endpoint) |
| 429 | Too Many Requests | Rate limit exceeded. Check X-RateLimit-* headers |
| 500 | Internal Server Error | Unexpected server error. Your credits are automatically refunded |
| 504 | Gateway Timeout | GPU service unavailable or timed out |
Error Response Example
1{2 "detail": "Insufficient credits. Please top up your balance."3}