{"openapi":"3.1.0","info":{"title":"Shofo API","description":"Social media data at scale. Access comprehensive indexes of TikTok, LinkedIn, Instagram, and X.","version":"1.0.0"},"paths":{"/api/tiktok/sql":{"post":{"tags":["TikTok"],"summary":"Tiktok Sql","operationId":"tiktok_sql_api_tiktok_sql_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__routers__tiktok__SQLRequest","default":{"query":"","limit":100,"include_full_data":false}}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tiktok/feed":{"get":{"tags":["TikTok"],"summary":"Tiktok Feed","operationId":"tiktok_feed_api_tiktok_feed_get","parameters":[{"name":"count","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Count"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tiktok/profile":{"get":{"tags":["TikTok"],"summary":"Tiktok Profile","operationId":"tiktok_profile_api_tiktok_profile_get","parameters":[{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"}},{"name":"sec_uid","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sec Uid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tiktok/hashtag":{"get":{"tags":["TikTok"],"summary":"Tiktok Hashtag","operationId":"tiktok_hashtag_api_tiktok_hashtag_get","parameters":[{"name":"hashtag","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hashtag"}},{"name":"challenge_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Challenge Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tiktok/comments":{"get":{"tags":["TikTok"],"summary":"Tiktok Comments","operationId":"tiktok_comments_api_tiktok_comments_get","parameters":[{"name":"video_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Video Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/linkedin/sql":{"post":{"tags":["LinkedIn"],"summary":"Linkedin Sql","operationId":"linkedin_sql_api_linkedin_sql_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__routers__linkedin__SQLRequest","default":{"query":"","table":"profiles","limit":100}}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/linkedin/user-profile":{"get":{"tags":["LinkedIn"],"summary":"Linkedin User Profile","operationId":"linkedin_user_profile_api_linkedin_user_profile_get","parameters":[{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/linkedin/user-posts":{"get":{"tags":["LinkedIn"],"summary":"Linkedin User Posts","operationId":"linkedin_user_posts_api_linkedin_user_posts_get","parameters":[{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/linkedin/company-profile":{"get":{"tags":["LinkedIn"],"summary":"Linkedin Company Profile","operationId":"linkedin_company_profile_api_linkedin_company_profile_get","parameters":[{"name":"company","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company"}},{"name":"company_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/linkedin/company-posts":{"get":{"tags":["LinkedIn"],"summary":"Linkedin Company Posts","operationId":"linkedin_company_posts_api_linkedin_company_posts_get","parameters":[{"name":"company","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company"}},{"name":"company_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/linkedin/search-employees":{"get":{"tags":["LinkedIn"],"summary":"Linkedin Search Employees","operationId":"linkedin_search_employees_api_linkedin_search_employees_get","parameters":[{"name":"company","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company"}},{"name":"school","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"School"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/instagram/sql":{"post":{"tags":["Instagram"],"summary":"Instagram Sql","operationId":"instagram_sql_api_instagram_sql_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__routers__instagram__SQLRequest","default":{"query":"","table":"profiles","limit":100}}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/instagram/user-profile":{"get":{"tags":["Instagram"],"summary":"Instagram User Profile","operationId":"instagram_user_profile_api_instagram_user_profile_get","parameters":[{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/instagram/user-posts":{"get":{"tags":["Instagram"],"summary":"Instagram User Posts","operationId":"instagram_user_posts_api_instagram_user_posts_get","parameters":[{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/instagram/post":{"get":{"tags":["Instagram"],"summary":"Instagram Post","operationId":"instagram_post_api_instagram_post_get","parameters":[{"name":"code_or_url","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code Or Url"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/instagram/hashtag":{"get":{"tags":["Instagram"],"summary":"Instagram Hashtag","operationId":"instagram_hashtag_api_instagram_hashtag_get","parameters":[{"name":"keyword","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Keyword"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/instagram/comments":{"get":{"tags":["Instagram"],"summary":"Instagram Comments","operationId":"instagram_comments_api_instagram_comments_get","parameters":[{"name":"media_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Media Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/x/sql":{"post":{"tags":["X (Twitter)"],"summary":"X Sql","operationId":"x_sql_api_x_sql_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__routers__x__SQLRequest","default":{"query":"","table":"tweets","limit":100}}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/x/user-profile":{"get":{"tags":["X (Twitter)"],"summary":"X User Profile","operationId":"x_user_profile_api_x_user_profile_get","parameters":[{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/x/user-posts":{"get":{"tags":["X (Twitter)"],"summary":"X User Posts","operationId":"x_user_posts_api_x_user_posts_get","parameters":[{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/x/post":{"get":{"tags":["X (Twitter)"],"summary":"X Post","operationId":"x_post_api_x_post_get","parameters":[{"name":"tweet_id_or_url","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tweet Id Or Url"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/x/comments":{"get":{"tags":["X (Twitter)"],"summary":"X Comments","operationId":"x_comments_api_x_comments_get","parameters":[{"name":"tweet_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tweet Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/x/search":{"get":{"tags":["X (Twitter)"],"summary":"X Search","operationId":"x_search_api_x_search_get","parameters":[{"name":"keyword","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Keyword"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/me":{"get":{"tags":["Users"],"summary":"Get Current User","description":"Get current user profile.\n\nRequires internal authentication from frontend.","operationId":"get_current_user_api_users_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"APIKeyHeader":[]}]},"patch":{"tags":["Users"],"summary":"Update Current User","description":"Update current user settings.\n\nAllowed fields: name, settings (emailNotifications, usageAlerts, alertThreshold)","operationId":"update_current_user_api_users_me_patch","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Settings Update"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/users/me/api-keys":{"get":{"tags":["Users"],"summary":"List Api Keys","description":"List all API keys for the current user.\n\nReturns masked keys (only prefix shown, not full key).","operationId":"list_api_keys_api_users_me_api_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"APIKeyHeader":[]}]},"post":{"tags":["Users"],"summary":"Create Api Key","description":"Create a new API key.\n\nThe raw key is only returned once - save it immediately!\n\nArgs:\n    name: User-friendly name for the key\n    permissions: List of platforms (default: all)","operationId":"create_api_key_api_users_me_api_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/users/me/api-keys/{key_id}":{"delete":{"tags":["Users"],"summary":"Revoke Api Key","description":"Revoke (deactivate) an API key.\n\nThe key cannot be recovered after revocation.","operationId":"revoke_api_key_api_users_me_api_keys__key_id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/me/usage/summary":{"get":{"tags":["Users"],"summary":"Get Usage Summary","description":"Get aggregated usage summary for dashboard.\n\nReturns total requests, current period cost, and key counts.\ncurrentPeriodCost is pulled from Stripe meter summaries (the actual\nbilling source of truth) when available.","operationId":"get_usage_summary_api_users_me_usage_summary_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/users/me/usage":{"get":{"tags":["Users"],"summary":"Get Usage Logs","description":"Get detailed usage logs for a date range.\n\nArgs:\n    start_date: Start of date range (default: 30 days ago)\n    end_date: End of date range (default: now)\n    limit: Maximum records to return (1-1000)","operationId":"get_usage_logs_api_users_me_usage_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Start date (ISO format)","title":"Start Date"},"description":"Start date (ISO format)"},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"End date (ISO format)","title":"End Date"},"description":"End date (ISO format)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/me/usage/by-platform":{"get":{"tags":["Users"],"summary":"Get Usage By Platform","description":"Get usage breakdown by platform.\n\nReturns aggregated stats for each platform (tiktok, linkedin, etc.)","operationId":"get_usage_by_platform_api_users_me_usage_by_platform_get","security":[{"APIKeyHeader":[]}],"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"}}}}}}},"/api/users/me/billing":{"get":{"tags":["Users"],"summary":"Get Billing History","description":"Get billing history (invoices and payments).","operationId":"get_billing_history_api_users_me_billing_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/delete":{"delete":{"tags":["Users"],"summary":"Delete Account","description":"Permanently delete user account and all associated data.\n\nThis action:\n- Revokes all API keys\n- Cancels Stripe subscription (if any)\n- Deletes user document and all related data","operationId":"delete_account_api_users_delete_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/stripe/webhook":{"post":{"tags":["Stripe"],"summary":"Stripe Webhook","description":"Handle Stripe webhooks for metered billing.\n\nEvents handled:\n- invoice.created: Report usage to Stripe before invoice finalization\n- invoice.paid: Record successful payment\n- invoice.payment_failed: Handle failed payment\n- customer.subscription.created: New subscription\n- customer.subscription.deleted: Subscription cancelled","operationId":"stripe_webhook_api_stripe_webhook_post","parameters":[{"name":"Stripe-Signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stripe-Signature"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/stripe/create-checkout-session":{"post":{"tags":["Stripe"],"summary":"Create Checkout Session","description":"Create a Stripe checkout session for subscription signup.\n\nCalled by frontend after user authentication.\nExpects X-Internal-Secret and X-User-Id headers.","operationId":"create_checkout_session_api_stripe_create_checkout_session_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/stripe/create-portal-session":{"post":{"tags":["Stripe"],"summary":"Create Portal Session","description":"Create a Stripe session for payment management.\n\n- If no payment method exists: Uses Checkout Setup mode (goes directly to card entry)\n- If payment method exists: Uses Billing Portal (for managing existing methods)","operationId":"create_portal_session_api_stripe_create_portal_session_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/":{"get":{"summary":"Root","description":"API root - basic info.","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health":{"get":{"summary":"Health","description":"Health check endpoint for Cloud Run.","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/health":{"get":{"summary":"Api Health","description":"API health check.","operationId":"api_health_api_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"CreateApiKeyRequest":{"properties":{"name":{"type":"string","title":"Name"},"permissions":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Permissions"}},"type":"object","required":["name"],"title":"CreateApiKeyRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"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"},"app__routers__instagram__SQLRequest":{"properties":{"query":{"type":"string","title":"Query","default":""},"table":{"type":"string","title":"Table","default":"profiles"},"limit":{"type":"integer","title":"Limit","default":100}},"type":"object","title":"SQLRequest"},"app__routers__linkedin__SQLRequest":{"properties":{"query":{"type":"string","title":"Query","default":""},"table":{"type":"string","title":"Table","default":"profiles"},"limit":{"type":"integer","title":"Limit","default":100}},"type":"object","title":"SQLRequest"},"app__routers__tiktok__SQLRequest":{"properties":{"query":{"type":"string","title":"Query","default":""},"limit":{"type":"integer","title":"Limit","default":100},"include_full_data":{"type":"boolean","title":"Include Full Data","default":false}},"type":"object","title":"SQLRequest"},"app__routers__x__SQLRequest":{"properties":{"query":{"type":"string","title":"Query","default":""},"table":{"type":"string","title":"Table","default":"tweets"},"limit":{"type":"integer","title":"Limit","default":100}},"type":"object","title":"SQLRequest"}},"securitySchemes":{"APIKeyHeader":{"type":"apiKey","in":"header","name":"X-User-Id"}}}}