Studio AI

Face crop, bulk QR cards and AI face matching for photo workflows.

Printcart Studio brings the Auto-Headshot engine into the dashboard as pay-per-token services, for both print-on-demand merchants and school / corporate / sports photography studios:

  • Face Crop — detect a face and crop it to an ICP preset, with optional AI sharpening (Real-ESRGAN).
  • Bulk QR — generate a printable PDF of QR cards from a subject roster.
  • AI Face Matching — match a batch of photos to known subjects using face embeddings.

These endpoints live under the /v1/services/studio/* prefix and are billed from your token wallet — the same wallet used by Background Removal and Preflight.

Authentication & billing

All Studio endpoints use account-level JWT auth (the same Bearer token as /account):

text
Authorization: Bearer <access_token>
Content-Type: application/json

Token cost per operation:

ActionToken cost
Face Crop (no enhance)2 tokens / image
Face Crop + sharpen (Real-ESRGAN)6 tokens / image
Bulk QR1 token / subject
AI Face Matching6 tokens / file (failed files are refunded)
Reference embeddings (Matching step 1)free
Job pollingfree

If your wallet balance is too low, the API responds with HTTP 402:

text
{
  "error": "INSUFFICIENT_TOKENS",
  "balance": 4,
  "shortfall": 2,
  "top_up_url": "https://app.printcart.com/payment?tab=buy"
}

Tokens are deducted before the request is forwarded to the engine. If the engine call fails, the tokens are automatically refunded.

Face Crop

Detects a face, crops it to the chosen ICP preset, and (optionally) sharpens it. icp_type ∈ school | corporate | sports | childcare.

From image URL(s) — POST /v1/services/studio/face-crop

FieldTypeRequiredDescription
image_urlstring (URL)one ofSingle source image
image_urlsstring[]one ofMultiple source images
icp_typestringyesschool, corporate, sports, childcare
enhancebooleannotrue to sharpen with Real-ESRGAN (6 tokens/image)
text
curl -X POST https://api.printcart.com/v1/services/studio/face-crop \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "image_urls": ["https://example.com/student.jpg"],
    "icp_type": "school",
    "enhance": false
  }'

Response — `200 OK`

text
{
  "results": [
    {
      "filename": "student.jpg",
      "icp_type": "school",
      "face_box": { "x": 120, "y": 80, "w": 300, "h": 300 },
      "output_urls": {
        "original": "https://.../student_orig.jpg",
        "medium": "https://.../student_md.jpg"
      }
    }
  ],
  "tokens_deducted": 2,
  "wallet_transaction_id": "TX-00021"
}

From file upload — POST /v1/services/studio/face-crop/upload

Multipart form. Send one or more file[] fields plus icp_type and optional enhance. Large batches are processed asynchronously and return 202 with a task_id.

text
curl -X POST https://api.printcart.com/v1/services/studio/face-crop/upload \
  -H "Authorization: Bearer <access_token>" \
  -F "file[][email protected]" \
  -F "file[][email protected]" \
  -F "icp_type=school" \
  -F "enhance=false"

Response (async batch) — `202 Accepted`

text
{ "task_id": "c1a2b3d4-...", "status": "queued", "total_files": 120, "tokens_deducted": 240, "wallet_transaction_id": "TX-00022" }

Poll a batch job — GET /v1/services/studio/jobs/{taskId}

text
{ "status": "running", "progress": { "current": 42, "total": 120, "percentage": 35.0 } }

status: queued → running → completed (with results) | failed.

Bulk QR

Generates a printable PDF of QR cards from a roster and uploads it to storage. layout ∈ 4up (basic) | single | 9up (Premium). Cost: 1 token / subject.

POST /v1/services/studio/qr/generate

FieldTypeRequiredDescription
job_idstringyesYour job reference
school_namestringnoPrinted on the cards
layoutstringno4up (default), single, 9up
logo_urlstring (URL)noCustom logo (Premium)
subjectsarrayyes1–2000 items: { student_id, name, class_name? }
text
curl -X POST https://api.printcart.com/v1/services/studio/qr/generate \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "job_id": "JOB-2026-001",
    "school_name": "Springfield Elementary",
    "layout": "4up",
    "subjects": [
      { "student_id": "STU-001", "name": "An Nguyen", "class_name": "5A" },
      { "student_id": "STU-002", "name": "Binh Tran", "class_name": "5A" }
    ]
  }'

Response — `200 OK`

text
{
  "job_id": "JOB-2026-001",
  "total_subjects": 2,
  "pdf_url": "https://.../qr_cards_JOB-2026-001_4up.pdf",
  "tokens_deducted": 2,
  "wallet_transaction_id": "TX-00023"
}

AI Face Matching

Matches a batch of photos against reference faces. Two steps: build reference embeddings (free), then run a match job (6 tokens/file).

1. Build references — POST /v1/services/studio/matching/references

Creates embeddings for the agency's subjects that have a reference_photo_url. Free of tokens. ≥ 20 subjects runs asynchronously.

text
curl -X POST https://api.printcart.com/v1/services/studio/matching/references \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{ "agency_id": 1 }'
text
{ "status": "completed", "agency_id": 1, "embeddings_created": 12 }

2. Run a match job — POST /v1/services/studio/matching/match-job

Provide job_id or file_ids. Tokens are deducted for every file (6 × total_files); failed files are refunded by the engine.

FieldTypeRequiredDescription
agency_idintegeryesAgency that owns the references
job_idintegerone ofMatch all files in this job
file_idsinteger[]one ofMatch specific files
thresholdnumberno0.50–0.99, default 0.85
text
curl -X POST https://api.printcart.com/v1/services/studio/matching/match-job \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{ "agency_id": 1, "job_id": 10, "threshold": 0.85 }'

Response — `200 OK`

text
{
  "match_job_id": 7,
  "task_id": "def-456",
  "total_files": 120,
  "tokens_deducted": 720,
  "wallet_transaction_id": "TX-00024"
}

3. Job status — GET /v1/services/studio/matching/jobs/{matchJobId}

text
{ "id": 7, "status": "completed", "total_files": 120, "matched": 102, "needs_review": 12, "unmatched": 6 }

Pickers — list & create agencies / jobs (free)

Agencies and jobs are scoped to your account (the gateway passes your Printcart user id). Use these to populate dropdowns and to create entities directly from the dashboard:

MethodPathBody / Returns
GET/v1/services/studio/agencies→ { "agencies": [ { "id": 1, "name": "...", "agency_type": "school" } ] }
POST/v1/services/studio/agencies{ "name": "...", "agency_type": "school|sports|corporate|yearbook|childcare|designer" }
GET/v1/services/studio/agencies/{agencyId}/jobs→ { "jobs": [ { "id": 10, "name": "...", "status": "draft" } ] }
POST/v1/services/studio/agencies/{agencyId}/jobs{ "name": "...", "icp_type": "school|corporate|sports|childcare", "status?": "draft" }

Using it from the dashboard

Try every Studio service without writing code in Dashboard → API Services:

  • Face Crop — upload images or paste URLs, pick an ICP, toggle sharpening, and run.
  • Bulk QR — paste a roster, choose a layout, and download the QR PDF.
  • AI Face Matching — build references for an agency, then run a match job and review results.

Token usage and history appear in Wallet & Billing → Transactions.