{"openapi":"3.1.0","info":{"title":"BI Jedi API","description":"\nThe **BI Jedi** API powers multi-tenant analytics: connect databases or a managed warehouse, run SQL, build dashboards, import data, and use AI chat grounded in your business context.\n\n## Authentication\n\nMost routes require a **Bearer** access token from `POST /api/auth/login`, `POST /api/auth/register` + activation, or `POST /api/auth/google/login`.\n\nSend the header: `Authorization: Bearer <access_token>`.\n\nRefresh expired access tokens with `POST /api/auth/refresh` using the refresh token from login.\n\n## Multi-tenancy\n\nResources such as sources, queries, reports, chats, and imports are scoped by **business** (`biz_id` in the path). The authenticated user must have access to that business.\n\n## Data sources\n\n- **Direct** sources point at your operational PostgreSQL (or supported) database.\n- **Warehouse** sources use an internal schema per business for curated and imported data.\n\nUse **execution targets** and query `sourceId` to control where SQL runs.\n\n## Errors\n\nErrors use HTTP status codes (`401`, `403`, `404`, `409`, `422`, `429`, etc.) with a JSON body `{ \"detail\": \"...\" }` unless noted otherwise.\n","version":"1.0.0"},"servers":[{"url":"https://api.bijedi.com","description":"Production API"}],"paths":{"/api/auth/login":{"post":{"tags":["auth"],"summary":"Login with username and password","description":"Authenticates a user by `username` and `password`. Returns access and refresh tokens plus the user profile. The account must be activated; otherwise the API responds with 403.","operationId":"login_api_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/register":{"post":{"tags":["auth"],"summary":"Register a new user","description":"Creates an inactive user and emails a one-time activation code. If SMTP is misconfigured or unreachable, registration still succeeds (201) with `emailSent: false` and the OTP stored for resend. Does not return tokens until `activate-account` succeeds. Returns 409 if username or email is already taken.","operationId":"register_api_auth_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegistrationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/send-activation-otp":{"post":{"tags":["auth"],"summary":"Resend account activation OTP","description":"If the given username/email pair exists and the account is still pending activation, sends a new OTP email. Response message is generic whether or not a user matched (avoid account enumeration).","operationId":"send_activation_otp_api_auth_send_activation_otp_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendActivationOtpRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicMessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/activate-account":{"post":{"tags":["auth"],"summary":"Activate account with OTP","description":"Validates the activation OTP, marks the user as activated and email-verified, and returns login tokens. Too many wrong attempts can lock the OTP.","operationId":"activate_account_api_auth_activate_account_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivateAccountRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/google/login":{"post":{"tags":["auth"],"summary":"Login or sign up with Google","description":"Verifies a Google ID token, links or creates a user by `sub`/email, and returns access and refresh tokens. New Google users are activated immediately.","operationId":"login_with_google_api_auth_google_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleLoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/refresh":{"post":{"tags":["auth"],"summary":"Refresh access token","description":"Exchanges a valid refresh token for a new access token and a new refresh token (refresh rotation). The previous refresh token is revoked.","operationId":"refresh_api_auth_refresh_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/logout":{"post":{"tags":["auth"],"summary":"Logout current user","description":"Revokes all refresh tokens for the authenticated user. The access token may still be valid until it expires.","operationId":"logout_api_auth_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/auth/change-password":{"post":{"tags":["auth"],"summary":"Change password (authenticated)","description":"Updates the password for the currently logged-in user after verifying the current password. All refresh tokens for this user are revoked.","operationId":"change_password_api_auth_change_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/me":{"get":{"tags":["users"],"summary":"Get current user profile","description":"Returns the authenticated user's identity, role flags, language, active business id, and last usage time.","operationId":"get_me_api_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfile"}}}}},"security":[{"HTTPBearer":[]}]},"patch":{"tags":["users"],"summary":"Update current user preferences","description":"Updates optional fields such as UI language (`lang`) and which business is active (`activeBusinessId`).","operationId":"update_me_api_me_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPatch"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/users/change-lang":{"post":{"tags":["users"],"summary":"Change language (authenticated)","description":"Updates the `lang` of the authenticated user only (derived from the access token).","operationId":"change_language_api_users_change_lang_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeLanguageRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/users/sendOtp":{"post":{"tags":["users"],"summary":"Request password-reset OTP (public)","description":"If username and email match an existing user, sends a password-reset OTP. Rate-limited per user and per client IP. Response text does not reveal whether the account exists.","operationId":"send_otp_api_users_sendOtp_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendOtpRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicMessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/forgot-password":{"post":{"tags":["users"],"summary":"Complete password reset with OTP (public)","description":"Validates the emailed OTP together with username/email, sets `newPassword`, and revokes refresh tokens for that user. Also subject to IP-based rate limiting.","operationId":"forgot_password_api_user_forgot_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/ai-token-usage":{"get":{"tags":["businesses"],"summary":"AI token usage for billing period","description":"Returns included quota, tokens used this billing period, and remaining allowance. The period follows the Stripe subscription when active; otherwise UTC calendar month. Chat requests are rejected with 403 when `tokensRemaining` is zero.","operationId":"get_ai_token_usage_api_businesses__biz_id__ai_token_usage_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiTokenUsageOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses":{"get":{"tags":["businesses"],"summary":"List my businesses","description":"Returns all businesses owned by the authenticated user, newest first.","operationId":"list_businesses_api_businesses_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/BusinessListOut"},"type":"array","title":"Response List Businesses Api Businesses Get"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["businesses"],"summary":"Create business","description":"Creates a business for the current user with workspace status **`unpaid`** until catalog free trial or a Stripe subscription is active (webhooks set **`active`** after payment). If the user had no active business, this one becomes the UI context. Creating a **second** owned workspace ends any active trial and consumes the one-time trial for the account.","operationId":"create_business_api_businesses_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/businesses/{biz_id}/start-explorer-trial":{"post":{"tags":["businesses"],"summary":"Start catalog 7-day free trial","description":"Activates the **trial-eligible** catalog plan (`subscription_plans.trialEligible`) for **7 days** without a Stripe card on your **first** workspace only. After the trial, the workspace becomes unpaid until you subscribe. Creating another workspace forfeits the trial.","operationId":"start_explorer_trial_endpoint_api_businesses__biz_id__start_explorer_trial_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}":{"put":{"tags":["businesses"],"summary":"Update business","description":"Replaces editable fields for a business you own. Allowed even when workspace status is **`unpaid`** (so metadata can be edited before or after billing). Other `/api/businesses/{biz_id}/…` resources remain gated until paid.","operationId":"update_business_api_businesses__biz_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["businesses"],"summary":"Delete business","description":"Deletes the business and clears it as the user's active business if it was selected.","operationId":"delete_business_api_businesses__biz_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/members":{"get":{"tags":["workspace-members"],"summary":"List workspace members","description":"Returns invited users and pending email invites. **Owner only**, paid workspace.","operationId":"list_members_api_businesses__biz_id__members_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceMemberOut"},"title":"Response List Members Api Businesses  Biz Id  Members Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["workspace-members"],"summary":"Invite user to workspace","description":"Adds an **existing** account (username or email) as a member, or sends a **signup invitation email** when the value is an email address with no matching user yet. Pending invites count toward the plan seat cap.","operationId":"invite_member_api_businesses__biz_id__members_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceMemberInvite"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceMemberOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/members/pending/{invite_id}":{"delete":{"tags":["workspace-members"],"summary":"Revoke pending workspace invite","description":"Removes an email invite that has not been accepted yet. **Owner only**.","operationId":"remove_pending_invite_api_businesses__biz_id__members_pending__invite_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"invite_id","in":"path","required":true,"schema":{"type":"string","title":"Invite Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/members/{member_user_id}":{"delete":{"tags":["workspace-members"],"summary":"Remove workspace member","description":"Revokes member access. **Owner only**, paid workspace.","operationId":"remove_member_api_businesses__biz_id__members__member_user_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"member_user_id","in":"path","required":true,"schema":{"type":"string","title":"Member User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/sectors":{"get":{"tags":["sectors"],"summary":"List business sectors","description":"Public catalog of sector options with `en`, `it`, and `es` labels for signup and business settings.","operationId":"list_sectors_api_sectors_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SectorOut"},"type":"array","title":"Response List Sectors Api Sectors Get"}}}}}}},"/api/businesses/{biz_id}/sources/test":{"post":{"tags":["sources"],"summary":"Test database connection credentials","description":"Attempts a live connection with the provided host/credentials without persisting a source. Registered both under `/api/sources/test` and under the business path for the same behavior.","operationId":"test_connection_standalone_api_businesses__biz_id__sources_test_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestConnectionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestConnectionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/sources/test":{"post":{"tags":["sources"],"summary":"Test database connection credentials","description":"Attempts a live connection with the provided host/credentials without persisting a source. Registered both under `/api/sources/test` and under the business path for the same behavior.","operationId":"test_connection_standalone_api_sources_test_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"query","required":false,"schema":{"type":"string","title":"Biz Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestConnectionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestConnectionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/sources":{"get":{"tags":["sources"],"summary":"List data sources","description":"Returns all configured sources for the business (direct DB, warehouse, etc.) including table metadata snapshots.","operationId":"list_sources_api_businesses__biz_id__sources_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SourceOut"},"title":"Response List Sources Api Businesses  Biz Id  Sources Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["sources"],"summary":"Create data source","description":"Adds a direct database source (tests connection on create) or activates the internal warehouse when `mode` is warehouse. Can mark the source as default for new queries.","operationId":"create_source_api_businesses__biz_id__sources_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/sources/execution-targets":{"get":{"tags":["sources"],"summary":"List sources available for query execution","description":"Like list sources but only entries in `connected` status—suitable for populating SQL runner and widget data source pickers.","operationId":"list_execution_targets_api_businesses__biz_id__sources_execution_targets_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SourceOut"},"title":"Response List Execution Targets Api Businesses  Biz Id  Sources Execution Targets Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/sources/warehouse":{"post":{"tags":["sources"],"summary":"Activate or refresh warehouse source","description":"Ensures the per-business warehouse schema exists, syncs metadata, and optionally rebinds saved queries that pointed at direct sources (when `rebindDirectQueries` is true).","operationId":"activate_warehouse_source_api_businesses__biz_id__sources_warehouse_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseSourceCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/sources/direct/activate":{"post":{"tags":["sources"],"summary":"Activate direct DB as default and optionally rebind queries","description":"Marks a direct (operational) source as the default for queries. Optionally moves saved queries from the warehouse source back to this direct source (`reboundWarehouseQueries`).","operationId":"activate_direct_source_api_businesses__biz_id__sources_direct_activate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DirectSourceActivateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DirectSourceActivateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/sources/{src_id}":{"put":{"tags":["sources"],"summary":"Update data source","description":"Updates connection parameters for a direct source or warehouse settings; may re-test connectivity and adjust default flags.","operationId":"update_source_api_businesses__biz_id__sources__src_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"src_id","in":"path","required":true,"schema":{"type":"string","title":"Src Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["sources"],"summary":"Delete data source","description":"Removes the source configuration and associated cached metadata from the app database.","operationId":"delete_source_api_businesses__biz_id__sources__src_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"src_id","in":"path","required":true,"schema":{"type":"string","title":"Src Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/sources/{src_id}/test":{"post":{"tags":["sources"],"summary":"Test saved source connection","description":"Re-validates connectivity using the request body (for direct) or internal checks (for warehouse) and updates stored `status` when successful.","operationId":"test_existing_source_api_businesses__biz_id__sources__src_id__test_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"src_id","in":"path","required":true,"schema":{"type":"string","title":"Src Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestConnectionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestConnectionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/sources/{src_id}/probe":{"post":{"tags":["sources"],"summary":"Probe saved source (stored credentials)","description":"Tests connectivity using credentials stored for this source and updates `status` in the database.","operationId":"probe_saved_source_api_businesses__biz_id__sources__src_id__probe_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"src_id","in":"path","required":true,"schema":{"type":"string","title":"Src Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestConnectionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/sources/{src_id}/sync":{"post":{"tags":["sources"],"summary":"Sync source metadata","description":"Re-introspects tables and columns from the live database or warehouse schema and refreshes the cached catalog used by the UI and AI.","operationId":"sync_source_api_businesses__biz_id__sources__src_id__sync_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"src_id","in":"path","required":true,"schema":{"type":"string","title":"Src Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceSyncResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/sources/{src_id}/tables/bulk-visibility":{"patch":{"tags":["sources"],"summary":"Bulk update table visibility","description":"Sets visible for many catalogued tables in one request (all tables or an optional id list).","operationId":"bulk_update_table_visibility_api_businesses__biz_id__sources__src_id__tables_bulk_visibility_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"src_id","in":"path","required":true,"schema":{"type":"string","title":"Src Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TableBulkVisibilityPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TableBulkVisibilityOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/sources/{src_id}/tables/{table_id}/showLastRecords":{"get":{"tags":["sources"],"summary":"Preview last rows of a table","description":"Returns a small sample (latest rows) of a table for exploration before writing SQL.","operationId":"show_last_records_api_businesses__biz_id__sources__src_id__tables__table_id__showLastRecords_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"src_id","in":"path","required":true,"schema":{"type":"string","title":"Src Id"}},{"name":"table_id","in":"path","required":true,"schema":{"type":"string","title":"Table Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TablePreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/sources/{src_id}/tables/{table_id}":{"patch":{"tags":["sources"],"summary":"Update table metadata","description":"Edits user-facing alias, description, or visibility for a catalogued table.","operationId":"update_table_metadata_api_businesses__biz_id__sources__src_id__tables__table_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"src_id","in":"path","required":true,"schema":{"type":"string","title":"Src Id"}},{"name":"table_id","in":"path","required":true,"schema":{"type":"string","title":"Table Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TablePatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TableOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/sources/{src_id}/tables/{table_id}/columns/{col_name}":{"patch":{"tags":["sources"],"summary":"Update column metadata","description":"Edits display alias and description for a single column, used in grids and prompts.","operationId":"update_column_metadata_api_businesses__biz_id__sources__src_id__tables__table_id__columns__col_name__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"src_id","in":"path","required":true,"schema":{"type":"string","title":"Src Id"}},{"name":"table_id","in":"path","required":true,"schema":{"type":"string","title":"Table Id"}},{"name":"col_name","in":"path","required":true,"schema":{"type":"string","title":"Col Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ColumnPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ColumnOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/queries":{"get":{"tags":["queries"],"summary":"List saved queries","description":"Returns SQL definitions, linked `sourceId`, and column formatting config for the business.","operationId":"list_queries_api_businesses__biz_id__queries_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/QueryOut"},"title":"Response List Queries Api Businesses  Biz Id  Queries Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["queries"],"summary":"Create saved query","description":"Stores a named SQL statement. `sourceId` selects the execution target; when omitted, the business default source is used.","operationId":"create_query_api_businesses__biz_id__queries_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/queries/{query_id}":{"put":{"tags":["queries"],"summary":"Update saved query","description":"Updates SQL, optional source binding, and column config. Ensures a source is assigned when needed.","operationId":"update_query_api_businesses__biz_id__queries__query_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"query_id","in":"path","required":true,"schema":{"type":"string","title":"Query Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["queries"],"summary":"Delete saved query","description":"Removes the query; widgets referencing it may break until reconfigured.","operationId":"delete_query_api_businesses__biz_id__queries__query_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"query_id","in":"path","required":true,"schema":{"type":"string","title":"Query Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/queries/templates":{"get":{"tags":["queries"],"summary":"List query templates","description":"Returns parametric query template definitions for the guided wizard.","operationId":"get_query_templates_api_businesses__biz_id__queries_templates_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Query Templates Api Businesses  Biz Id  Queries Templates Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/queries/generate-builder":{"post":{"tags":["queries"],"summary":"Generate SQL from visual builder","description":"Builds dialect-aware SQL from table, dimensions, measures, time grain, and filters.","operationId":"generate_query_from_builder_api_businesses__biz_id__queries_generate_builder_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryVisualBuilderRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryTemplateGenerateResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/queries/generate-template":{"post":{"tags":["queries"],"summary":"Generate SQL from template","description":"Builds dialect-aware SQL from a template id and parameters for the selected source.","operationId":"generate_query_from_template_api_businesses__biz_id__queries_generate_template_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryTemplateGenerateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryTemplateGenerateResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/queries/assist":{"post":{"tags":["queries"],"summary":"AI copilot for the query configurator","description":"Generates or edits a single read-only SQL query from a natural-language request, using the resolved source schema/dialect, and returns SQL plus a plain-language explanation. Nothing is executed or saved; counts against the AI token quota.","operationId":"assist_query_api_businesses__biz_id__queries_assist_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryAssistRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryAssistResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/queries/{query_id}/execute":{"post":{"tags":["queries"],"summary":"Execute saved query","description":"Runs the stored SQL against the resolved source (or `sourceId` override), applies `limit`, and returns rows plus timing. Column formatting from `columnsConfig` is applied unless `rawResult` is true.","operationId":"execute_saved_query_api_businesses__biz_id__queries__query_id__execute_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"query_id","in":"path","required":true,"schema":{"type":"string","title":"Query Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryExecuteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryExecuteResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/reports":{"get":{"tags":["reports"],"summary":"List reports","description":"Dashboard index for the business with name, timestamps, and widget counts.","operationId":"list_reports_api_businesses__biz_id__reports_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ReportListItem"},"title":"Response List Reports Api Businesses  Biz Id  Reports Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["reports"],"summary":"Create report","description":"Creates an empty dashboard; add widgets via widget endpoints or save a full layout.","operationId":"create_report_api_businesses__biz_id__reports_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportCreated"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/reports/{report_id}":{"get":{"tags":["reports"],"summary":"Get report with widgets","description":"Loads a single dashboard including widget definitions (layout, type, linked query ids).","operationId":"get_report_api_businesses__biz_id__reports__report_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"report_id","in":"path","required":true,"schema":{"type":"string","title":"Report Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportFull"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["reports"],"summary":"Update report","description":"Rename the dashboard and/or merge `settings` (e.g. `autoRefreshSec` for UI polling).","operationId":"patch_report_api_businesses__biz_id__reports__report_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"report_id","in":"path","required":true,"schema":{"type":"string","title":"Report Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["reports"],"summary":"Delete report","description":"Deletes the dashboard and its widgets.","operationId":"delete_report_api_businesses__biz_id__reports__report_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"report_id","in":"path","required":true,"schema":{"type":"string","title":"Report Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/reports/{report_id}/layout":{"put":{"tags":["reports"],"summary":"Save report layout","description":"Replaces the widget set and their positions: widgets omitted from the payload are deleted; ids that already exist are updated, new ids are inserted.","operationId":"save_layout_api_businesses__biz_id__reports__report_id__layout_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"report_id","in":"path","required":true,"schema":{"type":"string","title":"Report Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LayoutSave"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/reports/{report_id}/public-share":{"get":{"tags":["reports"],"summary":"Public share link status","description":"Returns whether a secret public URL is active for this dashboard. **Owner only.**","operationId":"get_report_public_share_status_api_businesses__biz_id__reports__report_id__public_share_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"report_id","in":"path","required":true,"schema":{"type":"string","title":"Report Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportPublicShareStatusOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["reports"],"summary":"Enable or refresh public share link","description":"Creates a new secret token or reactivates a revoked link with a **new** token. **Owner only.** Anyone with the URL can view this dashboard read-only (no login).","operationId":"enable_report_public_share_api_businesses__biz_id__reports__report_id__public_share_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"report_id","in":"path","required":true,"schema":{"type":"string","title":"Report Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportPublicShareStatusOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["reports"],"summary":"Revoke public share link","description":"Invalidates the secret URL. **Owner only.**","operationId":"revoke_report_public_share_api_businesses__biz_id__reports__report_id__public_share_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"report_id","in":"path","required":true,"schema":{"type":"string","title":"Report Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/reports/{report_id}/widgets":{"post":{"tags":["widgets"],"summary":"Create widget","description":"Adds a widget to the report (chart/KPI/table settings, optional grid position, link to a saved query).","operationId":"create_widget_api_businesses__biz_id__reports__report_id__widgets_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"report_id","in":"path","required":true,"schema":{"type":"string","title":"Report Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WidgetCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WidgetOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/reports/{report_id}/widgets/{widget_id}":{"put":{"tags":["widgets"],"summary":"Update widget","description":"Updates visualization type, query binding, formatting options, and layout coordinates.","operationId":"update_widget_api_businesses__biz_id__reports__report_id__widgets__widget_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"report_id","in":"path","required":true,"schema":{"type":"string","title":"Report Id"}},{"name":"widget_id","in":"path","required":true,"schema":{"type":"string","title":"Widget Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WidgetUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WidgetOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["widgets"],"summary":"Delete widget","description":"Removes the widget from the dashboard.","operationId":"delete_widget_api_businesses__biz_id__reports__report_id__widgets__widget_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"report_id","in":"path","required":true,"schema":{"type":"string","title":"Report Id"}},{"name":"widget_id","in":"path","required":true,"schema":{"type":"string","title":"Widget Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/reports/{report_id}/widgets/{widget_id}/data":{"get":{"tags":["widgets"],"summary":"Get widget data","description":"Runs the widget's linked saved query (up to 500 rows) and shapes the result for the widget type (KPI value/delta vs tabular/chart series).","operationId":"get_widget_data_api_businesses__biz_id__reports__report_id__widgets__widget_id__data_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"report_id","in":"path","required":true,"schema":{"type":"string","title":"Report Id"}},{"name":"widget_id","in":"path","required":true,"schema":{"type":"string","title":"Widget Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WidgetDataResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/chats":{"get":{"tags":["chats"],"summary":"List chats","description":"Returns chat threads for the business ordered by last activity.","operationId":"list_chats_api_businesses__biz_id__chats_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ChatListItem"},"title":"Response List Chats Api Businesses  Biz Id  Chats Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["chats"],"summary":"Create chat","description":"Creates an empty analysis chat; the title can be renamed or auto-derived from the first message.","operationId":"create_chat_api_businesses__biz_id__chats_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatFull"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/chats/text-to-speech":{"post":{"tags":["chats"],"summary":"Synthesize speech","description":"Streams MP3 audio via OpenAI TTS as it is generated (chunked transfer). Pass ?stream=false for a single buffered response.","operationId":"text_to_speech_api_businesses__biz_id__chats_text_to_speech_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"stream","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Stream"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatTtsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}},"audio/mpeg":{}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/chats/{chat_id}":{"patch":{"tags":["chats"],"summary":"Rename chat","description":"Updates the chat title shown in history lists.","operationId":"rename_chat_api_businesses__biz_id__chats__chat_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"chat_id","in":"path","required":true,"schema":{"type":"string","title":"Chat Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["chats"],"summary":"Delete chat","description":"Permanently removes the chat and all stored messages.","operationId":"delete_chat_api_businesses__biz_id__chats__chat_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"chat_id","in":"path","required":true,"schema":{"type":"string","title":"Chat Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/chats/{chat_id}/messages":{"get":{"tags":["chats"],"summary":"List chat messages","description":"Returns the full conversation in chronological order with optional assistant metadata (e.g. query references).","operationId":"get_messages_api_businesses__biz_id__chats__chat_id__messages_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"chat_id","in":"path","required":true,"schema":{"type":"string","title":"Chat Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MessageOut"},"title":"Response Get Messages Api Businesses  Biz Id  Chats  Chat Id  Messages Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["chats"],"summary":"Send chat message","description":"Appends the user message, calls the AI pipeline with business context, stores the assistant reply, and returns the assistant text plus metadata. May auto-title the chat from the first user message.","operationId":"send_message_api_businesses__biz_id__chats__chat_id__messages_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"chat_id","in":"path","required":true,"schema":{"type":"string","title":"Chat Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/subscription":{"get":{"tags":["subscription"],"summary":"Get current subscription","description":"Returns plan name, billing status, formatted monthly price, next renewal, and masked payment method for the **active Business** (`activeBusinessId`). If none is set or no row exists for that Business, returns the free tier defaults.","operationId":"get_subscription_api_subscription_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionOut"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/subscription/change-plan":{"post":{"tags":["subscription"],"summary":"Change subscription plan","description":"**Upgrade:** Stripe applies the new price immediately and invoices the prorated difference (`prorationInvoiceUrl` when available). **Downgrade:** Uses a Stripe Subscription Schedule so the lower price applies from the **next** billing period; until then the current plan stays active. See `pendingPlanChange` on `GET /api/subscription`. Requires the workspace owner and an active Stripe-backed subscription.","operationId":"change_plan_api_subscription_change_plan_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionChangePlanRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionChangePlanResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/subscription/pending-plan-change":{"delete":{"tags":["subscription"],"summary":"Cancel scheduled downgrade","description":"Releases the Stripe Subscription Schedule and clears a pending downgrade for the active workspace. Does not refund; the current plan continues until the next renewal.","operationId":"cancel_pending_plan_change_endpoint_api_subscription_pending_plan_change_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/subscription/plans":{"get":{"tags":["subscription"],"summary":"List subscription plans (catalog)","description":"Returns all configured plans from the catalog (same payload as admin `GET /api/subscription-plans`): name, minor-unit price, currency, display string, billing interval, Stripe Price id, sort order. Use `activeOnly=true` to show only purchasable plans. Requires authentication.","operationId":"list_subscription_plans_api_subscription_plans_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"activeOnly","in":"query","required":false,"schema":{"type":"boolean","description":"If true, only plans with `isActive` true.","default":false,"title":"Activeonly"},"description":"If true, only plans with `isActive` true."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SubscriptionPlanOut"},"title":"Response List Subscription Plans Api Subscription Plans Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/subscription/plans/{plan_id}":{"get":{"tags":["subscription"],"summary":"Get subscription plan by id","description":"Single catalog row by internal id (`spl_…`). Same as admin `GET /api/subscription-plans/{plan_id}`.","operationId":"get_subscription_plan_api_subscription_plans__plan_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"plan_id","in":"path","required":true,"schema":{"type":"string","title":"Plan Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionPlanOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/subscription/invoices":{"get":{"tags":["subscription"],"summary":"List invoices","description":"Historical invoices for the authenticated user with amounts, status, business workspace id, and PDF URLs. Optional `businessId` filters to invoices linked to that project (must be owned by the user).","operationId":"list_invoices_api_subscription_invoices_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"businessId","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"If set, only invoices linked to this `biz_…` workspace.","title":"Businessid"},"description":"If set, only invoices linked to this `biz_…` workspace."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/InvoiceOut"},"title":"Response List Invoices Api Subscription Invoices Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/subscription/invoices/{invoice_id}/pdf":{"get":{"tags":["subscription"],"summary":"Download invoice PDF","description":"Streams the stored PDF for an invoice that belongs to the current user.","operationId":"download_invoice_pdf_api_subscription_invoices__invoice_id__pdf_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"invoice_id","in":"path","required":true,"schema":{"type":"string","title":"Invoice Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/pdf":{}}},"404":{"description":"Invoice/PDF not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/import-sources":{"get":{"tags":["imports"],"summary":"List import sources","description":"Configured origins for data loads: linked DB, uploaded files, FTP/SFTP, etc., with secrets redacted in config.","operationId":"list_import_sources_api_businesses__biz_id__import_sources_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ImportSourceOut"},"title":"Response List Import Sources Api Businesses  Biz Id  Import Sources Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["imports"],"summary":"Create import source","description":"Defines where data is read from. `db` requires a linked operational `sourceId`; remote kinds require a normalized `config` (host, paths, credentials or SSH key).","operationId":"create_import_source_api_businesses__biz_id__import_sources_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportSourceCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportSourceOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/import-sources/upload":{"post":{"tags":["imports"],"summary":"Upload file as import source","description":"Accepts CSV or Excel; stores the file and registers an `excel`/`csv` import source pointing at it.","operationId":"upload_import_file_api_businesses__biz_id__import_sources_upload_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_import_file_api_businesses__biz_id__import_sources_upload_post"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileImportUploadResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/import-sources/test":{"post":{"tags":["imports"],"summary":"Test FTP/SFTP import configuration","description":"Validates credentials/connectivity for a not-yet-saved remote config (`kind` must be `ftp` or `sftp`).","operationId":"test_remote_import_source_api_businesses__biz_id__import_sources_test_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportSourceTestRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestConnectionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/import-sources/{import_source_id}/test":{"post":{"tags":["imports"],"summary":"Test saved FTP/SFTP import source","description":"Runs the same connectivity check using the persisted (decrypted) configuration for an existing import source.","operationId":"test_saved_import_source_api_businesses__biz_id__import_sources__import_source_id__test_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"import_source_id","in":"path","required":true,"schema":{"type":"string","title":"Import Source Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestConnectionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/import-sources/{import_source_id}":{"delete":{"tags":["imports"],"summary":"Delete import source","description":"Removes the import source record; jobs referencing it should be deleted or updated separately.","operationId":"delete_import_source_api_businesses__biz_id__import_sources__import_source_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"import_source_id","in":"path","required":true,"schema":{"type":"string","title":"Import Source Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/import-jobs":{"get":{"tags":["imports"],"summary":"List import jobs","description":"Shows mapping from import sources to warehouse tables, schedule settings, and last run status.","operationId":"list_import_jobs_api_businesses__biz_id__import_jobs_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ImportJobOut"},"title":"Response List Import Jobs Api Businesses  Biz Id  Import Jobs Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["imports"],"summary":"Create import job","description":"Binds an import source to a warehouse `targetSourceId`/`targetTable`, optional schedule, and write mode. Registers the job with the background scheduler when applicable.","operationId":"create_import_job_api_businesses__biz_id__import_jobs_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportJobCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportJobOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/import-jobs/{job_id}":{"put":{"tags":["imports"],"summary":"Update import job","description":"Replaces job parameters and refreshes scheduler registration to match the new cadence or active flag.","operationId":"update_import_job_api_businesses__biz_id__import_jobs__job_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportJobUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportJobOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["imports"],"summary":"Delete import job","description":"Unschedules the job if needed and deletes its configuration.","operationId":"delete_import_job_api_businesses__biz_id__import_jobs__job_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/import-jobs/{job_id}/run-now":{"post":{"tags":["imports"],"summary":"Run import job now","description":"Triggers an immediate ETL run and returns the resulting `ImportRun` summary (rows imported, errors).","operationId":"run_import_job_now_api_businesses__biz_id__import_jobs__job_id__run_now_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportJobRunResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/import-jobs/{job_id}/runs":{"get":{"tags":["imports"],"summary":"List import runs","description":"Audit log of executions for a job, newest first, including duration and status.","operationId":"list_import_runs_api_businesses__biz_id__import_jobs__job_id__runs_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ImportRunOut"},"title":"Response List Import Runs Api Businesses  Biz Id  Import Jobs  Job Id  Runs Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/import-latest-success":{"get":{"tags":["imports"],"summary":"Latest successful ETL completion","description":"Timestamp of the most recent **successful** import run in the workspace. Useful to show “data refreshed after ETL” hints next to dashboards.","operationId":"get_latest_successful_import_api_businesses__biz_id__import_latest_success_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportLatestSuccessOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/public/report-shares/{token}":{"get":{"tags":["public-shares"],"summary":"Load shared dashboard (metadata)","description":"No authentication. Returns report layout and column-format hints for charts; fetch widget data per id separately.","operationId":"get_public_report_bundle_api_public_report_shares__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicReportBundleOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/public/report-shares/{token}/widgets/{widget_id}/data":{"get":{"tags":["public-shares"],"summary":"Shared widget data","description":"Runs the linked saved query and returns formatted widget payload (same shape as authenticated widget data).","operationId":"get_public_widget_data_api_public_report_shares__token__widgets__widget_id__data_get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}},{"name":"widget_id","in":"path","required":true,"schema":{"type":"string","title":"Widget Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WidgetDataResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/semantic-metrics":{"get":{"tags":["semantic-metrics"],"summary":"List Semantic Metrics","operationId":"list_semantic_metrics_api_businesses__biz_id__semantic_metrics_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SemanticMetricOut"},"title":"Response List Semantic Metrics Api Businesses  Biz Id  Semantic Metrics Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["semantic-metrics"],"summary":"Create Semantic Metric","operationId":"create_semantic_metric_api_businesses__biz_id__semantic_metrics_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SemanticMetricCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SemanticMetricOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/semantic-metrics/{metric_id}":{"put":{"tags":["semantic-metrics"],"summary":"Update Semantic Metric","operationId":"update_semantic_metric_api_businesses__biz_id__semantic_metrics__metric_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"metric_id","in":"path","required":true,"schema":{"type":"string","title":"Metric Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SemanticMetricUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SemanticMetricOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["semantic-metrics"],"summary":"Delete Semantic Metric","operationId":"delete_semantic_metric_api_businesses__biz_id__semantic_metrics__metric_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"metric_id","in":"path","required":true,"schema":{"type":"string","title":"Metric Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/businesses/{biz_id}/semantic-metrics/{metric_id}/run":{"post":{"tags":["semantic-metrics"],"summary":"Run Semantic Metric","operationId":"run_semantic_metric_api_businesses__biz_id__semantic_metrics__metric_id__run_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"biz_id","in":"path","required":true,"schema":{"type":"string","title":"Biz Id"}},{"name":"metric_id","in":"path","required":true,"schema":{"type":"string","title":"Metric Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SemanticMetricRunRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryExecuteResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/support/thread":{"get":{"tags":["support"],"summary":"Get support conversation","description":"Returns the current user's support thread and messages.","operationId":"get_thread_api_support_thread_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupportThreadOut"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/support/messages":{"post":{"tags":["support"],"summary":"Send support message","description":"Adds a user message to the support thread and notifies the admin by email.","operationId":"send_message_api_support_messages_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupportMessageCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupportMessageOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/health":{"get":{"tags":["system"],"summary":"Health check","description":"Returns service availability and the configured application name. Use for load balancers and uptime checks.","operationId":"health_api_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"ActivateAccountRequest":{"properties":{"username":{"type":"string","title":"Username","description":"Username for the pending account."},"email":{"type":"string","title":"Email","description":"Email that received the activation code."},"otp":{"type":"string","maxLength":6,"minLength":6,"title":"Otp","description":"Six-character code from the activation email."}},"type":"object","required":["username","email","otp"],"title":"ActivateAccountRequest","example":{"email":"john.smith@example.com","otp":"Aa1B2c","username":"j.smith"}},"AiTokenUsageOut":{"properties":{"periodStart":{"type":"string","format":"date-time","title":"Periodstart","description":"Start of the current billing period for usage (UTC)."},"periodEnd":{"type":"string","format":"date-time","title":"Periodend","description":"End of the current billing period (exclusive boundary, UTC)."},"monthlyTokenQuota":{"type":"integer","title":"Monthlytokenquota","description":"Included tokens for this period."},"tokensUsed":{"type":"integer","title":"Tokensused","description":"Tokens consumed this period (LLM usage_metadata totals)."},"tokensRemaining":{"type":"integer","title":"Tokensremaining","description":"Remaining tokens before new chat requests are rejected."},"requestCountPeriod":{"type":"integer","title":"Requestcountperiod","description":"AI chat requests in the current billing period.","default":0},"tokensUsedLifetime":{"type":"integer","title":"Tokensusedlifetime","description":"Sum of tokens across all billing periods.","default":0},"aiRequestCountLifetime":{"type":"integer","title":"Airequestcountlifetime","description":"Total AI assistant replies for this workspace.","default":0},"tokensPerRequestLifetime":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Tokensperrequestlifetime","description":"Average tokens per AI request (lifetime)."},"stripePriceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stripepriceid","description":"Stripe Price id for this workspace when set (maps to catalog quota)."}},"type":"object","required":["periodStart","periodEnd","monthlyTokenQuota","tokensUsed","tokensRemaining"],"title":"AiTokenUsageOut"},"Body_upload_import_file_api_businesses__biz_id__import_sources_upload_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","required":["file"],"title":"Body_upload_import_file_api_businesses__biz_id__import_sources_upload_post"},"BusinessCreate":{"properties":{"name":{"type":"string","maxLength":100,"title":"Name","description":"Business display name (max 100 characters)."},"description":{"type":"string","title":"Description","description":"Free-text description shown in profile and prompts."},"sector":{"type":"string","title":"Sector","description":"Sector key from GET /api/sectors (typically English label value)."},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website","description":"Public website URL, if any."},"rag_rules":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rag Rules","description":"Optional rules text injected into RAG / AI context for this business.","default":""}},"type":"object","required":["name","description","sector"],"title":"BusinessCreate","example":{"description":"Sample business description","name":"BI Jedi Demo","rag_rules":"","sector":"Retail","website":"https://example.com"}},"BusinessListOut":{"properties":{"id":{"type":"string","title":"Id","description":"Business id used in path parameters."},"name":{"type":"string","title":"Name","description":"Display name."},"description":{"type":"string","title":"Description","description":"Description text."},"sector":{"type":"string","title":"Sector","description":"Selected sector identifier/label."},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website","description":"Website URL or null."},"status":{"type":"string","title":"Status","description":"Lifecycle status: `active` (paid), `trial` (catalog free trial), or `unpaid`."},"trialStartedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Trialstartedat","description":"When the catalog free trial started; null if not on trial."},"trialEndsAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Trialendsat","description":"When the catalog free trial ends (UTC); null if not on trial."},"rag_rules":{"type":"string","title":"Rag Rules","description":"RAG / AI rules text."},"createdAt":{"type":"string","format":"date-time","title":"Createdat","description":"Creation time (UTC)."},"isActiveContext":{"type":"boolean","title":"Isactivecontext","description":"True when this business is the user's selected workspace (`activeBusinessId`).","default":false},"workspaceRole":{"type":"string","title":"Workspacerole","description":"`owner` (project admin) or `member` (dashboards and analysis chat only).","default":"owner"},"subscriptionPlan":{"type":"string","title":"Subscriptionplan","description":"Commercial plan label for the **current** billing period. After a scheduled downgrade, this stays the higher plan until `pendingPlanChange.effectiveAt`; use `pendingPlanChange` for the next plan.","default":"BI Jedi Free"},"subscriptionPlanId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subscriptionplanid","description":"Internal catalog plan id (`spl_…`) stored when the subscription was activated; null if unknown."},"subscriptionPlanCatalog":{"anyOf":[{"$ref":"#/components/schemas/SubscriptionPlanOut"},{"type":"null"}],"description":"Full catalog snapshot for the active plan when a matching `subscription_plans` row exists."},"subscriptionStatus":{"type":"string","title":"Subscriptionstatus","description":"Billing status for this workspace subscription.","default":"active"},"priceMonthly":{"type":"string","title":"Pricemonthly","description":"Formatted recurring price for the **current** period. If `pendingPlanChange` is set, the lower price applies from `effectiveAt` (usually aligned with `nextRenewal`).","default":"€ 0,00"},"nextRenewal":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nextrenewal","description":"Next renewal date label when known."},"activatedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Activatedat","description":"First paid checkout completion or subscription row / business creation time."},"paymentMethod":{"anyOf":[{"$ref":"#/components/schemas/BusinessPaymentMethodOut"},{"type":"null"}],"description":"Masked payment method for this workspace when stored."},"tokensUsed":{"type":"integer","title":"Tokensused","description":"LLM tokens consumed in the current billing period (same window as GET …/ai-token-usage).","default":0},"tokensAvailable":{"type":"integer","title":"Tokensavailable","description":"Remaining LLM tokens before new chat requests are rejected (same period as tokensUsed).","default":0},"usersUsed":{"type":"integer","minimum":1,"title":"Usersused","description":"Workspace seats in use: 1 owner plus invited members (same cap as plan `maxIncludedUsers`).","default":1},"pendingPlanChange":{"anyOf":[{"$ref":"#/components/schemas/PendingPlanChangeOut"},{"type":"null"}],"description":"When set, a cheaper plan is scheduled from `effectiveAt` (next period); `subscriptionPlan` / `priceMonthly` remain the current period until then."}},"type":"object","required":["id","name","description","sector","website","status","rag_rules","createdAt"],"title":"BusinessListOut","description":"Business row for `GET /api/businesses` (list): same as `BusinessOut` but without Stripe audit / invoice totals.","example":{"activatedAt":"2026-04-18T10:05:00Z","createdAt":"2026-03-31T10:00:00Z","description":"Sample business description","id":"biz_123","isActiveContext":true,"name":"BI Jedi Demo","nextRenewal":"2026-05-18","paymentMethod":{"brand":"visa","last4":"4242","type":"card"},"priceMonthly":"€ 15,00","rag_rules":"","sector":"Retail","status":"active","subscriptionPlan":"BI Jedi Pro","subscriptionPlanId":"spl_abc123","subscriptionStatus":"active","tokensAvailable":88000,"tokensUsed":12000,"usersUsed":3,"website":"https://example.com","workspaceRole":"owner"}},"BusinessOut":{"properties":{"id":{"type":"string","title":"Id","description":"Business id used in path parameters."},"name":{"type":"string","title":"Name","description":"Display name."},"description":{"type":"string","title":"Description","description":"Description text."},"sector":{"type":"string","title":"Sector","description":"Selected sector identifier/label."},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website","description":"Website URL or null."},"status":{"type":"string","title":"Status","description":"Lifecycle status: `active` (paid), `trial` (catalog free trial), or `unpaid`."},"trialStartedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Trialstartedat","description":"When the catalog free trial started; null if not on trial."},"trialEndsAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Trialendsat","description":"When the catalog free trial ends (UTC); null if not on trial."},"rag_rules":{"type":"string","title":"Rag Rules","description":"RAG / AI rules text."},"createdAt":{"type":"string","format":"date-time","title":"Createdat","description":"Creation time (UTC)."},"isActiveContext":{"type":"boolean","title":"Isactivecontext","description":"True when this business is the user's selected workspace (`activeBusinessId`).","default":false},"workspaceRole":{"type":"string","title":"Workspacerole","description":"`owner` (project admin) or `member` (dashboards and analysis chat only).","default":"owner"},"subscriptionPlan":{"type":"string","title":"Subscriptionplan","description":"Commercial plan label for the **current** billing period. After a scheduled downgrade, this stays the higher plan until `pendingPlanChange.effectiveAt`; use `pendingPlanChange` for the next plan.","default":"BI Jedi Free"},"subscriptionPlanId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subscriptionplanid","description":"Internal catalog plan id (`spl_…`) stored when the subscription was activated; null if unknown."},"subscriptionPlanCatalog":{"anyOf":[{"$ref":"#/components/schemas/SubscriptionPlanOut"},{"type":"null"}],"description":"Full catalog snapshot for the active plan when a matching `subscription_plans` row exists."},"subscriptionStatus":{"type":"string","title":"Subscriptionstatus","description":"Billing status for this workspace subscription.","default":"active"},"priceMonthly":{"type":"string","title":"Pricemonthly","description":"Formatted recurring price for the **current** period. If `pendingPlanChange` is set, the lower price applies from `effectiveAt` (usually aligned with `nextRenewal`).","default":"€ 0,00"},"nextRenewal":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nextrenewal","description":"Next renewal date label when known."},"stripeSubscriptionId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stripesubscriptionid","description":"Stripe `sub_…` id when subscribed."},"subscriptionRecordCreatedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Subscriptionrecordcreatedat","description":"When the local subscriptions row was created."},"activatedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Activatedat","description":"First paid checkout completion or subscription row / business creation time."},"totalHistoricalPaid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Totalhistoricalpaid","description":"Human-readable sum of paid Stripe invoices for this subscription when available."},"totalHistoricalPaidMinorUnits":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Totalhistoricalpaidminorunits","description":"Same total in minor units (e.g. cents) when known."},"paymentMethod":{"anyOf":[{"$ref":"#/components/schemas/BusinessPaymentMethodOut"},{"type":"null"}],"description":"Masked payment method for this workspace when stored."},"tokensUsed":{"type":"integer","title":"Tokensused","description":"LLM tokens consumed in the current billing period (same window as GET …/ai-token-usage).","default":0},"tokensAvailable":{"type":"integer","title":"Tokensavailable","description":"Remaining LLM tokens before new chat requests are rejected (same period as tokensUsed).","default":0},"tokenPeriodStart":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Tokenperiodstart","description":"Start of the current billing period for token quota (UTC); resets usage at renewal."},"tokenPeriodEnd":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Tokenperiodend","description":"End of the current billing period (exclusive, UTC)."},"monthlyTokenQuota":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Monthlytokenquota","description":"Included LLM tokens for the current billing period."},"requestCountPeriod":{"type":"integer","title":"Requestcountperiod","description":"AI chat requests in the current billing period.","default":0},"tokensPerRequestPeriod":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Tokensperrequestperiod","description":"Average tokens per AI request in the current billing period."},"tokensUsedLifetime":{"type":"integer","title":"Tokensusedlifetime","description":"Sum of LLM tokens consumed across all billing periods.","default":0},"aiRequestCountLifetime":{"type":"integer","title":"Airequestcountlifetime","description":"Total assistant replies (AI requests) since workspace creation.","default":0},"tokensPerRequestLifetime":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Tokensperrequestlifetime","description":"Average tokens per AI request (lifetime), when request count > 0."},"usersUsed":{"type":"integer","minimum":1,"title":"Usersused","description":"Workspace seats in use: 1 owner plus invited members (same cap as plan `maxIncludedUsers`).","default":1},"pendingPlanChange":{"anyOf":[{"$ref":"#/components/schemas/PendingPlanChangeOut"},{"type":"null"}],"description":"When set, a cheaper plan is scheduled from `effectiveAt` (next period); `subscriptionPlan` / `priceMonthly` remain the current period until then."}},"type":"object","required":["id","name","description","sector","website","status","rag_rules","createdAt"],"title":"BusinessOut","example":{"activatedAt":"2026-04-18T10:05:00Z","aiRequestCountLifetime":380,"createdAt":"2026-03-31T10:00:00Z","description":"Sample business description","id":"biz_123","isActiveContext":true,"monthlyTokenQuota":100000,"name":"BI Jedi Demo","nextRenewal":"2026-05-18","paymentMethod":{"brand":"visa","last4":"4242","type":"card"},"priceMonthly":"€ 15,00","rag_rules":"","requestCountPeriod":42,"sector":"Retail","status":"active","stripeSubscriptionId":"sub_xxx","subscriptionPlan":"BI Jedi Pro","subscriptionPlanId":"spl_abc123","subscriptionRecordCreatedAt":"2026-04-18T10:00:00Z","subscriptionStatus":"active","tokenPeriodEnd":"2026-05-01T00:00:00Z","tokenPeriodStart":"2026-04-01T00:00:00Z","tokensAvailable":88000,"tokensPerRequestLifetime":1184.2,"tokensUsed":12000,"tokensUsedLifetime":450000,"totalHistoricalPaid":"€ 15,00","totalHistoricalPaidMinorUnits":1500,"usersUsed":3,"website":"https://example.com","workspaceRole":"owner"}},"BusinessPaymentMethodOut":{"properties":{"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type","description":"Instrument type, e.g. card."},"last4":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last4","description":"Last four digits when applicable."},"brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand","description":"Card brand or network."}},"type":"object","title":"BusinessPaymentMethodOut","description":"Masked card / payment summary stored on the subscription row for this workspace."},"BusinessUpdate":{"properties":{"name":{"type":"string","maxLength":100,"title":"Name","description":"Business display name (max 100 characters)."},"description":{"type":"string","title":"Description","description":"Free-text description shown in profile and prompts."},"sector":{"type":"string","title":"Sector","description":"Sector key from GET /api/sectors (typically English label value)."},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website","description":"Public website URL, if any."},"rag_rules":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rag Rules","description":"Optional rules text injected into RAG / AI context for this business.","default":""}},"type":"object","required":["name","description","sector"],"title":"BusinessUpdate","example":{"description":"Sample business description","name":"BI Jedi Demo","rag_rules":"","sector":"Retail","website":"https://example.com"}},"ChangeLanguageRequest":{"properties":{"lang":{"type":"string","maxLength":5,"minLength":2,"title":"Lang","description":"New UI locale code (e.g. en, it, es)."}},"type":"object","required":["lang"],"title":"ChangeLanguageRequest","example":{"lang":"en"}},"ChangePasswordRequest":{"properties":{"currentPassword":{"type":"string","title":"Currentpassword","description":"Existing password for verification."},"newPassword":{"type":"string","minLength":6,"title":"Newpassword","description":"Replacement password (minimum 6 characters)."}},"type":"object","required":["currentPassword","newPassword"],"title":"ChangePasswordRequest","example":{"currentPassword":"oldPass123","newPassword":"newPass123"}},"ChatFull":{"properties":{"id":{"type":"string","title":"Id","description":"Chat id."},"title":{"type":"string","title":"Title","description":"Conversation title."},"createdAt":{"type":"string","format":"date-time","title":"Createdat","description":"Created at (UTC)."},"messages":{"items":{"$ref":"#/components/schemas/MessageOut"},"type":"array","title":"Messages","description":"Messages in chronological order."}},"type":"object","required":["id","title","createdAt","messages"],"title":"ChatFull"},"ChatListItem":{"properties":{"id":{"type":"string","title":"Id","description":"Chat id."},"title":{"type":"string","title":"Title","description":"Conversation title."},"createdAt":{"type":"string","format":"date-time","title":"Createdat","description":"Created at (UTC)."},"updatedAt":{"type":"string","format":"date-time","title":"Updatedat","description":"Last activity (UTC)."}},"type":"object","required":["id","title","createdAt","updatedAt"],"title":"ChatListItem","example":{"createdAt":"2026-03-31T10:00:00Z","id":"c_123","title":"Q1 sales analysis","updatedAt":"2026-03-31T10:05:00Z"}},"ChatPatch":{"properties":{"title":{"type":"string","title":"Title","description":"New conversation title."}},"type":"object","required":["title"],"title":"ChatPatch","example":{"title":"Q1 sales analysis"}},"ChatTtsRequest":{"properties":{"text":{"type":"string","maxLength":4096,"minLength":1,"title":"Text","description":"Plain text to synthesize (markdown should be stripped client-side)."},"lang":{"anyOf":[{"type":"string","maxLength":8},{"type":"null"}],"title":"Lang","description":"UI locale hint for voice selection (e.g. it, en)."}},"type":"object","required":["text"],"title":"ChatTtsRequest","example":{"lang":"it","text":"Ecco l'analisi dei dati."}},"ColumnConfig":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id","description":"Stable id for UI bindings (optional)."},"displayName":{"type":"string","title":"Displayname","description":"Header label for grids and charts."},"formatType":{"type":"string","title":"Formattype","description":"Formatter key, e.g. text, MonetaryWithCents, NumberWithThousandsSep.","default":"text"},"symbol":{"type":"string","title":"Symbol","description":"Currency or unit symbol shown with the value.","default":""}},"type":"object","required":["displayName"],"title":"ColumnConfig","description":"Format config for a single result column.","example":{"displayName":"Revenue","formatType":"MonetaryWithCents","id":"col_1774971949654_hwxrw","symbol":"€"}},"ColumnOut":{"properties":{"name":{"type":"string","title":"Name","description":"Physical column name in the database."},"type":{"type":"string","title":"Type","description":"Database-reported type name."},"alias":{"type":"string","title":"Alias","description":"User-facing alias for UI and documentation."},"desc":{"type":"string","title":"Desc","description":"User-authored column description."}},"type":"object","required":["name","type","alias","desc"],"title":"ColumnOut"},"ColumnPatch":{"properties":{"alias":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Alias","description":"New display alias for the column."},"desc":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Desc","description":"New description text."}},"type":"object","title":"ColumnPatch"},"DirectSourceActivateRequest":{"properties":{"sourceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourceid","description":"Direct source to activate; required if multiple direct sources exist."},"rebindWarehouseQueries":{"type":"boolean","title":"Rebindwarehousequeries","description":"When true, move saved queries from warehouse sources onto this direct source.","default":false}},"type":"object","title":"DirectSourceActivateRequest","example":{"rebindWarehouseQueries":true,"sourceId":"src_direct_123"}},"DirectSourceActivateResponse":{"properties":{"source":{"$ref":"#/components/schemas/SourceOut","description":"The activated direct source with current metadata."},"reboundQueriesCount":{"type":"integer","title":"Reboundqueriescount","description":"Number of saved queries rebound when rebindWarehouseQueries was true.","default":0}},"type":"object","required":["source"],"title":"DirectSourceActivateResponse","example":{"reboundQueriesCount":12,"source":{"dbname":"erp","host":"db.example.com","id":"src_direct_123","isDefaultForQueries":true,"mode":"direct","name":"ERP Production","port":5432,"role":"operational","status":"connected","tables":[],"type":"PostgreSQL","user":"readonly_user","version":"15"}}},"FileImportUploadResponse":{"properties":{"importSource":{"$ref":"#/components/schemas/ImportSourceOut","description":"Import source created from the uploaded file."}},"type":"object","required":["importSource"],"title":"FileImportUploadResponse","example":{"importSource":{"config":{},"createdAt":"2026-03-31T10:00:00Z","fileName":"movements_march.xlsx","fileType":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","id":"imp_src_123","kind":"excel","name":"movements_march.xlsx","updatedAt":"2026-03-31T10:00:00Z"}}},"ForgotPasswordRequest":{"properties":{"username":{"type":"string","title":"Username","description":"Account username."},"email":{"type":"string","title":"Email","description":"Email that matches the account."},"newPassword":{"type":"string","minLength":6,"title":"Newpassword","description":"New password after OTP verification."},"otp":{"type":"string","maxLength":6,"minLength":6,"title":"Otp","description":"Password-reset code from email."}},"type":"object","required":["username","email","newPassword","otp"],"title":"ForgotPasswordRequest","example":{"email":"john.smith@example.com","newPassword":"newpassword123","otp":"Aa1B2c","username":"j.smith"}},"GoogleLoginRequest":{"properties":{"idToken":{"type":"string","title":"Idtoken","description":"Google Sign-In ID token (JWT) from the client SDK."}},"type":"object","required":["idToken"],"title":"GoogleLoginRequest","example":{"idToken":"eyJhbGciOiJSUzI1NiIsImtpZCI6Ij..."}},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ImportJobCreate":{"properties":{"importSourceId":{"type":"string","title":"Importsourceid","description":"ImportSource to read data from."},"targetSourceId":{"type":"string","title":"Targetsourceid","description":"Warehouse Source id to write into."},"targetTable":{"type":"string","title":"Targettable","description":"Destination table name in the warehouse schema."},"sourceTable":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourcetable","description":"Source table name for db imports."},"sourceSql":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourcesql","description":"Alternative custom SELECT for db imports."},"writeMode":{"type":"string","title":"Writemode","description":"How writes are applied, e.g. replace or append.","default":"replace"},"active":{"type":"boolean","title":"Active","description":"Whether scheduled runs are enabled.","default":true},"scheduleType":{"type":"string","title":"Scheduletype","description":"manual, interval, or cron-driven.","default":"manual"},"intervalMinutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Intervalminutes","description":"Repeat interval when scheduleType is interval."},"cronExpression":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cronexpression","description":"Cron string when scheduleType is cron."},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone","description":"IANA timezone for cron scheduling."}},"type":"object","required":["importSourceId","targetSourceId","targetTable"],"title":"ImportJobCreate","example":{"active":true,"importSourceId":"imp_src_123","intervalMinutes":60,"scheduleType":"interval","sourceTable":"movements","targetSourceId":"src_wh_123","targetTable":"sales_by_shop","timezone":"UTC","writeMode":"replace"}},"ImportJobOut":{"properties":{"id":{"type":"string","title":"Id","description":"Import job id."},"importSourceId":{"type":"string","title":"Importsourceid","description":"Source id for inbound data."},"targetSourceId":{"type":"string","title":"Targetsourceid","description":"Warehouse source id."},"targetTable":{"type":"string","title":"Targettable","description":"Target table name."},"sourceTable":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourcetable","description":"Upstream table when applicable."},"sourceSql":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourcesql","description":"Custom SQL when applicable."},"writeMode":{"type":"string","title":"Writemode","description":"Write strategy."},"active":{"type":"boolean","title":"Active","description":"Scheduler active flag."},"scheduleType":{"type":"string","title":"Scheduletype","description":"Scheduling mode."},"intervalMinutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Intervalminutes","description":"Interval in minutes."},"cronExpression":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cronexpression","description":"Cron expression."},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone","description":"Schedule timezone."},"lastRunAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Lastrunat","description":"Last execution start."},"nextRunAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Nextrunat","description":"Next scheduled run."},"lastStatus":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Laststatus","description":"Last run status summary."},"lastError":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lasterror","description":"Last error message if failed."},"isRunning":{"type":"boolean","title":"Isrunning","description":"Whether a run is in progress."},"createdAt":{"type":"string","format":"date-time","title":"Createdat","description":"Created at (UTC)."},"updatedAt":{"type":"string","format":"date-time","title":"Updatedat","description":"Updated at (UTC)."}},"type":"object","required":["id","importSourceId","targetSourceId","targetTable","writeMode","active","scheduleType","isRunning","createdAt","updatedAt"],"title":"ImportJobOut","example":{"active":true,"createdAt":"2026-03-31T10:00:00Z","id":"imp_job_123","importSourceId":"imp_src_123","intervalMinutes":60,"isRunning":false,"nextRunAt":"2026-03-31T11:00:00Z","scheduleType":"interval","sourceTable":"movements","targetSourceId":"src_wh_123","targetTable":"sales_by_shop","timezone":"UTC","updatedAt":"2026-03-31T10:00:00Z","writeMode":"replace"}},"ImportJobRunResponse":{"properties":{"run":{"$ref":"#/components/schemas/ImportRunOut","description":"Record for the import execution just triggered."}},"type":"object","required":["run"],"title":"ImportJobRunResponse","example":{"run":{"finishedAt":"2026-03-31T10:01:05Z","id":"imp_run_123","importJobId":"imp_job_123","message":"Import completed successfully","rowsImported":2388,"startedAt":"2026-03-31T10:00:00Z","status":"success"}}},"ImportJobUpdate":{"properties":{"importSourceId":{"type":"string","title":"Importsourceid","description":"ImportSource to read data from."},"targetSourceId":{"type":"string","title":"Targetsourceid","description":"Warehouse Source id to write into."},"targetTable":{"type":"string","title":"Targettable","description":"Destination table name in the warehouse schema."},"sourceTable":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourcetable","description":"Source table name for db imports."},"sourceSql":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourcesql","description":"Alternative custom SELECT for db imports."},"writeMode":{"type":"string","title":"Writemode","description":"How writes are applied, e.g. replace or append.","default":"replace"},"active":{"type":"boolean","title":"Active","description":"Whether scheduled runs are enabled.","default":true},"scheduleType":{"type":"string","title":"Scheduletype","description":"manual, interval, or cron-driven.","default":"manual"},"intervalMinutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Intervalminutes","description":"Repeat interval when scheduleType is interval."},"cronExpression":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cronexpression","description":"Cron string when scheduleType is cron."},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone","description":"IANA timezone for cron scheduling."}},"type":"object","required":["importSourceId","targetSourceId","targetTable"],"title":"ImportJobUpdate","example":{"active":true,"importSourceId":"imp_src_123","intervalMinutes":60,"scheduleType":"interval","sourceTable":"movements","targetSourceId":"src_wh_123","targetTable":"sales_by_shop","timezone":"UTC","writeMode":"replace"}},"ImportLatestSuccessOut":{"properties":{"lastSuccessfulImportFinishedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Lastsuccessfulimportfinishedat","description":"Most recent `finished_at` of a successful import run in this workspace."}},"type":"object","title":"ImportLatestSuccessOut"},"ImportRunOut":{"properties":{"id":{"type":"string","title":"Id","description":"Run id."},"importJobId":{"type":"string","title":"Importjobid","description":"Parent import job id."},"status":{"type":"string","title":"Status","description":"success, error, running, etc."},"rowsImported":{"type":"integer","title":"Rowsimported","description":"Rows written in this run."},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message","description":"Human-readable summary."},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error","description":"Error detail when status is failed."},"startedAt":{"type":"string","format":"date-time","title":"Startedat","description":"Run start (UTC)."},"finishedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Finishedat","description":"Run completion (UTC)."}},"type":"object","required":["id","importJobId","status","rowsImported","startedAt"],"title":"ImportRunOut","example":{"finishedAt":"2026-03-31T10:01:05Z","id":"imp_run_123","importJobId":"imp_job_123","message":"Import completed successfully","rowsImported":2388,"startedAt":"2026-03-31T10:00:00Z","status":"success"}},"ImportSourceCreate":{"properties":{"name":{"type":"string","title":"Name","description":"Label for this import origin."},"kind":{"type":"string","title":"Kind","description":"db, csv, excel, ftp, or sftp."},"sourceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourceid","description":"For kind=db, the operational Source id to read from."},"config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Config","description":"Remote connection and path options for ftp/sftp; normalized server-side."}},"type":"object","required":["name","kind"],"title":"ImportSourceCreate","example":{"config":{"authType":"password","filePattern":"*.csv","host":"sftp.example.com","password":"secret","port":22,"readMode":"all_matching","remotePath":"/exports/nightly","username":"demo_user"},"kind":"sftp","name":"SFTP Nightly Import"}},"ImportSourceOut":{"properties":{"id":{"type":"string","title":"Id","description":"Import source id."},"name":{"type":"string","title":"Name","description":"Display name."},"kind":{"type":"string","title":"Kind","description":"db, csv, excel, ftp, or sftp."},"sourceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourceid","description":"Linked operational source for db imports."},"fileName":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename","description":"Uploaded file name when applicable."},"fileType":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filetype","description":"MIME type for uploads."},"config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Config","description":"Sanitized config; secrets redacted."},"createdAt":{"type":"string","format":"date-time","title":"Createdat","description":"Created at (UTC)."},"updatedAt":{"type":"string","format":"date-time","title":"Updatedat","description":"Updated at (UTC)."}},"type":"object","required":["id","name","kind","createdAt","updatedAt"],"title":"ImportSourceOut","example":{"config":{"authType":"password","filePattern":"*.csv","host":"sftp.example.com","password":"***","port":22,"readMode":"all_matching","remotePath":"/exports/nightly","username":"demo_user"},"createdAt":"2026-03-31T10:00:00Z","id":"imp_src_123","kind":"sftp","name":"SFTP Nightly Import","updatedAt":"2026-03-31T10:00:00Z"}},"ImportSourceTestRequest":{"properties":{"kind":{"type":"string","title":"Kind","description":"ftp or sftp."},"config":{"additionalProperties":true,"type":"object","title":"Config","description":"Connection parameters to validate before saving."}},"type":"object","required":["kind","config"],"title":"ImportSourceTestRequest","examples":[{"summary":"SFTP password auth","value":{"config":{"authType":"password","filePattern":"*.csv","host":"sftp.example.com","password":"secret","port":22,"readMode":"all_matching","remotePath":"/exports/nightly","username":"demo_user"},"kind":"sftp"}},{"summary":"SFTP private key auth","value":{"config":{"authType":"privateKey","fileName":"sales.csv","host":"sftp.example.com","port":22,"privateKey":"-----BEGIN OPENSSH PRIVATE KEY-----\\n...\\n-----END OPENSSH PRIVATE KEY-----","readMode":"single","remotePath":"/exports/nightly","username":"demo_user"},"kind":"sftp"}}]},"InvoiceOut":{"properties":{"id":{"type":"string","title":"Id","description":"Invoice id."},"businessId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Businessid","description":"Workspace / business this charge belongs to (`biz_…`) when linked from Stripe."},"businessName":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Businessname","description":"Display name of the linked workspace when `businessId` is set and the business exists."},"date":{"type":"string","title":"Date","description":"Invoice date (ISO or display string)."},"amount":{"type":"string","title":"Amount","description":"Formatted currency amount."},"status":{"type":"string","title":"Status","description":"paid, open, etc."},"invoicePdf":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Invoicepdf","description":"Stripe `invoice_pdf` URL (direct PDF) when synced from webhooks."},"hostedInvoiceUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hostedinvoiceurl","description":"Stripe hosted invoice page URL when synced from webhooks."},"pdfUrl":{"type":"string","title":"Pdfurl","description":"Best URL for opening the invoice: direct PDF when available, else hosted page, else local PDF path."}},"type":"object","required":["id","date","amount","status","pdfUrl"],"title":"InvoiceOut","example":{"amount":"€19.99","businessId":"biz_abc123","businessName":"Acme Corp","date":"2026-03-01","hostedInvoiceUrl":"https://invoice.stripe.com/i/acct_xxx/test_xxx","id":"inv_123","invoicePdf":"https://pay.stripe.com/invoice/acct_xxx/xxx/pdf?s=ap","pdfUrl":"https://pay.stripe.com/invoice/acct_xxx/xxx/pdf?s=ap","status":"paid"}},"LayoutSave":{"properties":{"widgets":{"items":{"$ref":"#/components/schemas/WidgetLayoutItem"},"type":"array","title":"Widgets","description":"Full widget set; omitted ids are deleted, existing ids updated, new ids inserted."}},"type":"object","required":["widgets"],"title":"LayoutSave","example":{"widgets":[{"cardWidth":"half","gridPos":{"col":0,"row":0},"id":"w_123","labelColumn":"Store","queryId":"q_123","settings":{"barOrientation":"vertical"},"showLegend":true,"showValues":false,"title":"Sales by store","type":"bar","valueColumns":["Revenue","Movements"]}]}},"LoginRequest":{"properties":{"username":{"type":"string","title":"Username","description":"User identifier used at registration (often equal to email)."},"password":{"type":"string","title":"Password","description":"Account password."}},"type":"object","required":["username","password"],"title":"LoginRequest","example":{"password":"password123","username":"demo@bijedi.ai"}},"LoginResponse":{"properties":{"token":{"type":"string","title":"Token","description":"JWT access token. Send as Authorization: Bearer <token>."},"refreshToken":{"type":"string","title":"Refreshtoken","description":"Opaque refresh token for POST /api/auth/refresh."},"user":{"$ref":"#/components/schemas/UserBrief","description":"Authenticated user profile."}},"type":"object","required":["token","refreshToken","user"],"title":"LoginResponse","example":{"refreshToken":"rt_xxx","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...","user":{"email":"demo@bijedi.ai","emailVerified":true,"explorerTrialConsumed":false,"googleLinked":false,"id":"usr_123","isActivated":true,"lang":"en","name":"Demo User","role":"ADMIN","username":"demo@bijedi.ai"}}},"MessageOut":{"properties":{"id":{"type":"string","title":"Id","description":"Message id."},"role":{"type":"string","title":"Role","description":"user or assistant."},"content":{"type":"string","title":"Content","description":"Message body (markdown or plain text)."},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata","description":"Assistant extras, e.g. referenced queryId."},"createdAt":{"type":"string","format":"date-time","title":"Createdat","description":"Created at (UTC)."}},"type":"object","required":["id","role","content","createdAt"],"title":"MessageOut","example":{"content":"Here is the analysis...","createdAt":"2026-03-31T10:05:00Z","id":"msg_123","metadata":{"queryId":"q_123"},"role":"assistant"}},"OkResponse":{"properties":{"ok":{"type":"boolean","title":"Ok","description":"Operation success flag.","default":true}},"type":"object","title":"OkResponse"},"PaymentMethodOut":{"properties":{"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type","description":"Payment instrument type, e.g. card."},"last4":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last4","description":"Last four digits when applicable."},"brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand","description":"Card brand or network name."}},"type":"object","title":"PaymentMethodOut"},"PendingPlanChangeOut":{"properties":{"subscriptionPlanId":{"type":"string","title":"Subscriptionplanid","description":"Catalog plan id that will apply after renewal."},"subscriptionPlanCatalog":{"anyOf":[{"$ref":"#/components/schemas/SubscriptionPlanOut"},{"type":"null"}],"description":"Snapshot of the pending plan when present in the catalog."},"effectiveAt":{"type":"string","format":"date-time","title":"Effectiveat","description":"UTC time when the downgrade takes effect (current period end)."}},"type":"object","required":["subscriptionPlanId","effectiveAt"],"title":"PendingPlanChangeOut","description":"Downgrade scheduled for the next Stripe billing period (Subscription Schedule)."},"PublicMessageResponse":{"properties":{"ok":{"type":"boolean","title":"Ok","description":"Always true on success; avoids leaking account existence.","default":true},"message":{"type":"string","title":"Message","description":"Generic status text for the client."}},"type":"object","required":["message"],"title":"PublicMessageResponse","example":{"message":"If username and email match, an OTP has been sent.","ok":true}},"PublicReportBundleOut":{"properties":{"report":{"$ref":"#/components/schemas/ReportFull"},"queryColumnsConfigById":{"additionalProperties":true,"type":"object","title":"Querycolumnsconfigbyid","description":"Map of saved-query id → columnsConfig (same shape as SavedQuery.columnsConfig)."}},"type":"object","required":["report"],"title":"PublicReportBundleOut","description":"Public (unauthenticated) dashboard payload: layout plus per-query column format config for charts."},"QueryAssistRequest":{"properties":{"message":{"type":"string","title":"Message","description":"Natural-language request describing the query to generate or change."},"currentSql":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currentsql","description":"SQL currently in the editor; when present the assistant edits it instead of starting fresh."},"sourceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourceid","description":"Source whose schema/dialect to target; default business source used when omitted."}},"type":"object","required":["message"],"title":"QueryAssistRequest","example":{"message":"vendite mensili per la campagna 62, con etichetta mese/anno"}},"QueryAssistResult":{"properties":{"sql":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sql","description":"Generated/updated read-only SQL, or null if none was produced."},"explanation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Explanation","description":"Plain-language description of what the query returns."},"message":{"type":"string","title":"Message","description":"Full assistant reply (markdown); may contain a clarifying question when no SQL is produced."},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata","description":"Model/timing/token metadata."}},"type":"object","required":["message"],"title":"QueryAssistResult","example":{"explanation":"Conta i movimenti per ogni mese della campagna 62, ordinati per anno e mese.","message":"```sql\n...\n```\nConta i movimenti...","metadata":{"model":"gpt-4o","tokensUsed":412},"sql":"SELECT EXTRACT(YEAR FROM date_time) AS anno, EXTRACT(MONTH FROM date_time) AS mese, COUNT(*) AS movimenti FROM movements WHERE campaign_id = 62 GROUP BY EXTRACT(YEAR FROM date_time), EXTRACT(MONTH FROM date_time) ORDER BY anno, mese"}},"QueryCreate":{"properties":{"name":{"type":"string","title":"Name","description":"Human-readable query title."},"sql":{"type":"string","title":"Sql","description":"SQL executed against the resolved source (read-only expectations)."},"sourceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourceid","description":"Explicit source id; default business source used when omitted."},"columnsConfig":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/ColumnConfig"},"type":"object"},{"type":"null"}],"title":"Columnsconfig","description":"Column formatting. Keys = SQL column names. Only listed columns appear in results.","example":{"movements_count":{"displayName":"Movements","formatType":"NumberWithThousandsSep","symbol":""},"shop_name":{"displayName":"Store","formatType":"text","symbol":""},"total_sales":{"displayName":"Revenue","formatType":"MonetaryWithCents","symbol":"€"}}},"sourceChat":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourcechat","description":"Optional provenance id or label linking this query to a chat-generated suggestion."},"builderConfig":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Builderconfig","description":"Optional template wizard state: { templateId, params } for re-editing generated SQL."}},"type":"object","required":["name","sql"],"title":"QueryCreate","example":{"columnsConfig":{"movements_count":{"displayName":"Movements","formatType":"NumberWithThousandsSep","id":"col_3","symbol":""},"shop_name":{"displayName":"Store","formatType":"text","id":"col_1","symbol":""},"total_sales":{"displayName":"Revenue","formatType":"MonetaryWithCents","id":"col_2","symbol":"€"}},"name":"Sales by store","sourceId":"src_warehouse_123","sql":"SELECT shop_name, total_sales, movements_count FROM sales_by_shop"}},"QueryExecuteRequest":{"properties":{"sourceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourceid","description":"Override execution source for this run only; default is the query's source."},"limit":{"type":"integer","title":"Limit","description":"Maximum rows to return (server-enforced cap).","default":100},"rawResult":{"type":"boolean","title":"Rawresult","description":"If true, return SQL column names and raw cell values (no columnsConfig formatting).","default":false}},"type":"object","title":"QueryExecuteRequest","example":{"limit":100,"rawResult":false,"sourceId":"src_123"}},"QueryExecuteResult":{"properties":{"columns":{"items":{"type":"string"},"type":"array","title":"Columns","description":"Column names in result order."},"rows":{"items":{"items":{},"type":"array"},"type":"array","title":"Rows","description":"Result tuples aligned with columns."},"rowCount":{"type":"integer","title":"Rowcount","description":"Number of rows returned."},"executionTimeMs":{"type":"integer","title":"Executiontimems","description":"Server-side execution time in milliseconds."}},"type":"object","required":["columns","rows","rowCount","executionTimeMs"],"title":"QueryExecuteResult","example":{"columns":["Store","Revenue","Movements"],"executionTimeMs":123,"rowCount":2,"rows":[["Demo Store","€1,933,200.66","38,845"],["MediaWorld","€1,852,855.22","36,357"]]}},"QueryOut":{"properties":{"id":{"type":"string","title":"Id","description":"Saved query id."},"name":{"type":"string","title":"Name","description":"Query title."},"sql":{"type":"string","title":"Sql","description":"Stored SQL."},"sourceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourceid","description":"Bound data source id."},"columnsConfig":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/ColumnConfig"},"type":"object"},{"type":"null"}],"title":"Columnsconfig","description":"Column format map."},"builderConfig":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Builderconfig","description":"Template wizard state when applicable."},"createdAt":{"type":"string","format":"date-time","title":"Createdat","description":"Created at (UTC)."},"updatedAt":{"type":"string","format":"date-time","title":"Updatedat","description":"Last update (UTC)."}},"type":"object","required":["id","name","sql","createdAt","updatedAt"],"title":"QueryOut","example":{"columnsConfig":{"movements_count":{"displayName":"Movements","formatType":"NumberWithThousandsSep","id":"col_3","symbol":""},"shop_name":{"displayName":"Store","formatType":"text","id":"col_1","symbol":""},"total_sales":{"displayName":"Revenue","formatType":"MonetaryWithCents","id":"col_2","symbol":"€"}},"createdAt":"2026-03-31T10:00:00Z","id":"q_123","name":"Sales by store","sourceId":"src_warehouse_123","sql":"SELECT shop_name, total_sales, movements_count FROM sales_by_shop","updatedAt":"2026-03-31T10:00:00Z"}},"QueryTemplateGenerateRequest":{"properties":{"templateId":{"type":"string","title":"Templateid","description":"Template id: timeseries, top_n, category_breakdown, filtered_detail."},"params":{"additionalProperties":true,"type":"object","title":"Params","description":"Template-specific parameters."},"sourceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourceid","description":"Source whose SQL dialect to use."}},"type":"object","required":["templateId"],"title":"QueryTemplateGenerateRequest"},"QueryTemplateGenerateResult":{"properties":{"sql":{"type":"string","title":"Sql","description":"Generated read-only SQL."},"builderConfig":{"additionalProperties":true,"type":"object","title":"Builderconfig","description":"State to persist for re-opening the wizard."},"suggestedName":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Suggestedname","description":"Optional suggested query title."}},"type":"object","required":["sql","builderConfig"],"title":"QueryTemplateGenerateResult"},"QueryUpdate":{"properties":{"name":{"type":"string","title":"Name","description":"Updated query title."},"sql":{"type":"string","title":"Sql","description":"Updated SQL text."},"sourceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourceid","description":"Updated source binding when provided."},"columnsConfig":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/ColumnConfig"},"type":"object"},{"type":"null"}],"title":"Columnsconfig","description":"Column formatting. Keys = SQL column names. Only listed columns appear in results.","example":{"movements_count":{"displayName":"Movements","formatType":"NumberWithThousandsSep","symbol":""},"shop_name":{"displayName":"Store","formatType":"text","symbol":""},"total_sales":{"displayName":"Revenue","formatType":"MonetaryWithCents","symbol":"€"}}},"builderConfig":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Builderconfig","description":"Optional template wizard state for re-editing."}},"type":"object","required":["name","sql"],"title":"QueryUpdate","example":{"columnsConfig":{"movements_count":{"displayName":"Movements","formatType":"NumberWithThousandsSep","id":"col_3","symbol":""},"shop_name":{"displayName":"Store","formatType":"text","id":"col_1","symbol":""},"total_sales":{"displayName":"Revenue","formatType":"MonetaryWithCents","id":"col_2","symbol":"€"}},"name":"Sales by store (updated)","sourceId":"src_warehouse_123","sql":"SELECT shop_name, total_sales, movements_count FROM sales_by_shop"}},"QueryVisualBuilderRequest":{"properties":{"params":{"additionalProperties":true,"type":"object","title":"Params","description":"Visual builder parameters."},"sourceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourceid","description":"Source whose SQL dialect to use."}},"type":"object","title":"QueryVisualBuilderRequest"},"RefreshRequest":{"properties":{"refreshToken":{"type":"string","title":"Refreshtoken","description":"Refresh token issued by login or previous refresh."}},"type":"object","required":["refreshToken"],"title":"RefreshRequest","example":{"refreshToken":"rt_xxx"}},"RefreshResponse":{"properties":{"token":{"type":"string","title":"Token","description":"New JWT access token."},"refreshToken":{"type":"string","title":"Refreshtoken","description":"New refresh token; the old one is revoked."}},"type":"object","required":["token","refreshToken"],"title":"RefreshResponse","example":{"refreshToken":"rt_xxx","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}},"RegisterRequest":{"properties":{"name":{"type":"string","title":"Name","description":"User display name."},"username":{"type":"string","title":"Username","description":"Unique login name."},"email":{"type":"string","title":"Email","description":"Email used for activation OTP and login recovery."},"password":{"type":"string","minLength":6,"title":"Password","description":"Initial password (minimum 6 characters)."},"lang":{"type":"string","title":"Lang","description":"Preferred UI locale code stored on the user.","default":"it"}},"type":"object","required":["name","username","email","password"],"title":"RegisterRequest","example":{"email":"john.smith@example.com","lang":"en","name":"John Smith","password":"password123","username":"j.smith"}},"RegistrationResponse":{"properties":{"ok":{"type":"boolean","title":"Ok","description":"Whether the registration request was accepted.","default":true},"activationRequired":{"type":"boolean","title":"Activationrequired","description":"True until the user completes email OTP activation.","default":true},"message":{"type":"string","title":"Message","description":"Human-readable outcome for the client."},"emailSent":{"type":"boolean","title":"Emailsent","description":"False if SMTP failed after the account was created; OTP is stored and resend can be used when mail works.","default":true}},"type":"object","required":["message"],"title":"RegistrationResponse","example":{"activationRequired":true,"emailSent":true,"message":"Registration created. Activation OTP sent by email.","ok":true}},"ReportCreate":{"properties":{"name":{"type":"string","title":"Name","description":"Dashboard title."}},"type":"object","required":["name"],"title":"ReportCreate","example":{"name":"Sales dashboard"}},"ReportCreated":{"properties":{"id":{"type":"string","title":"Id","description":"New report id."},"name":{"type":"string","title":"Name","description":"Dashboard name."},"widgets":{"items":{"$ref":"#/components/schemas/WidgetOut"},"type":"array","title":"Widgets","description":"Initially empty; use layout or widget endpoints."},"createdAt":{"type":"string","format":"date-time","title":"Createdat","description":"Created at (UTC)."}},"type":"object","required":["id","name","widgets","createdAt"],"title":"ReportCreated","example":{"createdAt":"2026-03-31T10:00:00Z","id":"rep_123","name":"Sales dashboard","widgets":[]}},"ReportFull":{"properties":{"id":{"type":"string","title":"Id","description":"Report id."},"name":{"type":"string","title":"Name","description":"Dashboard name."},"widgets":{"items":{"$ref":"#/components/schemas/WidgetOut"},"type":"array","title":"Widgets","description":"Ordered widget definitions."},"settings":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Settings","description":"Dashboard options (refresh interval, etc.)."}},"type":"object","required":["id","name","widgets"],"title":"ReportFull","example":{"id":"rep_123","name":"Sales dashboard","settings":{"autoRefreshSec":60},"widgets":[]}},"ReportListItem":{"properties":{"id":{"type":"string","title":"Id","description":"Report id."},"name":{"type":"string","title":"Name","description":"Dashboard name."},"createdAt":{"type":"string","format":"date-time","title":"Createdat","description":"Created at (UTC)."},"updatedAt":{"type":"string","format":"date-time","title":"Updatedat","description":"Last update (UTC)."},"widgetCount":{"type":"integer","title":"Widgetcount","description":"Number of widgets on the dashboard."}},"type":"object","required":["id","name","createdAt","updatedAt","widgetCount"],"title":"ReportListItem","example":{"createdAt":"2026-03-31T10:00:00Z","id":"rep_123","name":"Sales dashboard","updatedAt":"2026-03-31T10:00:00Z","widgetCount":3}},"ReportPatch":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"New dashboard title."},"settings":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Settings","description":"Optional dashboard settings (merged), e.g. `autoRefreshSec` for client polling."}},"type":"object","title":"ReportPatch","example":{"name":"Sales dashboard (renamed)","settings":{"autoRefreshSec":120}}},"ReportPublicShareStatusOut":{"properties":{"active":{"type":"boolean","title":"Active","description":"Whether a non-revoked share link exists."},"token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token","description":"Raw secret token (only when active)."},"sharePath":{"type":"string","title":"Sharepath","description":"Relative path for the SPA, e.g. /share/<token> (caller prepends origin).","default":""},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Createdat","description":"When the current token was issued (UTC)."}},"type":"object","required":["active"],"title":"ReportPublicShareStatusOut"},"SectorOut":{"properties":{"en":{"type":"string","title":"En","description":"Sector label in English."},"it":{"type":"string","title":"It","description":"Sector label in Italian."},"es":{"type":"string","title":"Es","description":"Sector label in Spanish."}},"type":"object","required":["en","it","es"],"title":"SectorOut","example":{"en":"Retail","es":"Retail","it":"Retail"}},"SemanticMetricCreate":{"properties":{"title":{"type":"string","title":"Title"},"description":{"type":"string","title":"Description","default":""},"queryId":{"type":"string","title":"Queryid"},"filters":{"items":{"$ref":"#/components/schemas/SemanticMetricFilterItem"},"type":"array","title":"Filters"},"sortOrder":{"type":"integer","title":"Sortorder","default":0}},"type":"object","required":["title","queryId"],"title":"SemanticMetricCreate"},"SemanticMetricFilterItem":{"properties":{"key":{"type":"string","title":"Key","description":"Form field id sent back in `filters` when running the metric."},"column":{"type":"string","title":"Column","description":"Result column name from the underlying saved query (simple identifier)."},"label":{"type":"string","title":"Label","description":"User-visible label for the filter.","default":""},"type":{"type":"string","title":"Type","description":"Input type: `text`, `number`, `date` (equality), `select` (options list), `daterange` (preset or from/to on result column).","default":"text"},"options":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Options","description":"For type=select: [{ value, label }, ...]."},"presets":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Presets","description":"For type=daterange: allowed preset ids (last_7, last_30, last_90, month_current, ytd, custom)."}},"type":"object","required":["key","column"],"title":"SemanticMetricFilterItem"},"SemanticMetricOut":{"properties":{"id":{"type":"string","title":"Id"},"title":{"type":"string","title":"Title"},"description":{"type":"string","title":"Description"},"queryId":{"type":"string","title":"Queryid"},"queryName":{"type":"string","title":"Queryname"},"filters":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Filters"},"sortOrder":{"type":"integer","title":"Sortorder"}},"type":"object","required":["id","title","description","queryId","queryName","filters","sortOrder"],"title":"SemanticMetricOut"},"SemanticMetricRunRequest":{"properties":{"filters":{"additionalProperties":true,"type":"object","title":"Filters","description":"Values keyed by each filter's `key`."},"limit":{"type":"integer","maximum":2000,"minimum":1,"title":"Limit","default":200},"rawResult":{"type":"boolean","title":"Rawresult","description":"If true, skip saved query column formatting.","default":false}},"type":"object","title":"SemanticMetricRunRequest"},"SemanticMetricUpdate":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"queryId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Queryid"},"filters":{"anyOf":[{"items":{"$ref":"#/components/schemas/SemanticMetricFilterItem"},"type":"array"},{"type":"null"}],"title":"Filters"},"sortOrder":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sortorder"}},"type":"object","title":"SemanticMetricUpdate"},"SendActivationOtpRequest":{"properties":{"username":{"type":"string","title":"Username","description":"Username provided at registration."},"email":{"type":"string","title":"Email","description":"Email that must match the pending registration."}},"type":"object","required":["username","email"],"title":"SendActivationOtpRequest","example":{"email":"john.smith@example.com","username":"j.smith"}},"SendMessageRequest":{"properties":{"message":{"type":"string","maxLength":10000,"minLength":1,"title":"Message","description":"User prompt to the AI; max 10000 characters."}},"type":"object","required":["message"],"title":"SendMessageRequest","example":{"message":"Show me sales by store and movements."}},"SendMessageResponse":{"properties":{"response":{"type":"string","title":"Response","description":"Assistant reply text."},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata","description":"Structured hints: queries, charts, etc."},"messageId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Messageid","description":"Persisted assistant message id."},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Createdat","description":"UTC timestamp when the assistant message was stored."}},"type":"object","required":["response"],"title":"SendMessageResponse","example":{"createdAt":"2026-03-31T10:05:00Z","messageId":"msg_123","metadata":{"queryId":"q_123","tokensUsed":1200},"response":"Here is the analysis..."}},"SendOtpRequest":{"properties":{"username":{"type":"string","title":"Username","description":"Account username."},"email":{"type":"string","title":"Email","description":"Email that must match the account for OTP delivery."}},"type":"object","required":["username","email"],"title":"SendOtpRequest","example":{"email":"john.smith@example.com","username":"j.smith"}},"SourceCreate":{"properties":{"type":{"type":"string","title":"Type","description":"Database product type (e.g. PostgreSQL).","default":"PostgreSQL"},"mode":{"type":"string","title":"Mode","description":"direct = customer DB; warehouse = internal managed schema.","default":"direct"},"role":{"type":"string","title":"Role","description":"Source role hint, e.g. operational or warehouse.","default":"operational"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Friendly label; defaults from dbname when omitted."},"host":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Host","description":"Database hostname or IP."},"port":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Port","description":"TCP port; product default used when omitted."},"dbname":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dbname","description":"Database name to connect to."},"oracleIdentifierType":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oracleidentifiertype","description":"Oracle only: interpret `dbname` as `service_name` or `sid` when connecting.","default":"service_name"},"user":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User","description":"Database username."},"password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Password","description":"Database password (stored encrypted server-side)."},"isDefaultForQueries":{"type":"boolean","title":"Isdefaultforqueries","description":"If true, becomes the default execution target for new saved queries.","default":false}},"type":"object","title":"SourceCreate","example":{"dbname":"demo","host":"db.example.com","isDefaultForQueries":true,"mode":"direct","name":"ERP Production","password":"secret","port":5432,"role":"operational","type":"PostgreSQL","user":"demo_user"}},"SourceOut":{"properties":{"id":{"type":"string","title":"Id","description":"Source id."},"name":{"type":"string","title":"Name","description":"Display name."},"type":{"type":"string","title":"Type","description":"Connector type label."},"mode":{"type":"string","title":"Mode","description":"direct or warehouse.","default":"direct"},"role":{"type":"string","title":"Role","description":"operational, warehouse, etc.","default":"operational"},"version":{"type":"string","title":"Version","description":"Server version string when known."},"host":{"type":"string","title":"Host","description":"Host for direct sources; may be empty for warehouse internals."},"port":{"type":"integer","title":"Port","description":"TCP port."},"dbname":{"type":"string","title":"Dbname","description":"Database name."},"oracleIdentifierType":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oracleidentifiertype","description":"Oracle only: `service_name` or `sid` (how `dbname` is interpreted)."},"user":{"type":"string","title":"User","description":"Connection username."},"status":{"type":"string","title":"Status","description":"connected, error, etc."},"isDefaultForQueries":{"type":"boolean","title":"Isdefaultforqueries","description":"Default execution target flag.","default":false},"warehouseSchema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Warehouseschema","description":"Postgres schema name for warehouse mode."},"tables":{"items":{"$ref":"#/components/schemas/TableOut"},"type":"array","title":"Tables","description":"Cached table catalog after sync."}},"type":"object","required":["id","name","type","version","host","port","dbname","user","status","tables"],"title":"SourceOut","example":{"dbname":"demo","host":"db.example.com","id":"src_123","isDefaultForQueries":true,"mode":"direct","name":"ERP Production","port":5432,"role":"operational","status":"connected","tables":[],"type":"PostgreSQL","user":"demo_user","version":"15"}},"SourceSyncResponse":{"properties":{"tables":{"items":{"$ref":"#/components/schemas/TableOut"},"type":"array","title":"Tables","description":"Refreshed table catalog after introspection."}},"type":"object","required":["tables"],"title":"SourceSyncResponse","example":{"tables":[{"alias":"Sales","columns":[{"alias":"","desc":"","name":"shop_name","type":"VARCHAR"}],"description":"","id":"tbl_123","name":"sales","rows":"12345","visible":true}]}},"SubscriptionChangePlanRequest":{"properties":{"subscriptionPlanId":{"type":"string","title":"Subscriptionplanid","description":"Target catalog plan id (`spl_…`)."}},"type":"object","required":["subscriptionPlanId"],"title":"SubscriptionChangePlanRequest","example":{"subscriptionPlanId":"spl_abc123"}},"SubscriptionChangePlanResponse":{"properties":{"changeType":{"type":"string","title":"Changetype","description":"`upgrade` or `downgrade`."},"effective":{"type":"string","title":"Effective","description":"`immediate` (upgrade with proration) or `next_period` (scheduled downgrade)."},"plan":{"type":"string","title":"Plan","description":"Target plan display name."},"subscriptionPlanId":{"type":"string","title":"Subscriptionplanid","description":"Target catalog plan id."},"subscriptionPlanCatalog":{"$ref":"#/components/schemas/SubscriptionPlanOut","description":"Full catalog row for the target plan."},"prorationInvoiceUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prorationinvoiceurl","description":"Hosted invoice URL for the proration charge after an upgrade, when Stripe returns one."},"pendingChangeAt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pendingchangeat","description":"ISO timestamp when a scheduled downgrade applies; null for immediate upgrades."}},"type":"object","required":["changeType","effective","plan","subscriptionPlanId","subscriptionPlanCatalog"],"title":"SubscriptionChangePlanResponse"},"SubscriptionOut":{"properties":{"plan":{"type":"string","title":"Plan","description":"Commercial plan name for the **current** period; when `pendingPlanChange` is set, this remains the higher plan until `pendingPlanChange.effectiveAt`."},"subscriptionPlanId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subscriptionplanid","description":"Internal catalog plan id (`spl_…`) for the active business subscription when known."},"subscriptionPlanCatalog":{"anyOf":[{"$ref":"#/components/schemas/SubscriptionPlanOut"},{"type":"null"}],"description":"Full catalog snapshot when a matching `subscription_plans` row exists."},"status":{"type":"string","title":"Status","description":"Billing state, e.g. active."},"priceMonthly":{"type":"string","title":"Pricemonthly","description":"Formatted monthly price for the **current** period; if `pendingPlanChange` is set, the lower price applies from `effectiveAt`."},"nextRenewal":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nextrenewal","description":"Next renewal date label when scheduled."},"paymentMethod":{"anyOf":[{"$ref":"#/components/schemas/PaymentMethodOut"},{"type":"null"}],"description":"Masked payment method summary."},"pendingPlanChange":{"anyOf":[{"$ref":"#/components/schemas/PendingPlanChangeOut"},{"type":"null"}],"description":"When set, a downgrade to this plan is scheduled for the next billing period."}},"type":"object","required":["plan","status","priceMonthly"],"title":"SubscriptionOut","example":{"plan":"BI Jedi Free","priceMonthly":"€0.00","status":"active"}},"SubscriptionPlanOut":{"properties":{"id":{"type":"string","title":"Id","description":"Internal plan id (`spl_…`)."},"name":{"type":"string","title":"Name","description":"Commercial plan display name."},"priceMinorUnits":{"type":"integer","title":"Priceminorunits","description":"Stripe unit amount in minor currency units (e.g. cents)."},"currency":{"type":"string","title":"Currency","description":"ISO currency code, e.g. eur."},"priceDisplay":{"type":"string","title":"Pricedisplay","description":"Human-readable price for UI."},"billingInterval":{"type":"string","title":"Billinginterval","description":"month or year."},"stripePriceId":{"type":"string","title":"Stripepriceid","description":"Stripe Price id (`price_…`)."},"monthlyTokenQuota":{"type":"integer","title":"Monthlytokenquota","description":"Included LLM tokens per billing period for this plan (aligned with Stripe subscription period)."},"maxIncludedUsers":{"type":"integer","title":"Maxincludedusers","description":"Maximum workspace users included: 1 owner + invited members (total cap)."},"trialEligible":{"type":"boolean","title":"Trialeligible","description":"If true, this plan is used for the cardless first-workspace free trial (see POST …/start-explorer-trial).","default":false},"isActive":{"type":"boolean","title":"Isactive","description":"Whether the plan is offered in Checkout."},"sortOrder":{"type":"integer","title":"Sortorder","description":"Catalog ordering."},"createdAt":{"type":"string","format":"date-time","title":"Createdat","description":"Created at (UTC)."},"updatedAt":{"type":"string","format":"date-time","title":"Updatedat","description":"Updated at (UTC)."}},"type":"object","required":["id","name","priceMinorUnits","currency","priceDisplay","billingInterval","stripePriceId","monthlyTokenQuota","maxIncludedUsers","isActive","sortOrder","createdAt","updatedAt"],"title":"SubscriptionPlanOut","description":"Catalog plan row (same payload as `GET /api/subscription/plans`). Embedded under business and subscription responses."},"SupportMessageCreate":{"properties":{"content":{"type":"string","maxLength":10000,"minLength":1,"title":"Content","description":"Message body."}},"type":"object","required":["content"],"title":"SupportMessageCreate"},"SupportMessageOut":{"properties":{"id":{"type":"string","title":"Id"},"role":{"type":"string","title":"Role"},"content":{"type":"string","title":"Content"},"createdAt":{"type":"string","format":"date-time","title":"Createdat"}},"type":"object","required":["id","role","content","createdAt"],"title":"SupportMessageOut"},"SupportThreadOut":{"properties":{"id":{"type":"string","title":"Id"},"needsReply":{"type":"boolean","title":"Needsreply"},"createdAt":{"type":"string","format":"date-time","title":"Createdat"},"updatedAt":{"type":"string","format":"date-time","title":"Updatedat"},"messages":{"items":{"$ref":"#/components/schemas/SupportMessageOut"},"type":"array","title":"Messages"}},"type":"object","required":["id","needsReply","createdAt","updatedAt","messages"],"title":"SupportThreadOut"},"TableBulkVisibilityOut":{"properties":{"updated":{"type":"integer","title":"Updated","description":"Number of table rows updated."}},"type":"object","required":["updated"],"title":"TableBulkVisibilityOut"},"TableBulkVisibilityPatch":{"properties":{"visible":{"type":"boolean","title":"Visible","description":"Visibility flag to apply."},"table_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Table Ids","description":"Optional subset of table ids; when omitted, all tables in the source are updated."}},"type":"object","required":["visible"],"title":"TableBulkVisibilityPatch"},"TableOut":{"properties":{"id":{"type":"string","title":"Id","description":"Catalogued table id."},"name":{"type":"string","title":"Name","description":"Physical table name."},"alias":{"type":"string","title":"Alias","description":"User-facing table alias."},"description":{"type":"string","title":"Description","description":"User-authored table description."},"visible":{"type":"boolean","title":"Visible","description":"Whether the table is exposed in UI and AI tools."},"rows":{"type":"string","title":"Rows","description":"Estimated or cached row count as a string."},"columns":{"items":{"$ref":"#/components/schemas/ColumnOut"},"type":"array","title":"Columns","description":"Column metadata for this table."}},"type":"object","required":["id","name","alias","description","visible","rows","columns"],"title":"TableOut"},"TablePatch":{"properties":{"alias":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Alias","description":"New table alias."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"New table description."},"visible":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Visible","description":"Toggle visibility in catalog."}},"type":"object","title":"TablePatch"},"TablePreviewResponse":{"properties":{"columns":{"items":{"type":"string"},"type":"array","title":"Columns","description":"Column names in preview order."},"rows":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Rows","description":"Sample rows as objects keyed by column name."},"rowCount":{"type":"integer","title":"Rowcount","description":"Number of rows in this preview payload."},"orderBy":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Orderby","description":"Column used for latest-first ordering when applicable."}},"type":"object","required":["columns","rows","rowCount"],"title":"TablePreviewResponse","example":{"columns":["id","shop_id","total_money","date_time"],"orderBy":"date_time","rowCount":1,"rows":[{"date_time":"2026-04-04T09:45:00","id":15092,"shop_id":4,"total_money":"1933.20"}]}},"TestConnectionRequest":{"properties":{"type":{"type":"string","title":"Type","description":"Database product type to test."},"host":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Host","description":"Hostname or IP."},"port":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Port","description":"Port; default for product if omitted."},"dbname":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dbname","description":"Database name."},"oracleIdentifierType":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oracleidentifiertype","description":"Oracle only: `service_name` or `sid`.","default":"service_name"},"user":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User","description":"Username."},"password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Password","description":"Password for the probe connection."}},"type":"object","required":["type"],"title":"TestConnectionRequest","example":{"dbname":"demo","host":"db.example.com","password":"secret","port":5432,"type":"PostgreSQL","user":"demo_user"}},"TestConnectionResponse":{"properties":{"ok":{"type":"boolean","title":"Ok","description":"Whether the connection probe succeeded."},"message":{"type":"string","title":"Message","description":"Human-readable success or error detail."}},"type":"object","required":["ok","message"],"title":"TestConnectionResponse","example":{"message":"Connected","ok":true}},"UserBrief":{"properties":{"id":{"type":"string","title":"Id","description":"Stable user id."},"name":{"type":"string","title":"Name","description":"Display name."},"username":{"type":"string","title":"Username","description":"Unique login name."},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"Email address when set."},"role":{"type":"string","title":"Role","description":"Access role, e.g. USER or ADMIN."},"isActivated":{"type":"boolean","title":"Isactivated","description":"Whether the account can sign in.","default":true},"emailVerified":{"type":"boolean","title":"Emailverified","description":"Whether email ownership was confirmed.","default":false},"googleLinked":{"type":"boolean","title":"Googlelinked","description":"Whether a Google account is linked.","default":false},"lang":{"type":"string","title":"Lang","description":"Preferred UI locale code (e.g. en, it)."},"explorerTrialConsumed":{"type":"boolean","title":"Explorertrialconsumed","description":"True after the one-time catalog free trial was started or a second workspace was created.","default":false}},"type":"object","required":["id","name","username","role","lang"],"title":"UserBrief"},"UserPatch":{"properties":{"lang":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lang","description":"Update preferred UI locale."},"activeBusinessId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Activebusinessid","description":"Set which business context is active."}},"type":"object","title":"UserPatch","example":{"activeBusinessId":"biz_123","lang":"en"}},"UserProfile":{"properties":{"id":{"type":"string","title":"Id","description":"Stable user id."},"name":{"type":"string","title":"Name","description":"Display name."},"username":{"type":"string","title":"Username","description":"Unique login name."},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"Email address when set."},"role":{"type":"string","title":"Role","description":"Access role, e.g. USER or ADMIN."},"isActivated":{"type":"boolean","title":"Isactivated","description":"Whether the account can sign in.","default":true},"emailVerified":{"type":"boolean","title":"Emailverified","description":"Whether email ownership was confirmed.","default":false},"googleLinked":{"type":"boolean","title":"Googlelinked","description":"Whether a Google account is linked.","default":false},"lang":{"type":"string","title":"Lang","description":"Preferred UI locale code (e.g. en, it)."},"explorerTrialConsumed":{"type":"boolean","title":"Explorertrialconsumed","description":"True after the one-time catalog free trial was started or a second workspace was created.","default":false},"activeBusinessId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Activebusinessid","description":"Currently selected business id for multi-tenant UI, or null if none."}},"type":"object","required":["id","name","username","role","lang"],"title":"UserProfile"},"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"},"WarehouseSourceCreate":{"properties":{"name":{"type":"string","title":"Name","description":"Display name for the warehouse source.","default":"Datawarehouse"},"isDefaultForQueries":{"type":"boolean","title":"Isdefaultforqueries","description":"Whether this warehouse should be the default query target.","default":false},"rebindDirectQueries":{"type":"boolean","title":"Rebinddirectqueries","description":"When true, re-point saved queries from direct sources to this warehouse.","default":false}},"type":"object","title":"WarehouseSourceCreate","example":{"isDefaultForQueries":true,"name":"Datawarehouse","rebindDirectQueries":true}},"WidgetCreate":{"properties":{"title":{"type":"string","title":"Title","description":"Widget title."},"type":{"type":"string","title":"Type","description":"Visualization type."},"queryId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Queryid","description":"Saved query to bind."},"labelColumn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Labelcolumn","description":"Label column name."},"valueColumns":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Valuecolumns","description":"Numeric/value column names."},"settings":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Settings","description":"Visualization settings."},"cardWidth":{"type":"string","title":"Cardwidth","description":"Layout width token.","default":"quarter"},"showLegend":{"type":"boolean","title":"Showlegend","description":"Show legend.","default":false},"showValues":{"type":"boolean","title":"Showvalues","description":"Show data labels.","default":false},"gridPos":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Gridpos","description":"Grid position {row, col}."}},"type":"object","required":["title","type"],"title":"WidgetCreate","example":{"cardWidth":"half","gridPos":{"col":0,"row":0},"labelColumn":"Store","queryId":"q_123","settings":{"barOrientation":"vertical","curveType":"monotone"},"showLegend":true,"showValues":false,"title":"Sales by store","type":"bar","valueColumns":["Revenue","Movements"]}},"WidgetDataResponse":{"properties":{"value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value","description":"Formatted KPI value."},"delta":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Delta","description":"Change vs baseline, e.g. +12.5%."},"isPositive":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ispositive","description":"Semantic direction for delta coloring."},"data":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Data","description":"Row objects keyed by column display names for charts/tables."},"fetchedAt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fetchedat","description":"ISO-8601 timestamp when this payload was computed."},"alertBreaches":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Alertbreaches","description":"KPI threshold rules from widget settings that are currently triggered."}},"type":"object","title":"WidgetDataResponse","examples":[{"summary":"Chart/table data","value":{"data":[{"Movements":"38,845","Revenue":"€1,933,200.66","Store":"Demo Store"},{"Movements":"36,357","Revenue":"€1,852,855.22","Store":"MediaWorld"}]}},{"summary":"KPI data","value":{"delta":"+12.5%","isPositive":true,"value":"€1,933,200.66"}}]},"WidgetLayoutItem":{"properties":{"id":{"type":"string","title":"Id","description":"Client-generated or existing widget id."},"title":{"type":"string","title":"Title","description":"Widget title."},"type":{"type":"string","title":"Type","description":"Widget visualization type."},"queryId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Queryid","description":"Linked saved query id."},"labelColumn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Labelcolumn","description":"Label column from query result."},"valueColumns":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Valuecolumns","description":"Value columns from query result."},"settings":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Settings","description":"Type-specific settings object."},"cardWidth":{"type":"string","title":"Cardwidth","description":"Layout width token.","default":"quarter"},"showLegend":{"type":"boolean","title":"Showlegend","description":"Show legend flag.","default":false},"showValues":{"type":"boolean","title":"Showvalues","description":"Show value labels flag.","default":false},"gridPos":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Gridpos","description":"{row, col} in dashboard grid."}},"type":"object","required":["id","title","type"],"title":"WidgetLayoutItem","example":{"cardWidth":"half","gridPos":{"col":0,"row":0},"id":"w_123","labelColumn":"Store","queryId":"q_123","settings":{"barOrientation":"vertical","curveType":"monotone"},"showLegend":true,"showValues":false,"title":"Sales by store","type":"bar","valueColumns":["Revenue","Movements"]}},"WidgetOut":{"properties":{"id":{"type":"string","title":"Id","description":"Widget id."},"title":{"type":"string","title":"Title","description":"Widget heading."},"type":{"type":"string","title":"Type","description":"Visualization type, e.g. bar, line, kpi, table."},"queryId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Queryid","description":"Linked saved query id."},"labelColumn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Labelcolumn","description":"Result column used as category/label."},"valueColumns":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Valuecolumns","description":"Result columns plotted or aggregated."},"settings":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Settings","description":"Type-specific options (orientation, curve, etc.)."},"cardWidth":{"type":"string","title":"Cardwidth","description":"Layout width token, e.g. quarter, half, full."},"showLegend":{"type":"boolean","title":"Showlegend","description":"Whether to show chart legend."},"showValues":{"type":"boolean","title":"Showvalues","description":"Whether to show data labels on charts."},"gridPos":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Gridpos","description":"Optional {row, col} position in the grid."},"value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value","description":"KPI primary value when precomputed in list responses."},"delta":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Delta","description":"KPI delta string when applicable."},"isPositive":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ispositive","description":"Whether delta is considered positive."},"data":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Data","description":"Inline series/table rows when hydrated."}},"type":"object","required":["id","title","type","cardWidth","showLegend","showValues"],"title":"WidgetOut","example":{"cardWidth":"half","gridPos":{"col":0,"row":0},"id":"w_123","labelColumn":"Store","queryId":"q_123","settings":{"barOrientation":"vertical","curveType":"monotone"},"showLegend":true,"showValues":false,"title":"Sales by store","type":"bar","valueColumns":["Revenue","Movements"]}},"WidgetUpdate":{"properties":{"title":{"type":"string","title":"Title","description":"Widget title."},"type":{"type":"string","title":"Type","description":"Visualization type."},"queryId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Queryid","description":"Saved query to bind."},"labelColumn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Labelcolumn","description":"Label column name."},"valueColumns":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Valuecolumns","description":"Numeric/value column names."},"settings":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Settings","description":"Visualization settings."},"cardWidth":{"type":"string","title":"Cardwidth","description":"Layout width token.","default":"quarter"},"showLegend":{"type":"boolean","title":"Showlegend","description":"Show legend.","default":false},"showValues":{"type":"boolean","title":"Showvalues","description":"Show data labels.","default":false},"gridPos":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Gridpos","description":"Grid position {row, col}."}},"type":"object","required":["title","type"],"title":"WidgetUpdate","example":{"cardWidth":"half","gridPos":{"col":0,"row":0},"labelColumn":"Store","queryId":"q_123","settings":{"barOrientation":"vertical","curveType":"monotone"},"showLegend":true,"showValues":false,"title":"Sales by store","type":"bar","valueColumns":["Revenue","Movements"]}},"WorkspaceMemberInvite":{"properties":{"usernameOrEmail":{"type":"string","title":"Usernameoremail","description":"Existing user's username or email, or a **valid email** to invite someone who is not registered yet (signup email)."}},"type":"object","required":["usernameOrEmail"],"title":"WorkspaceMemberInvite","example":{"usernameOrEmail":"colleague@company.com"}},"WorkspaceMemberOut":{"properties":{"pendingInvite":{"type":"boolean","title":"Pendinginvite","description":"True for email-only invites awaiting registration; userId is null until they sign up.","default":false},"inviteId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inviteid","description":"Pending invite id (use DELETE .../pending/{inviteId})."},"userId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Userid","description":"Active member user id."},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Display name (empty while pending)."},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username","description":"Login name (empty while pending)."},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"Email when set."},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Createdat","description":"When the membership or pending invite was created (UTC)."},"invitedByUserId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Invitedbyuserid","description":"Owner user who sent the invite."},"emailSent":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Emailsent","description":"POST only: when pendingInvite, whether the signup invitation email was sent."},"inviteMessage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Invitemessage","description":"POST only: extra context (e.g. SMTP error) for pending invites."}},"type":"object","title":"WorkspaceMemberOut"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}},"tags":[{"name":"system","description":"Operational endpoints that do not require authentication."},{"name":"auth","description":"Sign-in and session management: username/password login, Google SSO, token refresh, logout, password change for logged-in users, self-service registration, and email OTP account activation."},{"name":"users","description":"Current user profile (`/me`), language preference, and public password-recovery flow (request OTP via `sendOtp`, complete reset with `user/forgot-password`). Privileged user administration is provided by the separate internal Admin API."},{"name":"sectors","description":"Read-only list of business sector labels localized in English, Italian, and Spanish for onboarding forms."},{"name":"businesses","description":"CRUD for businesses owned by the authenticated user. Creating a business may set it as the active business when none is selected."},{"name":"sources","description":"Data connections per business: list/create/update/delete sources, test connectivity, sync table metadata, preview rows, and edit table/column aliases for UI and AI. Supports activating an internal **warehouse** and switching default query targets between direct DB and warehouse."},{"name":"imports","description":"Import **sources** (database link, uploaded CSV/Excel, FTP/SFTP) and **import jobs** that load data into a warehouse table. Jobs support scheduling, manual runs, and run history. Remote FTP/SFTP configs can be validated before use."},{"name":"queries","description":"Saved SQL definitions per business, optional column formatting (`columnsConfig`), and execution against the resolved data source (with optional per-request `sourceId` override)."},{"name":"semantic-metrics","description":"Lightweight **guided metrics** for workspace members: each metric wraps an owner-defined saved query with optional filter fields (no SQL shown). Owners manage metrics; members can list and **run** them with `POST .../run`."},{"name":"reports","description":"Dashboards (**reports**) per business: list, fetch with widgets, create, rename, delete, and save grid layout in one call."},{"name":"widgets","description":"Widgets inside a report: create, update, delete, and fetch **computed data** by running the linked saved query and formatting results for the widget type."},{"name":"chats","description":"AI chat threads per business: list chats, create, rename, delete, load message history, and send a user message (assistant reply is generated and stored)."},{"name":"subscription","description":"Subscription summary for the active business, **catalog of plans** (`GET /api/subscription/plans`), **plan change** (upgrade with immediate proration or downgrade from the next billing period), pending downgrade display, invoices, and PDF download."}]}