WheelStage

API Reference

Process car photos programmatically with the WheelStage API.

Checking...

Authentication

All API requests require a Bearer token. Create an API key from your dashboard. Keys start with ws_.

curl https://wheelstage.com/api/v1/process \
  -H "Authorization: Bearer ws_your_api_key"

Base URL

https://wheelstage.com/api/v1

Endpoints

POST/v1/process

Get a presigned upload URL. Upload your image to this URL via PUT before submitting for processing.

Request body

{}

Response

{
  "uploadUrl": "https://...",
  "objectKey": "uploads/user_id/uuid.jpg",
  "message": "Upload your image to uploadUrl via PUT..."
}
POST/v1/process

Submit an uploaded image for processing. Uses your saved preset settings by default. Costs 1 credit.

Request body

ParameterTypeRequiredDescription
objectKeystringYesThe objectKey returned from the upload step
filenamestringNoOriginal filename for reference
outputFormatstringNo"jpg" (default) or "png"
presetobjectNoOverride preset settings for this job

Preset overrides

ParameterTypeRequiredDescription
preset.bg_template_idstringNoBackground template ID (e.g., "showroom-white-02", "turntable-01")
preset.plate_blurbooleanNoEnable/disable license plate blur
preset.aspect_ratiostringNo"3:2" (default), "1:1", or "16:9"

Response

{
  "jobId": "uuid",
  "status": "queued",
  "creditsRemaining": 4
}
GET/v1/jobs/:id

Check the status of a processing job. Poll this endpoint until status is 'completed' or 'failed'. Signed URLs expire after 1 hour.

Response (queued/processing)

{
  "id": "uuid",
  "status": "processing",
  "error": null,
  "inputUrl": null,
  "outputUrl": null,
  "processingTimeMs": null,
  "createdAt": "2026-09-30T12:00:00Z",
  "completedAt": null
}

Response (completed)

{
  "id": "uuid",
  "status": "completed",
  "error": null,
  "inputUrl": "https://... (signed, 1hr)",
  "outputUrl": "https://... (signed, 1hr)",
  "processingTimeMs": 18500,
  "createdAt": "2026-09-30T12:00:00Z",
  "completedAt": "2026-09-30T12:00:18Z"
}

Full Example

# 1. Get upload URL
RESPONSE=$(curl -s -X POST https://wheelstage.com/api/v1/process \
  -H "Authorization: Bearer ws_your_key" \
  -H "Content-Type: application/json" \
  -d '{}')

UPLOAD_URL=$(echo $RESPONSE | jq -r '.uploadUrl')
OBJECT_KEY=$(echo $RESPONSE | jq -r '.objectKey')

# 2. Upload image
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: image/jpeg" \
  --data-binary @my-car-photo.jpg

# 3. Submit for processing
RESPONSE=$(curl -s -X POST https://wheelstage.com/api/v1/process \
  -H "Authorization: Bearer ws_your_key" \
  -H "Content-Type: application/json" \
  -d "{\"objectKey\": \"$OBJECT_KEY\"}")

JOB_ID=$(echo $RESPONSE | jq -r '.jobId')

# 4. Poll for result
while true; do
  RESULT=$(curl -s https://wheelstage.com/api/v1/jobs/$JOB_ID \
    -H "Authorization: Bearer ws_your_key")
  STATUS=$(echo $RESULT | jq -r '.status')
  echo "Status: $STATUS"
  if [ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ]; then
    echo $RESULT | jq .
    break
  fi
  sleep 3
done

Errors

StatusDescription
401Invalid or missing API key
402Insufficient credits
404Job not found
500Internal server error

Limits

  • Each processed image costs 1 credit
  • Max 3 API keys per account
  • Max upload size: 20 MB
  • Supported formats: JPEG, PNG, WebP, HEIC
  • Processing time: ~15-30 seconds per image
  • Signed output URLs expire after 1 hour

Ready to get started?

Create free account

5 free credits included. No credit card required.