{"openapi":"3.1.0","info":{"title":"Figma AI Agent Backend","description":"LangGraph-powered Figma AI agent with caching","version":"0.1.0"},"paths":{"/ably/connect":{"post":{"tags":["ably"],"summary":"Connect User","description":"Connect a user to their communication channel.","operationId":"connect_user_ably_connect_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectUserRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectUserResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/ably/refresh-token":{"post":{"tags":["ably"],"summary":"Refresh User Token","description":"Refresh a user's Ably token (JWT authenticated).","operationId":"refresh_user_token_ably_refresh_token_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshTokenResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/ably/newMessage":{"post":{"tags":["ably"],"summary":"Webhook New Message","description":"Handle incoming messages from Ably webhook.","operationId":"webhook_new_message_ably_newMessage_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/ably/directMessage":{"post":{"tags":["ably"],"summary":"Direct Message","description":"Handle direct messages from the plugin, bypassing Ably for large payloads.\nSupports image attachments for vision-based design generation.","operationId":"direct_message_ably_directMessage_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DirectMessageRequest","description":"Direct message request with optional images"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DirectMessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/ably/reply-to-agent":{"post":{"tags":["ably"],"summary":"Reply To Agent","description":"Handle user replies to agent clarification questions (interrupt resume).\n\nWhen the orchestrator calls ask_user(), it pauses and waits.\nThe frontend sends the user's reply here to resume the agent.","operationId":"reply_to_agent_ably_reply_to_agent_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/auth/figma/token":{"post":{"tags":["figma-auth"],"summary":"Exchange Code For Token","description":"Exchange authorization code for access token and get user information.","operationId":"exchange_code_for_token_api_auth_figma_token_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenExchangeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenExchangeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/figma/config":{"get":{"tags":["figma-auth"],"summary":"Get Oauth Config","description":"Get OAuth configuration (client ID only, never expose client secret).","operationId":"get_oauth_config_api_auth_figma_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/auth/google/token":{"post":{"tags":["google-auth"],"summary":"Exchange Code For Token","description":"Exchange authorization code for Google access token and get user information.","operationId":"exchange_code_for_token_api_auth_google_token_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenExchangeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenExchangeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/figma/check-auth-status":{"post":{"tags":["figma-auth-status"],"summary":"Check Auth Status","description":"Check OAuth authentication status. Called by the Figma plugin to poll for completion.","operationId":"check_auth_status_api_auth_figma_check_auth_status_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthStatusRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/history":{"get":{"tags":["chat-history"],"summary":"Get Chat History","description":"Get paginated chat history for the authenticated user.\nReturns the latest messages in chronological order (oldest first).","operationId":"get_chat_history_api_chat_history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-based)","default":1,"title":"Page"},"description":"Page number (1-based)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Number of messages per page","default":50,"title":"Limit"},"description":"Number of messages per page"},{"name":"include_drawable_only","in":"query","required":false,"schema":{"type":"boolean","description":"Return only drawable messages","default":false,"title":"Include Drawable Only"},"description":"Return only drawable messages"},{"name":"conversation_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by specific conversation ID","title":"Conversation Id"},"description":"Filter by specific conversation ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatHistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/history/drawable":{"get":{"tags":["chat-history"],"summary":"Get Drawable Messages","description":"Get drawable messages for the authenticated user.","operationId":"get_drawable_messages_api_chat_history_drawable_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Maximum number of drawable messages","default":20,"title":"Limit"},"description":"Maximum number of drawable messages"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DrawableMessagesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/history/{message_id}":{"get":{"tags":["chat-history"],"summary":"Get Message","description":"Get a specific chat message by ID. Only returns messages that belong to the authenticated user.","operationId":"get_message_api_chat_history__message_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"message_id","in":"path","required":true,"schema":{"type":"integer","title":"Message Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatMessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/messages/{message_id}/design-data":{"get":{"tags":["chat-history"],"summary":"Get Design Data","description":"Fetch the full design data (xml_data, parameters) for a drawable message.\nUsed by the frontend when the Ably payload exceeds the 64KB limit.","operationId":"get_design_data_api_chat_messages__message_id__design_data_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"message_id","in":"path","required":true,"schema":{"type":"integer","title":"Message Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/conversations/":{"post":{"tags":["user-conversations"],"summary":"Create Conversation","description":"Create a new conversation for the authenticated user.","operationId":"create_conversation_api_conversations__post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["user-conversations"],"summary":"Get User Conversations","description":"Get all conversations for the authenticated user.","operationId":"get_user_conversations_api_conversations__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"include_archived","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Archived"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/conversations/{conversation_id}":{"get":{"tags":["user-conversations"],"summary":"Get Conversation Detail","description":"Get detailed conversation with all messages for the authenticated user.","operationId":"get_conversation_detail_api_conversations__conversation_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"integer","title":"Conversation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/email/send":{"post":{"tags":["email"],"summary":"Send Email","description":"Submit a contact form email and store it in the database.","operationId":"send_email_api_email_send_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/payments/create-checkout":{"post":{"tags":["payments"],"summary":"Create Checkout","description":"Create a payment checkout session with the specified payment gateway (Hyperpay, PayPal, or Stripe)","operationId":"create_checkout_api_payments_create_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"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/payments/status/{checkout_id}":{"get":{"tags":["payments"],"summary":"Check Payment Status","description":"Check payment status and activate subscription if successful\nSupports Hyperpay, PayPal and Stripe","operationId":"check_payment_status_api_payments_status__checkout_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"checkout_id","in":"path","required":true,"schema":{"type":"string","title":"Checkout Id"}},{"name":"gateway","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gateway"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/payments/subscription/status":{"get":{"tags":["payments"],"summary":"Get Subscription Status","description":"Get current user's subscription status","operationId":"get_subscription_status_api_payments_subscription_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/payments/subscription/cancel":{"post":{"tags":["payments"],"summary":"Cancel Subscription","description":"Cancel user's subscription (remains active until end of period)\nFor Stripe, returns a URL to the customer portal.","operationId":"cancel_subscription_api_payments_subscription_cancel_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/payments/paypal/execute":{"get":{"tags":["payments"],"summary":"Paypal Execute Payment","description":"Execute PayPal order after user approval (Orders API v2)\nThis endpoint is called by PayPal after user approves payment","operationId":"paypal_execute_payment_api_payments_paypal_execute_get","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/payments/paypal/cancel":{"get":{"tags":["payments"],"summary":"Paypal Cancel Payment","description":"Handle PayPal payment cancellation\nThis endpoint is called when user cancels the payment on PayPal","operationId":"paypal_cancel_payment_api_payments_paypal_cancel_get","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/payments/webhook":{"post":{"tags":["payments"],"summary":"Stripe Webhook","description":"Handle Stripe webhooks for subscription updates","operationId":"stripe_webhook_api_payments_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/reviews/submit":{"post":{"tags":["reviews"],"summary":"Submit Review","description":"Submit a review with rating and optional feedback.\nFor 'max_trials_bonus' type: feedback validated by ChatGPT; valid feedback can award 1 bonus trial.\nFor 'success_drawing' type: feedback stored without validation; no bonus.","operationId":"submit_review_api_reviews_submit_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewSubmitRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewSubmitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/reviews/can-earn-bonus":{"get":{"tags":["reviews"],"summary":"Check Can Earn Bonus","description":"Check if the current user can earn a bonus trial today.","operationId":"check_can_earn_bonus_api_reviews_can_earn_bonus_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CanEarnBonusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/reviews/history":{"get":{"tags":["reviews"],"summary":"Get Review History","description":"Get the current user's review history.","operationId":"get_review_history_api_reviews_history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewHistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/images/resize":{"post":{"tags":["Images"],"summary":"Resize Image","description":"Resize an image from a URL to fit within Figma's size constraints.\nFetches an image from a URL, resizes it if needed, and returns the resized image as a JPEG.","operationId":"resize_image_api_images_resize_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResizeImageRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/html/fetch":{"get":{"tags":["HTML Fetch"],"summary":"Fetch Html","description":"Fetch HTML content from a URL and return it to the client.\nThe client attaches the result as an html_file, bypassing Playwright on the server.","operationId":"fetch_html_api_html_fetch_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string","description":"URL to fetch HTML from","title":"Url"},"description":"URL to fetch HTML from"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/html/screenshot":{"post":{"tags":["HTML Fetch"],"summary":"Take Screenshot","description":"Fetch a URL using the scrapling fallback chain (Fetcher → PlayWrightFetcher →\nStealthyFetcher), render the HTML locally in Playwright, and return a full-page\nscreenshot as a base64-encoded PNG.\n\nReturns {\"screenshot_b64\": str, \"source_url\": str, \"fetcher_used\": str}.\nRaises 400 for invalid URLs, 502 if all fetchers are blocked.","operationId":"take_screenshot_api_html_screenshot_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScreenshotRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/usage/credits":{"get":{"tags":["usage"],"summary":"Get Credits","description":"Get the user's available credit/usage balance.\n\nReturns remaining credit (cost mode) or remaining requests (request_count mode).\nPremium users get unlimited.","operationId":"get_credits_api_usage_credits_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/health":{"get":{"summary":"Health Check","operationId":"health_check_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/users/{user_email}/messages":{"get":{"summary":"Get User Messages","description":"Get all messages for a user (from all their sessions).","operationId":"get_user_messages_users__user_email__messages_get","parameters":[{"name":"user_email","in":"path","required":true,"schema":{"type":"string","title":"User Email"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AuthStatusRequest":{"properties":{"session_id":{"type":"string","title":"Session Id"}},"type":"object","required":["session_id"],"title":"AuthStatusRequest"},"AuthStatusResponse":{"properties":{"status":{"type":"string","title":"Status"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"access_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Access Token"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"jwt_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jwt Token"},"jwt_expires_in":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Jwt Expires In"},"user_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"User Id"}},"type":"object","required":["status"],"title":"AuthStatusResponse"},"CanEarnBonusResponse":{"properties":{"can_earn_bonus":{"type":"boolean","title":"Can Earn Bonus"},"message":{"type":"string","title":"Message"}},"type":"object","required":["can_earn_bonus","message"],"title":"CanEarnBonusResponse","description":"Response for checking if user can earn bonus"},"ChatHistoryResponse":{"properties":{"messages":{"items":{"$ref":"#/components/schemas/ChatMessageResponse"},"type":"array","title":"Messages"},"total_count":{"type":"integer","title":"Total Count"},"page":{"type":"integer","title":"Page"},"limit":{"type":"integer","title":"Limit"},"has_next":{"type":"boolean","title":"Has Next"},"has_previous":{"type":"boolean","title":"Has Previous"},"drawable_count":{"type":"integer","title":"Drawable Count"}},"type":"object","required":["messages","total_count","page","limit","has_next","has_previous","drawable_count"],"title":"ChatHistoryResponse","description":"Chat history response with pagination"},"ChatMessageResponse":{"properties":{"id":{"type":"integer","title":"Id"},"conversation_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Conversation Id"},"role":{"type":"string","title":"Role"},"content":{"type":"string","title":"Content"},"message_type":{"$ref":"#/components/schemas/MessageType"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"is_drawable":{"type":"boolean","title":"Is Drawable"},"command_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Command Type"},"result_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Result Data"}},"type":"object","required":["id","role","content","message_type","created_at","is_drawable"],"title":"ChatMessageResponse","description":"Chat message response model"},"CheckoutRequest":{"properties":{"plan_type":{"type":"string","title":"Plan Type","default":"premium"},"payment_gateway":{"type":"string","title":"Payment Gateway","default":"paypal"}},"type":"object","title":"CheckoutRequest","description":"Request to create a payment checkout"},"CheckoutResponse":{"properties":{"checkout_id":{"type":"string","title":"Checkout Id"},"payment_url":{"type":"string","title":"Payment Url"},"payment_gateway":{"type":"string","title":"Payment Gateway"}},"type":"object","required":["checkout_id","payment_url","payment_gateway"],"title":"CheckoutResponse","description":"Response with checkout ID and payment URL"},"ConnectUserRequest":{"properties":{"user_email":{"type":"string","title":"User Email"}},"type":"object","required":["user_email"],"title":"ConnectUserRequest"},"ConnectUserResponse":{"properties":{"user_email":{"type":"string","title":"User Email"},"channel_name":{"type":"string","title":"Channel Name"},"ably_token":{"type":"string","title":"Ably Token"},"client_id":{"type":"string","title":"Client Id"}},"type":"object","required":["user_email","channel_name","ably_token","client_id"],"title":"ConnectUserResponse"},"ConversationCreate":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"design_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Design Config"}},"type":"object","title":"ConversationCreate"},"ConversationDetailResponse":{"properties":{"id":{"type":"integer","title":"Id"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"design_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Design Config"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"is_active":{"type":"boolean","title":"Is Active"},"messages":{"items":{"$ref":"#/components/schemas/MessageResponse"},"type":"array","title":"Messages"}},"type":"object","required":["id","title","created_at","updated_at","is_active","messages"],"title":"ConversationDetailResponse"},"ConversationListResponse":{"properties":{"conversations":{"items":{"$ref":"#/components/schemas/ConversationResponse"},"type":"array","title":"Conversations"},"total_count":{"type":"integer","title":"Total Count"}},"type":"object","required":["conversations","total_count"],"title":"ConversationListResponse"},"ConversationResponse":{"properties":{"id":{"type":"integer","title":"Id"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"design_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Design Config"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"is_active":{"type":"boolean","title":"Is Active"},"message_count":{"type":"integer","title":"Message Count"},"last_message_preview":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Message Preview"},"last_message_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Message At"}},"type":"object","required":["id","title","created_at","updated_at","is_active","message_count"],"title":"ConversationResponse"},"DirectMessageRequest":{"properties":{"content":{"type":"string","title":"Content","description":"The user's message content"},"xml_data":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Xml Data","description":"XML context from Figma"},"conversation_id":{"type":"integer","title":"Conversation Id","description":"The conversation ID"},"images":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Images","description":"List of attached images with base64 data or URLs"},"html_file":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Html File","description":"Attached HTML file with content, filename, and metadata"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url","description":"URL to fetch and process for design generation"}},"type":"object","required":["content","conversation_id"],"title":"DirectMessageRequest","description":"Request model for direct message API (bypasses Ably for large payloads).","example":{"content":"Create a dashboard based on this mockup","conversation_id":123,"html_file":{"content":"<html>...</html>","filename":"page.html","size":5000,"type":"html"},"images":[{"data":"data:image/png;base64,...","filename":"mockup.png","type":"base64"}],"url":"https://example.com/design","xml_data":"<xml>...</xml>"}},"DirectMessageResponse":{"properties":{"status":{"type":"string","title":"Status"},"message":{"type":"string","title":"Message"},"conversation_id":{"type":"integer","title":"Conversation Id"},"processing_time":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Processing Time"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"}},"type":"object","required":["status","message","conversation_id"],"title":"DirectMessageResponse","description":"Response model for direct message API."},"DrawableMessagesResponse":{"properties":{"messages":{"items":{"$ref":"#/components/schemas/ChatMessageResponse"},"type":"array","title":"Messages"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["messages","count"],"title":"DrawableMessagesResponse","description":"Response for drawable messages only"},"EmailRequest":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name","description":"Sender's name"},"email":{"type":"string","format":"email","title":"Email","description":"Sender's email address"},"subject":{"type":"string","maxLength":200,"minLength":1,"title":"Subject","description":"Email subject"},"message":{"type":"string","maxLength":2000,"minLength":1,"title":"Message","description":"Email message content"}},"type":"object","required":["name","email","subject","message"],"title":"EmailRequest","description":"Request model for email submission"},"EmailResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"message":{"type":"string","title":"Message"},"email_id":{"type":"integer","title":"Email Id"}},"type":"object","required":["success","message","email_id"],"title":"EmailResponse","description":"Response model for email submission"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"MessageResponse":{"properties":{"id":{"type":"integer","title":"Id"},"role":{"type":"string","title":"Role"},"content":{"type":"string","title":"Content"},"message_type":{"$ref":"#/components/schemas/MessageType"},"is_drawable":{"type":"boolean","title":"Is Drawable"},"command_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Command Type"},"result_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Result Data"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","role","content","message_type","is_drawable","created_at"],"title":"MessageResponse"},"MessageType":{"type":"string","enum":["chat","user_request","user_request_with_context","user_request_with_vision","direct_message","agent_response_out","agent_response_out_display","agent_response_out_history","greeting_classification","error_response","tool_response","vision_response"],"title":"MessageType","description":"Enum for message types used in chat message tracking.\n\nEach value represents a specific type of message that can be saved\nto the chat_messages table."},"PaymentStatusResponse":{"properties":{"status":{"type":"string","title":"Status"},"subscription_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subscription Status"},"subscription_end_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subscription End Date"}},"type":"object","required":["status"],"title":"PaymentStatusResponse","description":"Payment status response"},"RefreshTokenResponse":{"properties":{"ably_token":{"type":"string","title":"Ably Token"},"client_id":{"type":"string","title":"Client Id"},"channel_name":{"type":"string","title":"Channel Name"},"user_email":{"type":"string","title":"User Email"}},"type":"object","required":["ably_token","client_id","channel_name","user_email"],"title":"RefreshTokenResponse"},"ResizeImageRequest":{"properties":{"url":{"type":"string","title":"Url","description":"URL of the image to resize"},"max_width":{"type":"integer","title":"Max Width","description":"Maximum width in pixels (default: 2048)","default":2048},"max_height":{"type":"integer","title":"Max Height","description":"Maximum height in pixels (default: 2048)","default":2048},"quality":{"type":"integer","maximum":100.0,"minimum":1.0,"title":"Quality","description":"JPEG quality (1-100, default: 85)","default":85}},"type":"object","required":["url"],"title":"ResizeImageRequest","description":"Request to resize an image"},"ReviewHistoryResponse":{"properties":{"reviews":{"items":{"$ref":"#/components/schemas/ReviewItem"},"type":"array","title":"Reviews"},"total_count":{"type":"integer","title":"Total Count"}},"type":"object","required":["reviews","total_count"],"title":"ReviewHistoryResponse","description":"Response with user's review history"},"ReviewItem":{"properties":{"id":{"type":"integer","title":"Id"},"rating":{"type":"integer","title":"Rating"},"feedback":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Feedback"},"review_type":{"type":"string","title":"Review Type"},"is_valid":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Valid"},"bonus_awarded":{"type":"boolean","title":"Bonus Awarded"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","rating","feedback","review_type","is_valid","bonus_awarded","created_at"],"title":"ReviewItem","description":"A single review item"},"ReviewSubmitRequest":{"properties":{"rating":{"type":"integer","maximum":5.0,"minimum":1.0,"title":"Rating","description":"Rating from 1-5 stars"},"feedback":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Feedback","description":"User's feedback/suggestions"},"review_type":{"type":"string","title":"Review Type","description":"'success_drawing' or 'max_trials_bonus'"}},"type":"object","required":["rating","review_type"],"title":"ReviewSubmitRequest","description":"Request to submit a review"},"ReviewSubmitResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"message":{"type":"string","title":"Message"},"bonus_awarded":{"type":"boolean","title":"Bonus Awarded","default":false},"is_valid":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Valid"},"quality_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Quality Score"},"validation_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Validation Reason"}},"type":"object","required":["success","message"],"title":"ReviewSubmitResponse","description":"Response after submitting a review"},"ScreenshotRequest":{"properties":{"url":{"type":"string","title":"Url"}},"type":"object","required":["url"],"title":"ScreenshotRequest"},"TokenExchangeRequest":{"properties":{"code":{"type":"string","title":"Code"},"redirect_uri":{"type":"string","title":"Redirect Uri"},"session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Id"}},"type":"object","required":["code","redirect_uri"],"title":"TokenExchangeRequest"},"TokenExchangeResponse":{"properties":{"user_email":{"type":"string","title":"User Email"},"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refresh Token"},"expires_in":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Expires In"},"session_stored":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Session Stored","default":false},"jwt_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jwt Token"},"jwt_expires_in":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Jwt Expires In"},"user_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"User Id"}},"type":"object","required":["user_email","access_token"],"title":"TokenExchangeResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}}}