{"openapi":"3.1.0","info":{"title":"CTGT API","version":"1.0.0"},"paths":{"/v1/auth/signup":{"post":{"summary":"Signup","operationId":"signup_v1_auth_signup_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/verify":{"get":{"summary":"Verify Email","description":"Verify user email with token and display API key in formatted HTML page","operationId":"verify_email_v1_auth_verify_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"}}}}}}},"/v1/auth/regenerate-api-key":{"post":{"summary":"Regenerate Api Key","description":"Regenerate API key for authenticated user (JWT protected).\n\nSECURITY:\n- Old key is immediately invalidated\n- New key is returned once (user must save it)\n- Rate limited to prevent abuse (1 per 2 hours)\n- All user state is preserved (rate limits, subscription, billing)\n- Uses frontend JWT authentication (not API key)\n\nThis is safe because all restrictions are tied to user_id, not the API key.","operationId":"regenerate_api_key_v1_auth_regenerate_api_key_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/chat/completions":{"post":{"summary":"Chat Completions","operationId":"chat_completions_v1_chat_completions_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionRequest"}}},"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":[]}]}},"/metrics":{"get":{"summary":"Metrics","operationId":"metrics_metrics_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health":{"get":{"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/subscription/info":{"get":{"summary":"Get Subscription Info","description":"Get user's subscription tier and available models (JWT protected)","operationId":"get_subscription_info_v1_subscription_info_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/subscription/upgrade":{"post":{"summary":"Upgrade Subscription","description":"Self-service upgrade to paid tier (pay-as-you-go)\n\nIf user already has payment method on file (from previous paid subscription),\nupgrades immediately without re-entering card details.\n\nIf no payment method exists, creates Stripe Checkout Session to collect it.\nNo upfront charge - users are billed monthly for actual token usage.","operationId":"upgrade_subscription_v1_subscription_upgrade_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/subscription/confirm-upgrade":{"post":{"summary":"Confirm Upgrade","description":"Confirm upgrade after payment method is added via Setup Intent\n\nThis endpoint is called after the user successfully adds their payment method.\nIt verifies the payment method is attached and upgrades the user to paid tier.","operationId":"confirm_upgrade_v1_subscription_confirm_upgrade_post","parameters":[{"name":"setup_intent_id","in":"query","required":true,"schema":{"type":"string","title":"Setup Intent Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/subscription/upgrade-success":{"get":{"summary":"Upgrade Success","description":"Handle successful Checkout Session completion\n\nWhen user completes payment form, Stripe redirects here with session_id.\nWe retrieve the session, get the payment method, set it as default, and upgrade the user.","operationId":"upgrade_success_v1_subscription_upgrade_success_get","parameters":[{"name":"session_id","in":"query","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/subscription/upgrade-cancel":{"get":{"summary":"Upgrade Cancel","description":"Handle checkout cancellation\n\nWhen user cancels the checkout, Stripe redirects here.","operationId":"upgrade_cancel_v1_subscription_upgrade_cancel_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/subscription/update-payment-method":{"post":{"summary":"Update Payment Method","description":"Update payment method for existing paid tier user\n\nCreates a new Setup Intent to collect updated payment information.\nUseful when card expires, payment fails, or user wants to change cards.","operationId":"update_payment_method_v1_subscription_update_payment_method_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/subscription/confirm-payment-update":{"post":{"summary":"Confirm Payment Update","description":"Confirm payment method update after new card is added via Setup Intent\n\nSets the new payment method as default for future invoices.","operationId":"confirm_payment_update_v1_subscription_confirm_payment_update_post","parameters":[{"name":"setup_intent_id","in":"query","required":true,"schema":{"type":"string","title":"Setup Intent Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/subscription/downgrade":{"post":{"summary":"Downgrade Subscription","description":"Downgrade user to free tier and cancel Stripe subscription","operationId":"downgrade_subscription_v1_subscription_downgrade_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/webhooks/stripe":{"post":{"summary":"Stripe Webhook","description":"Handle Stripe webhook events for automatic tier management\n\nAutomatically upgrades/downgrades users when:\n- Checkout session completes (upgrade to paid)\n- Subscription is created (upgrade to paid)\n- Subscription is cancelled (downgrade to free)\n- Payment fails (downgrade to free)","operationId":"stripe_webhook_v1_webhooks_stripe_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/billing/usage":{"get":{"summary":"Get Usage","description":"Get current month's token usage and costs","operationId":"get_usage_v1_billing_usage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/billing/generate-invoice":{"post":{"summary":"Generate Invoice","description":"Manually generate and send invoice for current month","operationId":"generate_invoice_v1_billing_generate_invoice_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/billing/history":{"get":{"summary":"Get Billing History","description":"Get billing history for a specific period (JWT protected)","operationId":"get_billing_history_v1_billing_history_get","parameters":[{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Date"}},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Date"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"ChatCompletionRequest":{"properties":{"model":{"type":"string","maxLength":50,"title":"Model"},"messages":{"items":{"$ref":"#/components/schemas/ChatMessage"},"type":"array","maxItems":100,"title":"Messages"},"temperature":{"anyOf":[{"type":"number","maximum":2.0,"minimum":0.0},{"type":"null"}],"title":"Temperature","default":1.0},"max_tokens":{"anyOf":[{"type":"integer","maximum":8192.0,"minimum":1.0},{"type":"null"}],"title":"Max Tokens"},"top_p":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Top P","default":1.0},"n":{"anyOf":[{"type":"integer","maximum":5.0,"minimum":1.0},{"type":"null"}],"title":"N","default":1},"stream":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Stream","default":false},"stop":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":4},{"type":"null"}],"title":"Stop"},"presence_penalty":{"anyOf":[{"type":"number","maximum":2.0,"minimum":-2.0},{"type":"null"}],"title":"Presence Penalty","default":0},"frequency_penalty":{"anyOf":[{"type":"number","maximum":2.0,"minimum":-2.0},{"type":"null"}],"title":"Frequency Penalty","default":0},"logit_bias":{"anyOf":[{"additionalProperties":{"type":"number"},"type":"object"},{"type":"null"}],"title":"Logit Bias"},"user":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"User"},"persona":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Persona"}},"type":"object","required":["model","messages"],"title":"ChatCompletionRequest"},"ChatMessage":{"properties":{"role":{"type":"string","maxLength":20,"title":"Role"},"content":{"type":"string","maxLength":50000,"title":"Content"}},"type":"object","required":["role","content"],"title":"ChatMessage"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"SignupRequest":{"properties":{"name":{"type":"string","maxLength":100,"title":"Name"},"email":{"type":"string","format":"email","title":"Email"},"organization":{"type":"string","maxLength":100,"title":"Organization"}},"type":"object","required":["name","email","organization"],"title":"SignupRequest"},"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"}}}}