{"openapi":"3.1.0","info":{"title":"Tinify.ai API","description":"AI-powered image optimization API","version":"1.0.0"},"paths":{"/health":{"get":{"tags":["health"],"summary":"Health Check","description":"Health check endpoint for Cloud Run and monitoring.\nReturns 200 OK if the service is healthy.","operationId":"health_check_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness Check","description":"Readiness check for Kubernetes/Cloud Run.\nVerifies that the service can handle requests.","operationId":"readiness_check_readiness_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/upload":{"post":{"tags":["upload"],"summary":"Upload File","description":"Upload a single file to temporary storage (Phase 1 of two-phase upload).\n\nThis endpoint ONLY stores the file - NO processing occurs here.\nUse /auto, /compress, /resize, /upscale, or /tag endpoints to process uploaded files.\n\nReturns:\n    temp_file_id: Use this ID when calling processing endpoints","operationId":"upload_file_upload_post","parameters":[{"name":"x-session-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Guest session token","title":"X-Session-Token"},"description":"Guest session token"},{"name":"x-forwarded-for","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"User IP address","title":"X-Forwarded-For"},"description":"User IP address"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_file_upload_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TempFileResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"options":{"tags":["upload"],"summary":"Upload Options","description":"Handle CORS preflight requests.","operationId":"upload_options_upload_options","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/upload/url":{"post":{"tags":["upload"],"summary":"Upload From Url","description":"Upload an image from a URL to temporary storage (Phase 1 of two-phase upload).\n\nThe backend fetches the image directly from the URL, validates it,\nand stores it in temp storage — same result as POST /upload.","operationId":"upload_from_url_upload_url_post","parameters":[{"name":"x-session-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Guest session token","title":"X-Session-Token"},"description":"Guest session token"},{"name":"x-forwarded-for","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"User IP address","title":"X-Forwarded-For"},"description":"User IP address"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UrlUploadRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TempFileResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auto":{"post":{"tags":["auto"],"summary":"Process Auto","description":"Process previously uploaded temp files with smart routing.\n\nThis is the Phase 2 endpoint for the homepage. It accepts temp_file_ids\nfrom the /upload endpoint and applies processing based on settings.\n\nComponents are automatically determined by settings:\n- Upscale: if output_upscale_factor is set\n- Resize: if output_width or output_height is set\n- Compress: always runs (quality setting)\n- Tag: if output_seo_tag_gen is True","operationId":"process_auto_auto_post","parameters":[{"name":"x-session-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Guest session token","title":"X-Session-Token"},"description":"Guest session token"},{"name":"x-forwarded-for","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"User IP address","title":"X-Forwarded-For"},"description":"User IP address"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessFilesRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessFilesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/status/stream":{"get":{"tags":["status"],"summary":"Stream Batch Status","description":"Stream status updates for multiple jobs via SSE.\n\nStreams individual job updates as they occur.\nConnection closes when all jobs reach terminal states.\n\nQuery params:\n- job_ids: List of job UUIDs to monitor\n\nEvents:\n- `status`: Individual job status update\n- `complete`: Individual job reached terminal state\n- `done`: All jobs completed\n- `error`: Error occurred\n- `timeout`: Connection timeout","operationId":"stream_batch_status_status_stream_get","parameters":[{"name":"job_ids","in":"query","required":true,"schema":{"type":"array","items":{"type":"string","format":"uuid"},"description":"List of job IDs to stream","title":"Job Ids"},"description":"List of job IDs to stream"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"options":{"tags":["status"],"summary":"Status Options","description":"Handle CORS preflight requests.","operationId":"status_options_status_stream_options","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/status/{job_id}/stream":{"get":{"tags":["status"],"summary":"Stream Status","description":"Stream job status updates via Server-Sent Events (SSE).\n\nBenefits over polling:\n- Instant updates when status changes (~10ms vs ~250ms avg polling delay)\n- No wasted requests while waiting\n- Automatic reconnection via SSE retry mechanism\n\nEvents:\n- `status`: Job status update (queued, processing)\n- `complete`: Terminal state reached (completed, failed, expired)\n- `error`: Error occurred\n- `timeout`: Connection timeout (5 min max)\n\nExample client usage:\n```javascript\nconst eventSource = new EventSource('/status/123/stream');\neventSource.addEventListener('status', (e) => console.log(JSON.parse(e.data)));\neventSource.addEventListener('complete', (e) => {\n  console.log(JSON.parse(e.data));\n  eventSource.close();\n});\n```","operationId":"stream_status_status__job_id__stream_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"options":{"tags":["status"],"summary":"Status Options","description":"Handle CORS preflight requests.","operationId":"status_options_status__job_id__stream_options","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/status/{job_id}":{"get":{"tags":["status"],"summary":"Get Status","description":"Get the status of a single job.\n\nReturns:\n- Job status (queued, processing, completed, failed, expired)\n- Position in queue (if queued)\n- Estimated wait time (if queued)\n- Download URL (if completed)\n- Error message (if failed)\n- Processing results (compression ratio, file sizes, metadata)","operationId":"get_status_status__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"options":{"tags":["status"],"summary":"Status Options","description":"Handle CORS preflight requests.","operationId":"status_options_status__job_id__options","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/status":{"get":{"tags":["status"],"summary":"Get Batch Status","description":"Get the status of multiple jobs in a batch.\n\nQuery params:\n- job_ids: Comma-separated list of job UUIDs\n\nReturns list of job statuses.","operationId":"get_batch_status_status_get","parameters":[{"name":"job_ids","in":"query","required":true,"schema":{"type":"array","items":{"type":"string","format":"uuid"},"description":"List of job IDs to check","title":"Job Ids"},"description":"List of job IDs to check"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"options":{"tags":["status"],"summary":"Status Options","description":"Handle CORS preflight requests.","operationId":"status_options_status_options","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/download/{job_id}":{"get":{"tags":["download"],"summary":"Download File","description":"Download a processed image file.\n\n- Verifies job is completed\n- Checks job is not expired\n- Streams file from GCS\n- Sets appropriate headers for download\n- Returns 404 if file not found or expired","operationId":"download_file_download__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"options":{"tags":["download"],"summary":"Download Options","description":"Handle CORS preflight requests.","operationId":"download_options_download__job_id__options","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/download/{job_id}/url":{"get":{"tags":["download"],"summary":"Get Download Url","description":"Get a pre-signed URL for direct download from GCS.\n\nThis is faster than the streaming endpoint because:\n- Client downloads directly from GCS (no API server proxy)\n- Reduces latency by ~50-150ms\n- Reduces API server CPU/bandwidth usage\n\nThe URL is valid for 15 minutes.\n\nReturns:\n- url: Pre-signed GCS URL for direct download\n- filename: Suggested filename for the download\n- content_type: MIME type of the file\n- size: File size in bytes\n- expires_in: URL validity in seconds","operationId":"get_download_url_download__job_id__url_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedUrlResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"options":{"tags":["download"],"summary":"Download Options","description":"Handle CORS preflight requests.","operationId":"download_options_download__job_id__url_options","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/process":{"post":{"tags":["processing"],"summary":"Process Job","description":"Process an image job through the 4-component pipeline.\n\nPipeline order: Upscale → Resize → Compress → Tag\nComponents are determined by settings values (not run_* flags).\n\nArgs:\n    request: Job processing request with job_id, input_path, settings\n    token_claims: Verified OIDC token claims (injected by dependency)\n\nReturns:\n    Dict with processing results","operationId":"process_job_process_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-cloudtasks-taskname","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Cloudtasks-Taskname"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessJobRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"options":{"tags":["processing"],"summary":"Process Options","description":"Handle CORS preflight requests.","operationId":"process_options_process_options","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/compress":{"post":{"tags":["compress"],"summary":"Compress Images","description":"Compress images with optional format conversion.\n\nAccepts temp_file_ids from the /upload endpoint.","operationId":"compress_images_compress_post","parameters":[{"name":"x-session-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Guest session token","title":"X-Session-Token"},"description":"Guest session token"},{"name":"x-forwarded-for","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"User IP address","title":"X-Forwarded-For"},"description":"User IP address"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompressRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessFilesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/resize":{"post":{"tags":["resize"],"summary":"Resize Images","description":"Resize images to specified dimensions.\n\nAccepts temp_file_ids from the /upload endpoint.","operationId":"resize_images_resize_post","parameters":[{"name":"x-session-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Guest session token","title":"X-Session-Token"},"description":"Guest session token"},{"name":"x-forwarded-for","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"User IP address","title":"X-Forwarded-For"},"description":"User IP address"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResizeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessFilesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/upscale":{"post":{"tags":["upscale"],"summary":"Upscale Images","description":"Upscale images using AI (2x or 4x).\n\nAccepts temp_file_ids from the /upload endpoint.","operationId":"upscale_images_upscale_post","parameters":[{"name":"x-session-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Guest session token","title":"X-Session-Token"},"description":"Guest session token"},{"name":"x-forwarded-for","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"User IP address","title":"X-Forwarded-For"},"description":"User IP address"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpscaleRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessFilesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tag":{"post":{"tags":["tag"],"summary":"Tag Images","description":"Generate AI metadata for images (alt text, keywords, filename).\n\nAccepts temp_file_ids from the /upload endpoint.","operationId":"tag_images_tag_post","parameters":[{"name":"x-session-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Guest session token","title":"X-Session-Token"},"description":"Guest session token"},{"name":"x-forwarded-for","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"User IP address","title":"X-Forwarded-For"},"description":"User IP address"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessFilesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/config":{"get":{"tags":["config","config"],"summary":"Get Public Config","description":"Get public configuration values.\n\nReturns tier limits and other non-sensitive config.","operationId":"get_public_config_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/checkout":{"post":{"tags":["billing","billing"],"summary":"Create Checkout","description":"Create a Stripe Checkout session for subscription upgrade.\n\nEnforces single subscription per user:\n- Users with active subscription must use billing portal to change plans\n- Users can only create new checkout if no active subscription exists","operationId":"create_checkout_billing_checkout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/portal":{"post":{"tags":["billing","billing"],"summary":"Create Portal","description":"Create a Stripe Billing Portal session.","operationId":"create_portal_billing_portal_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalResponse"}}}}}}},"/billing/subscription":{"get":{"tags":["billing","billing"],"summary":"Get Subscription","description":"Get current subscription status.","operationId":"get_subscription_billing_subscription_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/webhooks/stripe":{"post":{"tags":["webhooks","webhooks"],"summary":"Stripe Webhook","description":"Handle Stripe webhook events.","operationId":"stripe_webhook_webhooks_stripe_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/usage/history":{"get":{"tags":["usage","usage"],"summary":"Get Usage History","description":"Get processing history for authenticated user.\n\nReturns aggregated daily usage for the past N days.\n\nArgs:\n    days: Number of days to look back (1-90, default 30)\n\nReturns:\n    Aggregated usage data including total jobs, daily breakdown","operationId":"get_usage_history_usage_history_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"default":30,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Usage History Usage History Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/usage/summary":{"get":{"tags":["usage","usage"],"summary":"Get Usage Summary","description":"Get current usage summary (credits remaining, tier info).\n\nReturns:\n    User's current tier, credits, and subscription info","operationId":"get_usage_summary_usage_summary_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Usage Summary Usage Summary Get"}}}}}}},"/internal/cleanup":{"post":{"tags":["cleanup"],"summary":"Cleanup Expired Jobs","description":"Cleanup expired jobs - called by Cloud Scheduler.\n\nThis endpoint:\n1. Fetches all expired jobs from the database\n2. Deletes the associated GCS files (both original and processed)\n3. Removes the job records from the database\n\nReturns:\n    Dict with count of deleted jobs and any errors","operationId":"cleanup_expired_jobs_internal_cleanup_post","parameters":[{"name":"X-CloudScheduler","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Cloudscheduler"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"options":{"tags":["cleanup"],"summary":"Cleanup Options","description":"Handle CORS preflight requests.","operationId":"cleanup_options_internal_cleanup_options","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/internal/refresh-daily-credits":{"post":{"tags":["internal","internal"],"summary":"Refresh Daily Credits","description":"Refresh daily credits for free tier users.\n\nCalled by Cloud Scheduler at midnight UTC.\n\nThis endpoint resets:\n- Guest sessions: credits_remaining = 20, credits_used_today = 0\n- Free tier users: credits_remaining = 50, credits_used_this_period = 0","operationId":"refresh_daily_credits_internal_refresh_daily_credits_post","parameters":[{"name":"X-CloudScheduler","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Cloudscheduler"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mcp/auth/device-code":{"post":{"tags":["mcp-auth","mcp-auth"],"summary":"Device Code Endpoint","description":"Generate a device code for MCP login. No auth required.\nRate limit: 10/hour per IP.","operationId":"device_code_endpoint_mcp_auth_device_code_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/mcp/auth/token":{"get":{"tags":["mcp-auth","mcp-auth"],"summary":"Token Endpoint","description":"Poll for mcp_token approval status. Called by MCP server during login.\nRate limit: 20/minute per device_code.","operationId":"token_endpoint_mcp_auth_token_get","parameters":[{"name":"device_code","in":"query","required":true,"schema":{"type":"string","title":"Device Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mcp/auth/approve":{"post":{"tags":["mcp-auth","mcp-auth"],"summary":"Approve Endpoint","description":"Called by web app when user clicks Approve. Requires authenticated user.\nRate limit: 10/hour per IP.","operationId":"approve_endpoint_mcp_auth_approve_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/mcp/auth/deny":{"post":{"tags":["mcp-auth","mcp-auth"],"summary":"Deny Endpoint","description":"Called by web app when user clicks Deny. Requires authenticated user.","operationId":"deny_endpoint_mcp_auth_deny_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/mcp/auth/revoke":{"post":{"tags":["mcp-auth","mcp-auth"],"summary":"Revoke Endpoint","description":"Revoke an MCP token (logout). Token sent in Authorization header.","operationId":"revoke_endpoint_mcp_auth_revoke_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mcp/auth/status":{"get":{"tags":["mcp-auth","mcp-auth"],"summary":"Status Endpoint","description":"Get account status. Accepts MCP token or session token.","operationId":"status_endpoint_mcp_auth_status_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-session-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Session-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/":{"get":{"summary":"Root","description":"Root endpoint.","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"BatchStatusResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"jobs":{"items":{"$ref":"#/components/schemas/JobResponse"},"type":"array","title":"Jobs"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["success","jobs","total"],"title":"BatchStatusResponse","description":"Batch status response."},"Body_upload_file_upload_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File","description":"Image file to upload"}},"type":"object","required":["file"],"title":"Body_upload_file_upload_post"},"CheckoutRequest":{"properties":{"price_id":{"type":"string","title":"Price Id"},"success_url":{"type":"string","title":"Success Url"},"cancel_url":{"type":"string","title":"Cancel Url"}},"type":"object","required":["price_id","success_url","cancel_url"],"title":"CheckoutRequest"},"CheckoutResponse":{"properties":{"checkout_url":{"type":"string","title":"Checkout Url"},"session_id":{"type":"string","title":"Session Id"}},"type":"object","required":["checkout_url","session_id"],"title":"CheckoutResponse"},"CompressRequest":{"properties":{"temp_file_ids":{"items":{"type":"string"},"type":"array","title":"Temp File Ids"},"settings":{"anyOf":[{"$ref":"#/components/schemas/ProcessingSettings"},{"type":"null"}]},"output_format":{"type":"string","title":"Output Format","default":"original"},"quality":{"type":"integer","maximum":100.0,"minimum":1.0,"title":"Quality","default":80},"target_file_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Target File Size"}},"type":"object","required":["temp_file_ids"],"title":"CompressRequest","description":"Request model for compress endpoint with temp_file_ids."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"JobResponse":{"properties":{"id":{"type":"string","format":"uuid4","title":"Id"},"status":{"$ref":"#/components/schemas/JobStatus"},"original_filename":{"type":"string","title":"Original Filename"},"original_size":{"type":"integer","title":"Original Size"},"original_format":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Original Format"},"original_mime_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Original Mime Type"},"original_width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Original Width"},"original_height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Original Height"},"original_dpi":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Original Dpi"},"original_file_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Original File Path"},"output_format":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Output Format"},"output_upscale_factor":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Output Upscale Factor"},"output_width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Output Width"},"output_height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Output Height"},"output_resize_behavior":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Output Resize Behavior"},"output_quality":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Output Quality"},"output_file_size_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Output File Size Limit"},"output_seo_tag_gen":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Output Seo Tag Gen"},"output_seo_rename":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Output Seo Rename"},"executed_upscale":{"type":"boolean","title":"Executed Upscale","default":false},"executed_resize":{"type":"boolean","title":"Executed Resize","default":false},"executed_compress":{"type":"boolean","title":"Executed Compress","default":false},"executed_tag":{"type":"boolean","title":"Executed Tag","default":false},"processed_file_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Processed File Path"},"processed_filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Processed Filename"},"processed_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Processed Size"},"processed_format":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Processed Format"},"processed_width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Processed Width"},"processed_height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Processed Height"},"processed_compression_ratio":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Processed Compression Ratio"},"seo_alt_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Seo Alt Text"},"seo_filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Seo Filename"},"seo_keywords":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Seo Keywords"},"job_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Source"},"job_entry_point":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Entry Point"},"processing_time_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Processing Time Ms"},"credits_used":{"type":"integer","title":"Credits Used","default":0},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Started At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"}},"type":"object","required":["id","status","original_filename","original_size","created_at","expires_at"],"title":"JobResponse","description":"Job response model matching database schema."},"JobStatus":{"type":"string","enum":["queued","processing","completed","failed","expired"],"title":"JobStatus","description":"Job status enum."},"OutputFormat":{"type":"string","enum":["original","jpg","png","webp","avif","gif","svg","ico"],"title":"OutputFormat","description":"Output format enum."},"PortalResponse":{"properties":{"portal_url":{"type":"string","title":"Portal Url"}},"type":"object","required":["portal_url"],"title":"PortalResponse"},"ProcessFilesRequest":{"properties":{"temp_file_ids":{"items":{"type":"string"},"type":"array","title":"Temp File Ids"},"settings":{"$ref":"#/components/schemas/ProcessingSettings"}},"type":"object","required":["temp_file_ids"],"title":"ProcessFilesRequest","description":"Request to process previously uploaded temp files."},"ProcessFilesResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"jobs":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Jobs"},"credits_used":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credits Used"},"credits_remaining":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credits Remaining"}},"type":"object","required":["success","jobs"],"title":"ProcessFilesResponse","description":"Response for batch file processing."},"ProcessJobRequest":{"properties":{"job_id":{"type":"string","title":"Job Id"},"input_path":{"type":"string","title":"Input Path"},"settings":{"$ref":"#/components/schemas/ProcessingSettings"}},"type":"object","required":["job_id","input_path","settings"],"title":"ProcessJobRequest","description":"Request model for job processing."},"ProcessingSettings":{"properties":{"output_format":{"$ref":"#/components/schemas/OutputFormat","description":"Output format","default":"original"},"output_upscale_factor":{"anyOf":[{"type":"number","maximum":10.0,"minimum":0.1},{"type":"null"}],"title":"Output Upscale Factor","description":"Upscale factor (e.g., 2.0, 4.0)"},"output_width":{"anyOf":[{"type":"integer","maximum":8192.0,"minimum":1.0},{"type":"null"}],"title":"Output Width","description":"Target width in pixels"},"output_height":{"anyOf":[{"type":"integer","maximum":8192.0,"minimum":1.0},{"type":"null"}],"title":"Output Height","description":"Target height in pixels"},"output_resize_behavior":{"$ref":"#/components/schemas/ResizeBehavior","description":"How to handle aspect ratio mismatch: pad (default) or crop","default":"pad"},"output_quality":{"type":"integer","maximum":100.0,"minimum":1.0,"title":"Output Quality","description":"Compression quality 1-100","default":80},"output_file_size_limit":{"anyOf":[{"type":"integer","exclusiveMinimum":0.0},{"type":"null"}],"title":"Output File Size Limit","description":"Target max file size in bytes"},"output_seo_tag_gen":{"type":"boolean","title":"Output Seo Tag Gen","description":"Generate SEO metadata (alt text, keywords)","default":false},"output_seo_rename":{"type":"boolean","title":"Output Seo Rename","description":"Rename file with SEO-friendly name","default":false},"gif_frame_limit":{"anyOf":[{"type":"integer","maximum":100.0,"minimum":1.0},{"type":"null"}],"title":"Gif Frame Limit","description":"Max frames to process for animated GIFs (1-100). None means process all frames."}},"type":"object","title":"ProcessingSettings","description":"User's desired output settings for image processing.\n\nNote: No activation booleans (run_*) - components are determined by:\n- Upscale: if output_upscale_factor is set\n- Resize: if output_width or output_height is set\n- Compress: always runs (quality setting)\n- Tag: if output_seo_tag_gen is True"},"ResizeBehavior":{"type":"string","enum":["pad","crop"],"title":"ResizeBehavior","description":"How to handle aspect ratio mismatch when both width and height are specified."},"ResizeRequest":{"properties":{"temp_file_ids":{"items":{"type":"string"},"type":"array","title":"Temp File Ids"},"settings":{"anyOf":[{"$ref":"#/components/schemas/ProcessingSettings"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","maximum":8192.0,"minimum":1.0},{"type":"null"}],"title":"Width"},"height":{"anyOf":[{"type":"integer","maximum":8192.0,"minimum":1.0},{"type":"null"}],"title":"Height"},"resize_behavior":{"type":"string","title":"Resize Behavior","default":"pad"},"output_format":{"type":"string","title":"Output Format","default":"original"}},"type":"object","required":["temp_file_ids"],"title":"ResizeRequest","description":"Request model for resize endpoint with temp_file_ids."},"SignedUrlResponse":{"properties":{"url":{"type":"string","title":"Url"},"filename":{"type":"string","title":"Filename"},"content_type":{"type":"string","title":"Content Type"},"size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size"},"expires_in":{"type":"integer","title":"Expires In"}},"type":"object","required":["url","filename","content_type","expires_in"],"title":"SignedUrlResponse","description":"Response for signed URL endpoint."},"StatusResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"job":{"$ref":"#/components/schemas/JobResponse"}},"type":"object","required":["success","job"],"title":"StatusResponse","description":"Status check response."},"TagRequest":{"properties":{"temp_file_ids":{"items":{"type":"string"},"type":"array","title":"Temp File Ids"},"settings":{"anyOf":[{"$ref":"#/components/schemas/ProcessingSettings"},{"type":"null"}]},"rename_file":{"type":"boolean","title":"Rename File","default":false},"output_format":{"type":"string","title":"Output Format","default":"original"}},"type":"object","required":["temp_file_ids"],"title":"TagRequest","description":"Request model for tag endpoint with temp_file_ids."},"TempFileResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"temp_file_id":{"type":"string","title":"Temp File Id"},"original_filename":{"type":"string","title":"Original Filename"},"file_size":{"type":"integer","title":"File Size"},"mime_type":{"type":"string","title":"Mime Type"},"temp_path":{"type":"string","title":"Temp Path"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"session_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Token"},"gif_frame_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Gif Frame Count"},"gif_fps":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Gif Fps"}},"type":"object","required":["success","temp_file_id","original_filename","file_size","mime_type","temp_path","expires_at"],"title":"TempFileResponse","description":"Response for temp file upload (Phase 1 of two-phase upload)."},"UpscaleRequest":{"properties":{"temp_file_ids":{"items":{"type":"string"},"type":"array","title":"Temp File Ids"},"settings":{"anyOf":[{"$ref":"#/components/schemas/ProcessingSettings"},{"type":"null"}]},"factor":{"type":"number","maximum":4.0,"minimum":1.0,"title":"Factor","default":2.0},"output_format":{"type":"string","title":"Output Format","default":"original"}},"type":"object","required":["temp_file_ids"],"title":"UpscaleRequest","description":"Request model for upscale endpoint with temp_file_ids."},"UrlUploadRequest":{"properties":{"url":{"type":"string","title":"Url"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename"}},"type":"object","required":["url"],"title":"UrlUploadRequest","description":"Request body for URL-based upload."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}