Model swap

Replace model identities in multiple PDPs at once

You will need an API token to send HTTP requests. See Authentication for instructions.

Quick start

Create a project to organize your images. The project_id will be used in subsequent requests. See Creating a project for details.


Upload one or more PDP images to the project. This is a two-step process:

  1. Request a pre-signed upload URL
  2. PUT the image binary to that URL

Collect all file_id values for the next step. See Uploading images for details.


Start a model swap job by providing the identity to swap onto the images and the list of uploaded file IDs. See Starting a job for details.


Poll for notifications to track job progress. Use the id_task parameter with your job ID. See Polling notifications for details.

Uploading identities

Before starting a swap job, you need an identity_code. You can either use an existing identity from your gallery or upload a new one.

import requests

api_url = "https://v2.api.piktid.com"
access_token = "your_access_token"
identity_image_path = "path/to/identity.jpg"

with open(identity_image_path, "rb") as f:
    response = requests.post(
        api_url + "/identity/upload",
        headers={"Authorization": "Bearer " + access_token},
        files={"image": f},
        data={"name": "Model A"},  # Optional custom name
    ).json()

identity_code = response["identity_code"]
print(f"Identity uploaded: {identity_code}")
Response
{
  "identity_code": "id_xyz...",  // IDENTITY_CODE
  "name": "Model A",
  "face_detected": true,
  "success": true,
  // ...
}

You can list existing identities using:

Creating a project

import requests

api_url = "https://v2.api.piktid.com"
access_token = "your_access_token"

response = requests.post(
    api_url + "/project",
    headers={"Authorization": "Bearer " + access_token},
    json={"project_name": "my-campaign"},
).json()
project_id = response["project_id"]
project_name = response["project_name"]
Response
{
  "project_id": "abc123...",   // PROJECT_ID
  "project_name": "my-campaign"
}

Uploading images

You can repeat this process for each image you want to process. All file_id values must be collected to start a job.

import requests

api_url = "https://v2.api.piktid.com"
access_token = "your_access_token"
project_name = "my-campaign"
image_path = "path/to/image.jpg"

# Step 1: Get pre-signed upload URL
response = requests.post(
    api_url + "/upload",
    headers={"Authorization": "Bearer " + access_token},
    json={
        "project_name": project_name,
        "filename": "model-photo-1.jpg",
    },
).json()

upload_url = response["upload_url"]
content_type = response["content_type"]
file_id = response["file_id"]

# Step 2: Upload the image binary
with open(image_path, "rb") as f:
    requests.put(
        upload_url,
        headers={"Content-Type": content_type},
        data=f.read(),
    )

print(f"Uploaded file ID: {file_id}")
Response
{
  "upload_url": "https://s3...",     // Pre-signed PUT URL
  "download_url": "https://...",
  "project_id": "abc123...",
  "project_name": "my-campaign",
  "file_id": "img_001...",           // FILE_ID
  "filename": "model-photo-1.jpg",
  "content_type": "image/jpeg"
}

The upload_url is only valid for a limited time. Upload the image immediately after receiving the response.

Starting a job

import requests

api_url = "https://v2.api.piktid.com"
access_token = "your_access_token"

project_id = "abc123..."
identity_code = "id_xyz..."  # From identity upload or gallery
file_ids = ["img_001...", "img_002...", "img_003..."]

response = requests.post(
    api_url + "/model-swap",
    headers={"Authorization": "Bearer " + access_token},
    json={
        "identity_code": identity_code,
        "project_id": project_id,
        "images": file_ids,
        "post_process": False,  # Optional: enable post-processing
    },
).json()

job_id = response["job_id"]
print(f"Job started: {job_id}")
Response
{
  "job_id": "job_abc123...",  // JOB_ID
  "status": "pending",
  "message": "Job created successfully"
}

Post-processing

Set post_process to true (default) in the job request to enable automatic post-processing of results. The job status will include post_processing_status to track this additional step.

Request with post-processing
{
  "identity_code": "id_xyz...",
  "project_id": "abc123...",
  "images": ["img_001...", "img_002..."],
  "post_process": true
}

Polling notifications

Poll for notifications to track job progress. Use the id_task parameter with your job ID.

import time
import requests

api_url = "https://v2.api.piktid.com"
access_token = "your_access_token"
job_id = "job_abc123..."

# Poll for notifications (recommended: every 3-5 seconds)
for _ in range(120):  # 10 minute timeout
    response = requests.post(
        api_url + "/notifications",
        headers={"Authorization": "Bearer " + access_token},
        json={
            "id_task": job_id,
            "name_list": ["completed", "error"],
        },
    ).json()

    for notification in response:
        print(f"Notification: {notification['name']}")
        print(f"Data: {notification['data']}")
        
        if notification["name"] == "completed":
            print("Job completed!")
            break
        elif notification["name"] == "error":
            print(f"Error: {notification['data']}")
            break
    else:
        time.sleep(5)
        continue
    break
Response
[
  {
    "id": 12345,
    "name": "completed",              // Notification type
    "timestamp": 1702819200.0,
    "data": {                         // Job-specific data
      "job_id": "job_abc123...",
      "status": "completed"
    }
  }
]

Retrieving results

Once the job is complete, retrieve the processed images.

import requests

api_url = "https://v2.api.piktid.com"
access_token = "your_access_token"
job_id = "job_abc123..."

response = requests.get(
    api_url + f"/jobs/{job_id}/results",
    headers={"Authorization": "Bearer " + access_token},
).json()

for result in response["results"]:
    print(f"Image {result['image_index']}: {result['url']}")
Response
{
  "job_id": "job_abc123...",
  "job_type": "model_swap",
  "status": "completed",
  "results": [
    {
      "image_index": 0,
      "url": "https://...",          // Result image URL
      "status": "completed"
    },
    {
      "image_index": 1,
      "url": "https://...",
      "status": "completed"
    }
  ],
  "summary": {
    // Job statistics
  }
}

Bulk download

For bulk downloads, generate a temporary download URL that packages all results into a ZIP file.

import requests

api_url = "https://v2.api.piktid.com"
access_token = "your_access_token"
job_id = "job_abc123..."

# Generate download URL
response = requests.post(
    api_url + "/download",
    headers={"Authorization": "Bearer " + access_token},
    json={"job_id": job_id},
).json()

download_url = response["download_url"]
expires = response["expires"]

print(f"Download URL: {download_url}")
print(f"Expires: {expires}")

# Download the ZIP file (no auth required for the token URL)
zip_response = requests.get(download_url)
with open("results.zip", "wb") as f:
    f.write(zip_response.content)
Response
{
  "download_url": "https://v2.api.piktid.com/download/token123...",
  "expires": "2024-12-17T11:00:00Z"  // URL expiration time
}