Quickstart
First Photta image in under five minutes.
A single account, a single API key, five shell commands. The steps below match exactly what the official Photta docs recommend — no wrappers, no SDKs, no framework assumptions.
In one sentence
Sign up at ai.photta.app, click Generate API key, export it as PHOTTA_API_KEY, POST to /api/v1/tryon/apparel and poll the returned generation ID every 3 seconds until status flips to completed — typically within 1.5 to 4 minutes.
How it works
Five commands from zero to first image
Paste them into a terminal in order. Every snippet is self-contained and uses only curl + jq.
- 01
Step 1
Generate an API key
Sign up at ai.photta.app and open the Developers dashboard. Click Generate API key — live keys start with photta_live_. Export it so the rest of the walkthrough can read it from your shell.
# Sign up at ai.photta.app, open the Developers dashboard, # click "Generate API key" and copy it into your env. export PHOTTA_API_KEY="photta_live_xxxxx" export PHOTTA_BASE_URL="https://ai.photta.app/api/v1" - 02
Step 2
POST your first try-on
Hit /api/v1/tryon/apparel with a product image URL, a mannequin ID and a pose ID. The API answers 202 Accepted immediately and returns a generation ID in data.id.
curl -X POST "$PHOTTA_BASE_URL/tryon/apparel" \ -H "Authorization: Bearer $PHOTTA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "product_type": "dress", "product_images": ["https://example.com/dress.jpg"], "mannequin_id": "mnq_athena_ts", "pose_id": "pose_standing_front", "resolution": "2K", "aspect_ratio": "3:4" }' # Response: 202 Accepted + data.id (generation ID) - 03
Step 3
Poll until it completes
GET /api/v1/tryon/apparel/:id every 3 seconds. Typical completion is 1.5–4 minutes. Put an upper bound on attempts so a stuck job can't hang your script forever.
# Loop every 3 seconds until status flips to "completed". # Typical completion: 1.5–4 minutes. Max 120 attempts = 6 min. for i in $(seq 1 120); do RESULT=$(curl -s "$PHOTTA_BASE_URL/tryon/apparel/$ID" \ -H "Authorization: Bearer $PHOTTA_API_KEY") STATUS=$(echo "$RESULT" | jq -r '.data.status') [ "$STATUS" = "completed" ] && break [ "$STATUS" = "failed" ] && echo "Job failed" && exit 1 sleep 3 done - 04
Step 4
Persist the output
When status flips to completed, data.output_url holds the rendered image. Download the bytes into your own storage so your product doesn't depend on Photta's CDN for rendering.
# Pull the final URL out of the response and save the bytes. OUTPUT_URL=$(echo "$RESULT" | jq -r '.data.output_url') curl -sO "$OUTPUT_URL" echo "Saved $(basename "$OUTPUT_URL")" - 05
Step 5
Handle the failure modes honestly
Branch on the HTTP status code: 402 for insufficient credits, 429 for rate limits (honour Retry-After), 5xx for transient server errors. Every error body carries a machine-readable error.code you can act on.
# Surface the common failure modes honestly. case "$STATUS_CODE" in 402) echo "Out of credits — top up at ai.photta.app" ;; 429) echo "Rate limited — honour Retry-After header" ;; 4??) echo "Client error: $(echo "$BODY" | jq '.error.message')" ;; 5??) echo "Server error — retry with backoff" ;; esac
Questions other developers ask
Questions about getting started
How long does the quickstart take?+
Five minutes for the signup + key generation + first cURL. The generation itself takes 1.5 to 4 minutes, so plan on ten minutes wall-clock before you see your first on-model image.
Do I need a credit card to try it?+
New accounts ship with trial credits you can spend before paying. When you're ready to go to production, subscribe to a plan for a higher monthly credit balance and faster rate limits.
Which endpoint should I try first?+
Apparel try-on (/api/v1/tryon/apparel) — it's the most widely used, the documentation is the most complete, and it covers the async + polling pattern every other Photta endpoint reuses. Once you're comfortable there, jewelry and ghost mannequin work the same way.
Can I run it from the browser?+
No. Your API key must stay server-side — shipping it to a browser leaks it to every visitor. Route calls through a thin proxy on your own backend (Next.js route handler, Express, Flask, Lambda) and let the browser talk to your proxy instead.