openapi: 3.1.0 info: title: 'solidpixels API documentation' description: 'Core orchestration API for the Solidpixels platform.' version: 1.0.0 servers: - url: 'https://solidpixels.app.solidpixels.com' tags: - name: '[auth] Authentication' description: 'Account registration and authentication.' - name: '[auth] Password Reset' description: 'Password recovery and reset endpoints.' - name: '[auth] JWT Tokens' description: 'JWT token generation and public key endpoints.' - name: '[auth] Personal Access Tokens' description: 'Manage API tokens for programmatic access.' - name: '[auth] SSO' description: 'Single Sign-On for cross-service authentication.' - name: '[auth] Impersonation' description: 'Console account impersonation using first-party login refresh credentials.' - name: '[auth] OAuth Clients' description: 'OAuth2 client application management.' - name: '[auth] OAuth Grants' description: 'OAuth2 grant management.' - name: '[auth] OAuth Protocol' description: 'OAuth2 authorization protocol endpoints.' - name: '[account] Accounts' description: 'Admin CRUD operations for accounts.' - name: '[account] Current Account' description: 'Manage the authenticated account profile.' - name: '[account] Current Account Settings' description: 'Manage the authenticated account settings (key-value preferences).' - name: '[account] Account Settings' description: 'Account configuration settings.' - name: '[account] Account Admin Settings' description: 'Admin-managed configuration settings for an account.' - name: '[website] Websites' description: 'CRUD operations for websites.' - name: '[website] Administration' description: 'Website administration endpoints.' - name: '[website] Domains' description: 'Website domain management.' - name: '[website] Accounts' description: 'Website account membership endpoints.' - name: '[website] Roles' description: 'Website role management endpoints.' - name: '[website] Invitations' description: 'Website access invitations.' - name: '[website] Redirects' description: 'URL redirect management.' - name: '[website] Headers' description: 'Response header management.' - name: '[website] Languages' description: 'Language management for websites.' - name: '[website] Backups' description: 'Per-website backup management.' - name: '[website] Language Settings' description: 'Language-specific website configuration settings.' - name: '[website] Settings' description: 'Website configuration settings.' - name: '[website] Entitlements' description: 'Website entitlement read endpoints.' - name: '[billing] Profiles' description: 'Account-scoped billing profiles.' - name: '[billing] Website Billing' description: 'Website subscription, prices, checkout, and invoices.' - name: '[billing] Website Pricing' description: 'Admin-set negotiated price for a single website.' - name: '[billing] Stripe Webhooks' description: 'Stripe billing event ingestion.' - name: '[feedback] Reports' description: 'User feedback submission endpoints.' - name: '[library] Libraries' description: 'Library management.' - name: '[library] Ownership' description: 'Library ownership operations.' - name: '[library] Accounts' description: 'Library member management.' - name: '[library] Invitations' description: 'Library access invitations.' - name: '[library] Folders' description: 'Library folder management.' - name: '[library] Items' description: 'Library item management.' - name: '[library] Website Libraries' description: 'Manage library-website bindings.' - name: '[library] Website Content' description: 'Read-only library content via website scope.' - name: '[platform] Administration' description: 'Platform administration operations.' - name: '[admin] Websites' description: 'Admin website operations.' - name: '[internal] Caddy' description: 'Internal endpoints for Caddy reverse proxy integration.' - name: '[internal] Library' description: 'Internal endpoints for library content.' - name: '[internal] Platform' description: 'Internal endpoints for platform infrastructure.' - name: '[internal] Tokens' description: 'Internal endpoints for minting component tokens.' - name: '[admin] Administration' description: 'Administrative endpoints (console admin).' - name: '[tag] Tags' description: 'Attach and detach tags on accounts.' components: securitySchemes: default: type: http scheme: bearer description: 'Use the bearer credential documented for each endpoint. Account impersonation start and return require the original first-party login refresh token. Website impersonation requires a first-party account JWT. Public endpoints do not require authentication.' schemas: Account: type: object properties: id: type: string name: type: string surname: type: string username: type: string email: type: string status: type: string roles: type: array items: type: string permissions: type: array items: type: string websites_count: type: integer websites: type: - string - 'null' tags: type: array items: type: object properties: id: type: string name: type: string color: type: string icon: type: string created_at: type: string updated_at: type: string avatar_file_id: type: - string - 'null' AccountAdminSetting: type: object properties: key: type: string value: type: boolean AccountAdminSettingResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/AccountAdminSetting' message: type: string required: - success - data AccountImpersonation: type: object properties: token_type: type: string const: Bearer access_token: type: string refresh_token: type: string expires_in: type: integer account: type: string pattern: '^acc_[A-Za-z0-9]{32}$' session_id: type: string pattern: '^pat_[A-Za-z0-9]{32}$' required: - token_type - access_token - refresh_token - expires_in - account - session_id AccountImpersonationResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/AccountImpersonation' message: type: string required: - success - data AccountImpersonationReturn: type: object properties: token_type: type: string const: Bearer access_token: type: string refresh_token: type: - string - 'null' description: 'Null retains the original login refresh credential.' expires_in: type: integer account: type: string pattern: '^acc_[A-Za-z0-9]{32}$' required: - token_type - access_token - refresh_token - expires_in - account AccountImpersonationReturnResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/AccountImpersonationReturn' message: type: string required: - success - data AccountPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/Account' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta AccountResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/Account' message: type: string required: - success - data AccountSetting: type: object properties: id: type: string group: type: string type: type: string key: type: string value: type: string created_at: type: string updated_at: type: string AccountSettingPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/AccountSetting' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta AccountSettingResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/AccountSetting' message: type: string required: - success - data AssignWebsiteAccountRequest: type: object properties: account_id: type: string description: 'Prefixed account ID to assign.' required: - account_id AttachLibraryToWebsiteRequest: type: object properties: library_id: type: string description: 'Library prefixed ID to attach.' required: - library_id AttachTagsRequest: type: object properties: tag_ids: type: array description: 'Prefixed tag IDs to attach.' items: type: string required: - tag_ids AuthToken: type: object properties: token_type: type: string access_token: type: string refresh_token: type: string expires_in: type: integer account: type: string AuthTokenResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/AuthToken' message: type: string required: - success - data AuthorizeInfo: type: object properties: client_id: type: string client_name: type: string scopes: type: array items: type: object properties: role: type: string required: - role roles_requiring_resource_selection: type: array items: type: string redirect_uri: type: string state: type: - string - 'null' required: - client_id - client_name - scopes - roles_requiring_resource_selection - redirect_uri - state AuthorizeInfoResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/AuthorizeInfo' message: type: string required: - success - data BatchAccountSettingsRequest: type: object properties: store: type: array description: 'Settings to create.' items: type: object update: type: array description: 'Settings to update; each item includes its prefixed id.' items: type: object destroy: type: array description: 'Prefixed IDs to delete.' items: type: string BatchAccountsRequest: type: object properties: store: type: array description: 'Accounts to create.' items: type: object update: type: array description: 'Accounts to update.' items: type: object destroy: type: array description: 'Prefixed account IDs to delete.' items: type: string enable: type: array description: 'Prefixed account IDs to enable.' items: type: string disable: type: array description: 'Prefixed account IDs to disable.' items: type: string BatchLibrariesRequest: type: object properties: store: type: array description: 'Libraries to create.' items: type: object update: type: array description: 'Libraries to update; each item includes its prefixed id.' items: type: object destroy: type: array description: 'Prefixed IDs to delete.' items: type: string BatchLibraryFoldersRequest: type: object properties: store: type: array description: 'Folders to create.' items: type: object update: type: array description: 'Folders to update; each item includes its prefixed id.' items: type: object destroy: type: array description: 'Prefixed IDs to delete.' items: type: string BatchLibraryItemsRequest: type: object properties: store: type: array description: 'Items to create (name, content, folder_id).' items: type: object update: type: array description: 'Items to update (id required, plus fields).' items: type: object destroy: type: array description: 'Item prefixed IDs to delete.' items: type: string BatchOAuthClientsRequest: type: object properties: store: type: array description: 'Clients to create.' items: type: object update: type: array description: 'Clients to update; each item includes its prefixed id.' items: type: object destroy: type: array description: 'Prefixed IDs to delete.' items: type: string BatchWebsiteHeadersRequest: type: object properties: store: type: array description: 'Headers to create.' items: type: object update: type: array description: 'Headers to update; each item includes its prefixed id.' items: type: object destroy: type: array description: 'Prefixed IDs to delete.' items: type: string BatchWebsiteLanguageSettingsRequest: type: object properties: store: type: array description: 'Language settings to create.' items: type: object update: type: array description: 'Language settings to update; each item includes its prefixed id.' items: type: object destroy: type: array description: 'Prefixed IDs to delete.' items: type: string BatchWebsiteLanguagesRequest: type: object properties: store: type: array description: 'Languages to create.' items: type: object update: type: array description: 'Languages to update; each item includes its prefixed id.' items: type: object destroy: type: array description: 'Prefixed IDs to delete.' items: type: string BatchWebsiteRedirectsRequest: type: object properties: store: type: array description: 'Redirects to create.' items: type: object update: type: array description: 'Redirects to update; each item includes its prefixed id.' items: type: object destroy: type: array description: 'Prefixed IDs to delete.' items: type: string BatchWebsiteSettingsRequest: type: object properties: store: type: array description: 'Settings to create.' items: type: object update: type: array description: 'Settings to update; each item includes its prefixed id.' items: type: object destroy: type: array description: 'Prefixed IDs to delete.' items: type: string BatchWebsitesRequest: type: object properties: store: type: array description: 'Websites to create.' items: type: object update: type: array description: 'Websites to update; each item includes its prefixed id.' items: type: object destroy: type: array description: 'Prefixed IDs to delete.' items: type: string BillingInvoice: type: object properties: id: type: string number: type: string status: type: string currency: type: string amount_due_minor: type: integer amount_paid_minor: type: integer period_start: type: string period_end: type: string invoice_number: type: string invoice_url: type: string created_at: type: string BillingInvoicePaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/BillingInvoice' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta BillingPortalSession: type: object properties: portal_url: type: string BillingPortalSessionResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/BillingPortalSession' message: type: string required: - success - data BillingPrice: type: object properties: id: type: string code: type: string kind: type: string label: type: string currency: type: string interval: type: string amount_minor: type: integer is_custom: type: boolean BillingPriceResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/BillingPrice' message: type: string required: - success - data BillingProfile: type: object properties: id: type: string label: type: string is_default: type: boolean billing_email: type: string phone: type: string name: type: string company: type: string street: type: string city: type: string postal_code: type: string country: type: string currency: type: string company_identification_number: type: string company_vatin: type: string has_stripe_customer: type: boolean created_at: type: string updated_at: type: string BillingProfilePaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/BillingProfile' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta BillingProfileResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/BillingProfile' message: type: string required: - success - data ChangeAccountPasswordRequest: type: object properties: new_password: type: string description: 'New password with at least 8 characters.' new_password_confirmation: type: string description: 'New password confirmation.' required: - new_password - new_password_confirmation CheckPermissionsRequest: type: object properties: permissions: type: array minItems: 1 maxItems: 100 uniqueItems: true items: type: string maxLength: 130 pattern: '^[a-z][a-z0-9._:-]*$' description: 'Unique permission names.' required: - permissions CheckoutSession: type: object properties: checkout_url: type: string CheckoutSessionResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/CheckoutSession' message: type: string required: - success - data ConfirmEmailEnrollmentRequest: type: object properties: token: type: string description: 'E-mail code enrollment challenge token.' code: type: string description: 'Six-digit code received by e-mail.' required: - token - code ConfirmPasskeyEnrollmentRequest: type: object properties: token: type: string description: 'Passkey enrollment challenge token.' attestation: type: object description: 'Structured WebAuthn registration response.' properties: {} name: type: string description: 'Passkey label.' required: - token - attestation - name ConfirmTotpEnrollmentRequest: type: object properties: token: type: string description: 'TOTP enrollment challenge token.' code: type: string description: 'Six-digit TOTP code.' required: - token - code CopyLibraryItemRequest: type: object properties: library_id: type: string description: 'Target library prefixed ID.' required: - library_id CreateAccountRequest: type: object properties: name: type: string maxLength: 50 description: 'First name.' surname: type: string maxLength: 50 description: 'Last name.' email: type: string format: email maxLength: 254 description: 'Unique email address.' password: type: string minLength: 8 description: Password. password_confirmation: type: string description: 'Password confirmation.' roles: type: array minItems: 1 items: type: string description: 'Console roles.' status: type: string enum: - enabled - disabled description: 'Account status.' required: - name - surname - email CreateAccountSettingRequest: type: object properties: group: type: string maxLength: 50 description: 'Setting group.' key: type: string maxLength: 100 description: 'Setting key.' value: description: 'Setting value.' type: type: string enum: - bool - text - int - json default: text description: 'Setting value type.' required: - group - key - value CreateBillingProfileRequest: type: object properties: label: type: string maxLength: 100 billing_email: type: string format: email maxLength: 254 is_default: type: boolean phone: type: string nullable: true maxLength: 50 name: type: string nullable: true maxLength: 110 company: type: string nullable: true maxLength: 100 street: type: string nullable: true maxLength: 200 city: type: string nullable: true maxLength: 100 postal_code: type: string nullable: true maxLength: 20 country: type: string nullable: true maxLength: 2 currency: type: string enum: - CZK - EUR company_identification_number: type: string nullable: true maxLength: 50 company_vatin: type: string nullable: true maxLength: 50 required: - label - billing_email CreateFeedbackRequest: type: object properties: text: type: string description: 'Feedback text.' context: type: object description: 'Console route and environment context.' properties: {} images: type: array description: 'Attached image references.' items: type: string required: - text CreateLibraryFolderRequest: type: object properties: name: type: string maxLength: 100 description: 'Folder name.' parent_id: type: string nullable: true description: 'Parent folder prefixed ID.' position: type: integer minimum: 0 description: 'Sort position.' required: - name CreateLibraryInvitationRequest: type: object properties: email: type: string format: email maxLength: 254 description: 'Email address to invite.' roles: type: array minItems: 1 items: type: integer description: 'Role IDs to assign.' required: - email - roles CreateLibraryItemRequest: type: object properties: name: type: string maxLength: 100 description: 'Item name.' content: type: object additionalProperties: true description: 'Item content.' folder_id: type: string nullable: true description: 'Folder prefixed ID.' required: - name - content CreateLibraryRequest: type: object properties: name: type: string maxLength: 100 description: 'Library name.' required: - name CreateOAuthClientRequest: type: object properties: name: type: string maxLength: 100 description: 'Client name.' type: type: string enum: - confidential - public description: 'OAuth client type.' redirect_uris: type: array items: type: string maxLength: 2048 description: 'Allowed redirect URIs.' component: type: string nullable: true maxLength: 64 description: 'Confidential client service component.' required: - name - type - redirect_uris CreatePersonalAccessTokenRequest: type: object properties: name: type: string maxLength: 100 description: 'Token name for identification.' abilities: type: array nullable: true items: type: string description: 'Token abilities.' expires_at: type: string nullable: true description: 'Optional expiration timestamp.' required: - name CreateSSOCodeRequest: type: object properties: access_token: type: string description: 'Current JWT access token to transfer.' required: - access_token CreateSlackFeedbackRequest: type: object properties: text: type: string description: 'Feedback text.' user_name: type: string description: 'Slack user name.' user_id: type: string description: 'Slack user ID.' required: - text CreateTagRequest: type: object properties: name: type: string description: 'Tag name. Lowercased and trimmed; matches /^[a-z0-9][a-z0-9. _-]*$/ and up to 50 characters.' color: type: string description: 'Optional #RRGGBB color.' icon: type: string description: 'Optional icon name.' enum: - hash - star - crown - globe - server - users - folder - heart - bookmark - shield entity_type: type: string description: 'Optional entity type restriction.' enum: - website - account - library required: - name CreateWebsiteBackupRequest: type: object properties: label: type: string maxLength: 20 pattern: '^[a-z0-9]+$' description: 'Unique website backup label matching ^[a-z0-9]+$.' required: - label CreateWebsiteDomainRequest: type: object properties: domain: type: string maxLength: 253 description: 'Domain to add.' role: type: string enum: - default - alias - redirect description: 'Domain role.' required: - domain CreateWebsiteHeaderRequest: type: object properties: name: type: string maxLength: 100 pattern: '^[A-Za-z][A-Za-z0-9\-]*$' description: 'Header name.' value: type: string maxLength: 8000 pattern: '^[^\x00-\x1f]*$' description: 'Header value.' required: - name - value CreateWebsiteInvitationRequest: type: object properties: email: type: string format: email maxLength: 254 roles: type: array items: type: integer minItems: 1 uniqueItems: true required: - email - roles CreateWebsiteLanguageRequest: type: object properties: code: type: string maxLength: 100 description: 'Supported BCP 47 language tag.' slug: type: string maxLength: 100 pattern: '^[a-z0-9]+(-[a-z0-9]+)*$' description: 'URL-safe slug.' required: - code CreateWebsiteLanguageSettingRequest: type: object properties: group: type: string maxLength: 50 description: 'Setting group.' key: type: string maxLength: 100 description: 'Setting key.' value: description: 'Setting value.' required: - group - key - value CreateWebsiteRedirectRequest: type: object properties: source_path: type: string maxLength: 1000 pattern: '^/[^?#]*$' description: 'Source URL path.' destination_url: type: string maxLength: 2000 description: 'Target URL path.' type: type: string enum: - '301' - '302' - '303' - '307' - '308' - alias description: 'Redirect type.' is_active: type: boolean description: 'Whether the redirect is active.' is_source_case_sensitive: type: boolean description: 'Whether source path matching is case-sensitive.' is_destination_case_sensitive: type: boolean description: 'Whether the destination preserves case.' required: - source_path - destination_url - type CreateWebsiteRequest: type: object properties: name: type: string maxLength: 100 description: 'Website name.' domain: type: string nullable: true maxLength: 253 description: 'Website domain.' required: - name CreateWebsiteRoleRequest: type: object properties: name: type: string maxLength: 42 pattern: '^[a-z0-9]+(?:-[a-z0-9]+)*$' description: 'Role slug. The API prefixes it with website:.' permissions: type: array items: type: string minItems: 1 uniqueItems: true required: - name - permissions additionalProperties: false CreateWebsiteSettingRequest: type: object properties: group: type: string maxLength: 50 description: 'Setting group.' key: type: string maxLength: 100 description: 'Setting key.' value: description: 'Setting value.' type: type: string enum: - bool - text - int - json default: text description: 'Setting value type.' required: - group - key - value DenyOAuthAuthorizationRequest: type: object properties: client_id: type: string description: 'Active client ID: cli_ plus 32 alphanumeric characters, exactly 36 bytes.' minLength: 36 maxLength: 36 pattern: '^cli_[A-Za-z0-9]{32}$' redirect_uri: type: string description: 'Exact registered callback, including native schemes. Maximum 2,048 characters and bytes.' maxLength: 2048 state: type: - string - 'null' description: 'State returned unchanged. Maximum 500 characters and bytes.' maxLength: 500 required: - client_id - redirect_uri EmailFactorEnrollmentStarted: type: object properties: token: type: string resend_in_seconds: type: integer EmailFactorEnrollmentStartedResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/EmailFactorEnrollmentStarted' message: type: string required: - success - data EmailFactorSent: type: object properties: resend_in_seconds: type: integer EmailFactorSentResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/EmailFactorSent' message: type: string required: - success - data EndAccountImpersonationRequest: type: object properties: session_id: type: string pattern: '^pat_[A-Za-z0-9]{32}$' required: - session_id Error: type: object properties: success: type: boolean message: type: string errors: type: object required: - success - message ExchangeSSOCodeRequest: type: object properties: code: type: string description: 'One-time SSO code from create-code endpoint.' required: - code ExportLibraryRequest: type: object properties: ids: type: array description: 'Prefixed library IDs to export.' items: type: string required: - ids FactorActivation: type: object properties: factor: type: object properties: id: type: string type: type: string name: type: string last_used_at: type: - string - 'null' recovery_codes: type: array items: type: string FactorActivationResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/FactorActivation' message: type: string required: - success - data ForgotPasswordRequest: type: object properties: email: type: string format: email maxLength: 254 description: 'The email address of the account.' required: - email GetLoginPasskeyOptionsRequest: type: object properties: token: type: string description: 'Login challenge token.' required: - token GetManagementAssertionOptionsRequest: type: object properties: current_password: type: string description: 'Current account password.' required: - current_password ImportLibraryRequest: type: object properties: version: type: integer description: 'Export format version.' resource_type: type: string description: 'Resource type of the payload; must match the import target.' data: type: array description: 'Exported records to import.' items: type: object required: - version - resource_type - data Library: type: object properties: id: type: string name: type: string is_system: type: boolean is_website_library: type: boolean items_count: type: integer websites_count: type: integer owner_account_id: type: string owner: type: object properties: firstname: type: string lastname: type: string email: type: string roles: type: array items: type: string tags: type: array items: type: object properties: id: type: string name: type: string color: type: string icon: type: string created_at: type: string updated_at: type: string LibraryAccount: type: object properties: account: type: object properties: id: type: string name: type: string surname: type: string username: type: string email: type: string status: type: string roles: type: array items: type: object properties: name: type: string is_owner: type: boolean is_default: type: boolean joined_at: type: string LibraryAccountPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/LibraryAccount' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta LibraryAccountResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/LibraryAccount' message: type: string required: - success - data LibraryCollectionResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/Library' message: type: string required: - success - data LibraryFolder: type: object properties: id: type: string library_id: type: string parent_id: type: - string - 'null' name: type: string position: type: integer created_at: type: string updated_at: type: string LibraryFolderCollectionResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/LibraryFolder' message: type: string required: - success - data LibraryFolderPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/LibraryFolder' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta LibraryFolderResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/LibraryFolder' message: type: string required: - success - data LibraryInvitation: type: object properties: id: type: string email: type: string token: type: string roles: type: array items: type: object properties: id: type: integer name: type: string status: type: string invited_by: type: object properties: id: type: string name: type: string expires_at: type: string accepted_at: type: - string - 'null' is_expired: type: boolean created_at: type: string LibraryInvitationDetails: type: object properties: email: type: string roles: type: array items: type: object properties: name: type: string status: type: string library_name: type: string invited_by: type: string expires_at: type: string is_expired: type: boolean requires_registration: type: boolean LibraryInvitationDetailsResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/LibraryInvitationDetails' message: type: string required: - success - data LibraryInvitationPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/LibraryInvitation' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta LibraryInvitationResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/LibraryInvitation' message: type: string required: - success - data LibraryItem: type: object properties: id: type: string library_id: type: string name: type: string folder_id: type: - string - 'null' content: type: object properties: blocks: type: array thumbnail_url: type: - string - 'null' created_at: type: string updated_at: type: string LibraryItemPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/LibraryItem' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta LibraryItemResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/LibraryItem' message: type: string required: - success - data LibraryPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/Library' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta LibraryPermissionCheck: type: object properties: type: type: string enum: - account - website - library id: type: string permissions: type: object additionalProperties: type: boolean required: - type - id - permissions LibraryPermissionCheckResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/LibraryPermissionCheck' message: type: string required: - success - data LibraryPermissionList: type: object properties: type: type: string enum: - account - website - library id: type: string permissions: type: array items: type: string required: - type - id - permissions LibraryPermissionListResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/LibraryPermissionList' message: type: string required: - success - data LibraryResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/Library' message: type: string required: - success - data LibraryRole: type: object properties: id: type: integer name: type: string LibraryRolePaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/LibraryRole' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta ListAccountFactors: type: object properties: factors: type: array items: type: object properties: id: type: string type: type: string name: type: string last_used_at: type: - string - 'null' recovery_codes_remaining: type: integer available_types: type: array items: type: string ListAccountFactorsResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/ListAccountFactors' message: type: string required: - success - data LoginRequest: type: object properties: email: type: string description: 'Account email address.' password: type: string description: 'Account password.' required: - email - password LoginResult: type: object properties: token_type: type: string access_token: type: string refresh_token: type: string expires_in: type: integer account: type: string challenge: type: object properties: token: type: string expires_at: type: string factors: type: array items: type: string LoginResultResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/LoginResult' message: type: string required: - success - data LogoutRequest: type: object properties: access_token: type: string description: 'Current access token (JWT) to invalidate.' required: - access_token MaintenanceState: type: object properties: enabled: type: boolean html: type: - string - 'null' MaintenanceStateRequest: type: object properties: enabled: type: boolean description: '' html: type: - string - 'null' description: '' required: - enabled MaintenanceStateResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/MaintenanceState' message: type: string required: - success - data ManagementAssertionOptions: type: object properties: token: type: string options: type: object properties: challenge: type: string rpId: type: string allowCredentials: type: array items: type: object properties: type: type: string id: type: string userVerification: type: string timeout: type: integer ManagementAssertionOptionsResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/ManagementAssertionOptions' message: type: string required: - success - data MintAccountTokenRequest: type: object properties: account: type: string description: 'Prefixed account ID of the PAT owner.' website: type: string description: 'Optional prefixed website ID visible to the owner.' required: - account MintComponentJwtRequest: type: object properties: account: type: string description: 'Account prefixed ID (acc_…). Required unless website is present.' website: type: string description: 'Website prefixed ID (web_…). Required unless account is present.' component: type: string description: '' MintToken: type: object properties: token_type: type: string access_token: type: string expires_in: type: integer MintTokenResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/MintToken' message: type: string required: - success - data MoveLibraryItemRequest: type: object properties: library_id: type: string description: 'Target library prefixed ID.' required: - library_id OauthClient: type: object properties: id: type: string name: type: string type: type: string redirect_uris: type: array items: type: string is_active: type: boolean component: type: string created_at: type: string updated_at: type: string OauthClientCollectionResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/OauthClient' message: type: string required: - success - data OauthClientCreated: type: object properties: id: type: string name: type: string type: type: string client_secret: type: string redirect_uris: type: array items: type: string is_active: type: boolean component: type: string created_at: type: string OauthClientCreatedResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/OauthClientCreated' message: type: string required: - success - data OauthClientResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/OauthClient' message: type: string required: - success - data OauthGrant: type: object properties: id: type: string client_id: type: string client_name: type: string scopes: type: array items: type: object properties: role: type: string created_at: type: string OauthGrantCollectionResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/OauthGrant' message: type: string required: - success - data OauthRedirect: type: object properties: redirect_uri: type: string required: - redirect_uri OauthRedirectResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/OauthRedirect' message: type: string required: - success - data PaginationMeta: type: object properties: current_page: type: integer last_page: type: integer per_page: type: integer total: type: integer required: - current_page - last_page - per_page - total PasskeyAssertionOptions: type: object properties: challenge: type: string rpId: type: string allowCredentials: type: array items: type: object properties: type: type: string id: type: string userVerification: type: string timeout: type: integer PasskeyAssertionOptionsResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/PasskeyAssertionOptions' message: type: string required: - success - data PasskeyEnrollmentOptions: type: object properties: token: type: string options: type: object properties: challenge: type: string rp: type: object properties: name: type: string id: type: string user: type: object properties: id: type: string name: type: string displayName: type: string pubKeyCredParams: type: array items: type: object properties: type: type: string alg: type: integer attestation: type: string excludeCredentials: type: array PasskeyEnrollmentOptionsResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/PasskeyEnrollmentOptions' message: type: string required: - success - data PasswordResetUrl: type: object properties: url: type: string PasswordResetUrlResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/PasswordResetUrl' message: type: string required: - success - data PermissionCheck: type: object properties: type: type: string enum: - account - website - library id: type: string permissions: type: object additionalProperties: type: boolean required: - type - id - permissions PermissionCheckResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/PermissionCheck' message: type: string required: - success - data PermissionList: type: object properties: type: type: string enum: - account - website - library id: type: string permissions: type: array items: type: string required: - type - id - permissions PermissionListPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/PermissionList' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta PermissionListResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/PermissionList' message: type: string required: - success - data PersonalAccessToken: type: object properties: id: type: string name: type: string abilities: type: array items: type: string created_at: type: string expires_at: type: string last_used_at: type: - string - 'null' PersonalAccessTokenCreated: type: object properties: token: type: string id: type: string PersonalAccessTokenCreatedResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/PersonalAccessTokenCreated' message: type: string required: - success - data PersonalAccessTokenPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/PersonalAccessToken' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta PlatformComponentLimits: type: object properties: services: type: object properties: data: type: object properties: default: type: integer overrides: type: array components: type: array items: type: string values: type: array items: type: integer PlatformComponentLimitsResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/PlatformComponentLimits' message: type: string required: - success - data PlatformIdentifiers: type: object properties: library: type: object properties: library_id: type: string account_id: type: string account_email: type: string website_id: type: string PlatformIdentifiersResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/PlatformIdentifiers' message: type: string required: - success - data RecoveryCodes: type: object properties: recovery_codes: type: array items: type: string RecoveryCodesResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/RecoveryCodes' message: type: string required: - success - data RegenerateRecoveryCodesRequest: type: object properties: current_password: type: string description: 'Current account password.' proof: type: object description: 'Management proof.' properties: {} required: - current_password RegisterRequest: type: object properties: name: type: string maxLength: 50 description: 'First name of the account holder.' surname: type: string nullable: true maxLength: 50 description: 'Last name of the account holder.' email: type: string format: email maxLength: 254 description: 'Unique email address.' password: type: string minLength: 8 description: Password. password_confirmation: type: string description: 'Password confirmation.' required: - name - email - password - password_confirmation RegisteredAccount: type: object properties: id: type: string email: type: string RegisteredAccountResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/RegisteredAccount' message: type: string required: - success - data RemoveAccountFactorRequest: type: object properties: current_password: type: string description: 'Current account password.' proof: type: object description: 'Management proof.' properties: {} required: - current_password RemoveLibraryAccountRequest: type: object properties: account_id: type: string description: 'Prefixed account ID to remove.' required: - account_id RemoveWebsiteAccountRequest: type: object properties: account_id: type: string description: 'Prefixed account ID to remove.' required: - account_id ReplaceAccountRolesRequest: type: object properties: roles: type: array description: 'Unique Console roles. Must include console:account.' items: type: string required: - roles ReplaceWebsiteAccountRolesRequest: type: object additionalProperties: false properties: console_roles: type: array items: type: string minItems: 1 uniqueItems: true description: 'Console role names. When supplied, values must be unique and include console:account.' website_roles: type: array items: type: integer minItems: 1 uniqueItems: true description: 'Assignable website role IDs for the route website.' allOf: - anyOf: - type: object properties: console_roles: type: array items: type: string required: - console_roles - type: object properties: website_roles: type: array items: type: integer required: - website_roles ResendEmailEnrollmentRequest: type: object properties: token: type: string description: 'E-mail code enrollment challenge token.' required: - token ResetPasswordRequest: type: object properties: token: type: string description: 'The password reset token from the email link (contains encoded email).' password: type: string description: 'The new password (min 8 characters).' password_confirmation: type: string description: 'Password confirmation (must match password).' required: - token - password - password_confirmation RunTaskRequest: type: object properties: params: type: object description: 'Task parameter values keyed by parameter name.' properties: {} SSOCode: type: object properties: code: type: string expires_in: type: integer SSOCodeResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/SSOCode' message: type: string required: - success - data SendEmailFactorRequest: type: object properties: token: type: string description: 'Login challenge token.' required: - token ServeLimit: type: object properties: key: type: string value: type: integer source: type: string ServeLimitResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/ServeLimit' message: type: string required: - success - data SetWebsitePriceRequest: type: object properties: code: type: string maxLength: 50 description: 'Product code.' currency: type: string enum: - CZK - EUR description: 'Billing currency.' interval: type: string enum: - monthly - yearly description: 'Billing interval.' amount_minor: type: integer minimum: 1 description: 'Amount in minor units.' required: - code - currency - interval - amount_minor StartEmailEnrollmentRequest: type: object properties: current_password: type: string description: 'Current account password.' proof: type: object description: 'Management proof when a factor exists.' properties: {} required: - current_password StartFactorRecoveryRequest: type: object properties: email: type: string description: 'Account email address.' required: - email StartPasskeyEnrollmentRequest: type: object properties: current_password: type: string description: 'Current account password.' proof: type: object description: 'Management proof when a factor exists.' properties: {} required: - current_password StartTotpEnrollmentRequest: type: object properties: current_password: type: string description: 'Current account password.' proof: type: object description: 'Management proof when a factor exists.' properties: {} required: - current_password StartWebsiteCheckoutRequest: type: object properties: billing_price_id: type: string description: '' billing_profile_id: type: string description: '' required: - billing_price_id - billing_profile_id StripeWebhookEventRequest: type: object additionalProperties: true Tag: type: object properties: id: type: string name: type: string color: type: string icon: type: string entity_type: type: string usage_count: type: integer created_at: type: string updated_at: type: string TagCollectionResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/Tag' message: type: string required: - success - data TagResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/Tag' message: type: string required: - success - data Task: type: object properties: id: type: string key: type: string name: type: string description: type: string command: type: string category: type: string parameters: type: array items: type: object properties: name: type: string label: type: string type: type: string required: type: boolean default: type: - string - 'null' status: type: string current_output: type: string last_run_at: type: string last_run_status: type: string last_exit_code: type: integer last_triggered_by: type: string created_at: type: string updated_at: type: string TaskResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/Task' message: type: string required: - success - data TotpEnrollment: type: object properties: token: type: string otpauth_uri: type: string TotpEnrollmentResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/TotpEnrollment' message: type: string required: - success - data TransferLibraryOwnershipRequest: type: object properties: account_id: type: string description: 'Prefixed account ID of new owner.' required: - account_id TransferWebsiteOwnershipRequest: type: object properties: account_id: type: string description: 'Prefixed account ID of new owner.' confirm_subscription_cancellation: type: boolean description: 'Must be true when the website has a live paid subscription; transfer cancels it at period end.' required: - account_id UpdateAccountRequest: type: object properties: name: type: string maxLength: 50 description: 'First name.' surname: type: string maxLength: 50 description: 'Last name.' email: type: string format: email maxLength: 254 description: 'Unique email address.' username: type: string maxLength: 30 description: 'Unique username.' UpdateAccountSettingRequest: type: object properties: value: description: 'Setting value.' type: type: string description: 'Setting value type. Omit to preserve the current type.' enum: - bool - text - int - json required: - value UpdateBillingProfileRequest: type: object properties: label: type: string maxLength: 100 billing_email: type: string format: email maxLength: 254 is_default: type: boolean phone: type: string nullable: true maxLength: 50 name: type: string nullable: true maxLength: 110 company: type: string nullable: true maxLength: 100 street: type: string nullable: true maxLength: 200 city: type: string nullable: true maxLength: 100 postal_code: type: string nullable: true maxLength: 20 country: type: string nullable: true maxLength: 2 currency: type: string enum: - CZK - EUR company_identification_number: type: string nullable: true maxLength: 50 company_vatin: type: string nullable: true maxLength: 50 UpdateComponentLimitsRequest: type: object properties: services: type: object description: 'Map of component to { default, overrides }.' properties: {} required: - services UpdateCurrentAccountRequest: type: object properties: name: type: string maxLength: 50 description: 'First name.' surname: type: string maxLength: 50 description: 'Last name.' username: type: string minLength: 3 maxLength: 30 pattern: '^[a-zA-Z0-9_-]+$' description: 'Unique username.' current_password: type: string description: 'Current password when changing the password.' new_password: type: string minLength: 8 description: 'New password.' new_password_confirmation: type: string description: 'New password confirmation.' UpdateCurrentAccountSettingsRequest: type: object properties: keys: type: array description: 'Must not be greater than 100 characters.' items: type: string UpdateLibraryAccountRequest: type: object properties: is_default: type: boolean description: 'Whether the library is a default for this account.' required: - is_default UpdateLibraryFolderRequest: type: object properties: name: type: string maxLength: 100 description: 'Folder name.' parent_id: type: string nullable: true description: 'Parent folder prefixed ID.' position: type: integer minimum: 0 description: 'Sort position.' UpdateLibraryItemRequest: type: object properties: name: type: string maxLength: 100 description: 'Item name.' content: type: object additionalProperties: true description: 'Item content.' folder_id: type: string nullable: true description: 'Folder prefixed ID.' UpdateLibraryRequest: type: object properties: name: type: string maxLength: 100 description: 'Library name.' UpdateOAuthClientRequest: type: object properties: name: type: string nullable: true maxLength: 100 description: 'Client name.' redirect_uris: type: array nullable: true items: type: string maxLength: 2048 description: 'Allowed redirect URIs.' is_active: type: boolean nullable: true description: 'Whether the client is active.' component: type: string nullable: true maxLength: 64 description: 'Confidential client service component.' UpdateTagRequest: type: object properties: name: type: string description: 'Tag name. Lowercased and trimmed; matches /^[a-z0-9][a-z0-9. _-]*$/ and up to 50 characters.' color: type: string description: 'Optional #RRGGBB color.' icon: type: string description: 'Optional icon name.' enum: - hash - star - crown - globe - server - users - folder - heart - bookmark - shield entity_type: type: string description: 'Optional entity type restriction.' enum: - website - account - library UpdateWebsiteDomainRequest: type: object properties: role: type: string description: 'New role: default, alias or redirect.' required: - role UpdateWebsiteHeaderRequest: type: object properties: name: type: string maxLength: 100 pattern: '^[A-Za-z][A-Za-z0-9\-]*$' description: 'Header name.' value: type: string maxLength: 8000 pattern: '^[^\x00-\x1f]*$' description: 'Header value.' UpdateWebsiteLanguageRequest: type: object properties: slug: type: string nullable: true maxLength: 100 pattern: '^[a-z0-9]+(-[a-z0-9]+)*$' description: 'URL-safe slug.' is_default: type: boolean nullable: true description: 'Whether to promote this language to default.' UpdateWebsiteLanguageSettingRequest: type: object properties: value: description: 'Setting value.' required: - value UpdateWebsiteRedirectRequest: type: object properties: source_path: type: string maxLength: 1000 pattern: '^/[^?#]*$' description: 'Source URL path.' destination_url: type: string maxLength: 2000 description: 'Target URL path.' type: type: string enum: - '301' - '302' - '303' - '307' - '308' - alias description: 'Redirect type.' is_active: type: boolean description: 'Whether the redirect is active.' is_source_case_sensitive: type: boolean description: 'Whether source path matching is case-sensitive.' is_destination_case_sensitive: type: boolean description: 'Whether the destination preserves case.' UpdateWebsiteRequest: type: object properties: name: type: string maxLength: 100 description: 'Website name.' UpdateWebsiteRoleRequest: type: object properties: permissions: type: array items: type: string minItems: 1 uniqueItems: true required: - permissions additionalProperties: false UpdateWebsiteServeLimitRequest: type: object properties: value: type: integer description: 'Override value in requests per second. Must be one of the configured preset values.' required: - value UpdateWebsiteSettingRequest: type: object properties: value: description: 'Setting value.' type: type: string description: 'Setting value type. Omit to preserve the current type.' enum: - bool - text - int - json required: - value UpsertAccountAdminSettingRequest: type: object properties: key: type: string maxLength: 100 pattern: '^[a-z0-9_.]+$' enum: - factors.email.enabled description: 'Registered admin setting key.' value: type: boolean description: 'Setting value.' required: - key - value ValidationError: type: object properties: success: type: boolean message: type: string errors: type: object required: - success - message - errors VerifyLoginFactorRequest: type: object properties: token: type: string description: 'Login challenge token.' type: type: string description: 'Factor type.' enum: - totp - passkey - recovery_code - email code: type: string description: 'TOTP, e-mail, or recovery code.' assertion: type: object description: 'Structured WebAuthn assertion response.' properties: {} required: - token - type Website: type: object properties: id: type: string code: type: string name: type: string domain: type: string status: type: string plan: type: string paid_until: type: string active_until: type: - string - 'null' owner: type: object properties: id: type: string firstname: type: string lastname: type: string email: type: string provisioning: type: object properties: id: type: string status: type: string progress: type: object properties: ready: type: integer total: type: integer started_at: type: string deadline_at: type: string completed_at: type: - string - 'null' maintenance: type: boolean maintenance_html: type: - string - 'null' roles: type: array items: type: string tags: type: array items: type: object properties: id: type: string name: type: string color: type: string icon: type: string created_at: type: string updated_at: type: string actions: type: array items: type: string enum: - show - open-builder - update - enable - disable - clone - transfer - assign-account - remove-account - impersonate - delete - ai - domain - billing - maintenance - library - list-library - list-role - create-role - list-setting - create-setting - update-setting - delete-setting - list-header - create-header - update-header - delete-header - list-redirect - create-redirect - update-redirect - delete-redirect - toggle-redirect - list-language - create-language - update-language - delete-language - list-language-setting - create-language-setting - update-language-setting - delete-language-setting - 'backup:create' - 'backup:restore' uniqueItems: true description: 'Unique available actions in the documented enum order.' WebsiteAccount: type: object properties: account: type: object properties: id: type: string name: type: string surname: type: string username: type: string email: type: string format: email status: type: string actions: type: array items: type: string enum: - show - impersonate - update - enable - disable - set-password - change-roles - delete uniqueItems: true description: 'Unique available actions in the documented enum order.' required: - id - name - surname - username - email - status - actions roles: type: array items: type: object properties: id: type: integer name: type: string required: - id - name console_roles: type: array items: type: string uniqueItems: true description: 'Unique null-scope Console role names sorted lexicographically. Omitted when the actor cannot change the account roles.' is_owner: type: boolean joined_at: type: - string - 'null' format: date-time relationship_actions: type: array items: type: string enum: - open-builder - remove-membership - change-roles uniqueItems: true required: - account - roles - is_owner - joined_at - relationship_actions WebsiteAccountPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/WebsiteAccount' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta WebsiteAccountRoles: type: object properties: console_roles: type: - array - 'null' items: type: string uniqueItems: true description: 'Unique Console role names sorted lexicographically, or null when the request section was not supplied.' website_roles: type: - array - 'null' items: $ref: '#/components/schemas/WebsiteRole' uniqueItems: true description: 'Website roles sorted by numeric role ID, or null when the request section was not supplied.' required: - console_roles - website_roles WebsiteAccountRolesResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/WebsiteAccountRoles' message: type: string required: - success - data - message WebsiteBackup: type: object properties: id: type: string website_id: type: string label: type: string provisioning: type: object properties: id: type: string status: type: string progress: type: object properties: ready: type: integer total: type: integer started_at: type: string deadline_at: type: string completed_at: type: - string - 'null' restoration: type: object properties: id: type: string status: type: string progress: type: object properties: ready: type: integer total: type: integer started_at: type: string deadline_at: type: string completed_at: type: - string - 'null' created_at: type: string updated_at: type: string WebsiteBackupPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/WebsiteBackup' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta WebsiteBackupResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/WebsiteBackup' message: type: string required: - success - data WebsiteBilling: type: object properties: plan: type: string paid_until: type: string active_until: type: string subscription: type: object properties: id: type: string status: type: string status_label: type: string is_live: type: boolean current_period_start: type: string current_period_end: type: string cancel_at_period_end: type: boolean payment_warning_at: type: - string - 'null' price: type: object properties: id: type: string code: type: string kind: type: string label: type: string currency: type: string interval: type: string amount_minor: type: integer is_custom: type: boolean billing_profile_id: type: string billing_profile_label: type: string prices: type: array items: type: object properties: id: type: string code: type: string kind: type: string label: type: string currency: type: string interval: type: string amount_minor: type: integer is_custom: type: boolean feature_prices: type: array items: type: object properties: id: type: string code: type: string kind: type: string label: type: string currency: type: string interval: type: string amount_minor: type: integer is_custom: type: boolean entitlements: type: array items: type: string profiles: type: array items: type: object properties: id: type: string label: type: string is_default: type: boolean billing_email: type: string phone: type: string name: type: string company: type: string street: type: string city: type: string postal_code: type: string country: type: string currency: type: string company_identification_number: type: string company_vatin: type: string has_stripe_customer: type: boolean created_at: type: string updated_at: type: string invoices: type: array items: type: object properties: id: type: string number: type: string status: type: string currency: type: string amount_due_minor: type: integer amount_paid_minor: type: integer period_start: type: string period_end: type: string invoice_number: type: string invoice_url: type: string created_at: type: string WebsiteBillingResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/WebsiteBilling' message: type: string required: - success - data WebsiteCollectionResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/Website' message: type: string required: - success - data WebsiteDomain: type: object properties: id: type: string domain: type: string kind: type: string role: type: string is_apex: type: boolean cname_target: type: - string - 'null' dcv: type: - string - 'null' cf_status: type: - string - 'null' created_at: type: string updated_at: type: string WebsiteDomainPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/WebsiteDomain' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta WebsiteDomainResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/WebsiteDomain' message: type: string required: - success - data WebsiteEntitlements: type: object properties: website_id: type: string features: type: array items: type: string resolved_at: type: string WebsiteEntitlementsResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/WebsiteEntitlements' message: type: string required: - success - data WebsiteHeader: type: object properties: id: type: string website_id: type: string name: type: string value: type: string created_at: type: string updated_at: type: string WebsiteHeaderPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/WebsiteHeader' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta WebsiteHeaderResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/WebsiteHeader' message: type: string required: - success - data WebsiteImpersonation: type: object properties: code: type: string expires_in: type: integer url: type: string WebsiteImpersonationAccount: type: object properties: id: type: string pattern: '^acc_[A-Za-z0-9]{32}$' name: type: string surname: type: string email: type: string format: email roles: type: array items: type: object properties: id: type: integer name: type: string required: - id - name is_owner: type: boolean required: - id - name - surname - email - roles - is_owner WebsiteImpersonationAccountPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/WebsiteImpersonationAccount' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta WebsiteImpersonationResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/WebsiteImpersonation' message: type: string required: - success - data WebsiteInvitation: type: object properties: id: type: string email: type: string format: email token: type: string roles: type: - array - 'null' items: $ref: '#/components/schemas/WebsiteRole' status: type: string enum: - pending - accepted - expired - revoked invited_by: type: - object - 'null' properties: id: type: string name: type: string required: - id - name expires_at: type: - string - 'null' format: date-time accepted_at: type: - string - 'null' format: date-time is_expired: type: boolean created_at: type: string format: date-time required: - id - email - token - roles - status - invited_by - expires_at - accepted_at - is_expired - created_at WebsiteInvitationDetails: type: object properties: email: type: string roles: type: array items: type: object properties: name: type: string status: type: string website_name: type: string website_domain: type: string invited_by: type: string expires_at: type: string is_expired: type: boolean requires_registration: type: boolean WebsiteInvitationDetailsResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/WebsiteInvitationDetails' message: type: string required: - success - data WebsiteInvitationPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/WebsiteInvitation' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta WebsiteInvitationResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/WebsiteInvitation' message: type: string required: - success - data WebsiteLanguage: type: object properties: id: type: string website_id: type: string code: type: string slug: type: string is_default: type: boolean provisioning: type: object properties: id: type: string status: type: string progress: type: object properties: ready: type: integer total: type: integer started_at: type: string deadline_at: type: string completed_at: type: - string - 'null' created_at: type: string updated_at: type: string WebsiteLanguagePaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/WebsiteLanguage' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta WebsiteLanguageResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/WebsiteLanguage' message: type: string required: - success - data WebsiteLanguageSetting: type: object properties: id: type: string website_id: type: string website_language_id: type: string group: type: string key: type: string value: type: object properties: text: type: string created_at: type: string updated_at: type: string WebsiteLanguageSettingPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/WebsiteLanguageSetting' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta WebsiteLanguageSettingResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/WebsiteLanguageSetting' message: type: string required: - success - data WebsitePaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/Website' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta WebsiteRedirect: type: object properties: id: type: string website_id: type: string source_path: type: string destination_url: type: string type: type: string is_active: type: boolean is_source_case_sensitive: type: boolean is_destination_case_sensitive: type: boolean created_at: type: string updated_at: type: string WebsiteRedirectPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/WebsiteRedirect' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta WebsiteRedirectResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/WebsiteRedirect' message: type: string required: - success - data WebsiteResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/Website' message: type: string required: - success - data WebsiteRole: type: object properties: id: type: integer name: type: string type: type: string enum: - built-in - custom permissions: type: array items: type: string uniqueItems: true description: 'Unique permission names sorted lexicographically.' assignable: type: boolean actions: type: array items: type: string enum: - update - delete uniqueItems: true description: 'Unique lifecycle actions in update, delete order.' required: - id - name - type - permissions - assignable - actions WebsiteRoleCollectionResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/WebsiteRole' message: type: string required: - success - data WebsiteRolePaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/WebsiteRole' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta WebsiteRolePermissionGroup: type: object additionalProperties: false properties: group: type: string minLength: 1 permissions: type: array items: type: string uniqueItems: true description: 'Unique permission names sorted lexicographically.' required: - group - permissions WebsiteRolePermissionGroupCollectionResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/WebsiteRolePermissionGroup' description: 'Groups use stable configured order.' message: type: string required: - success - data - message additionalProperties: false WebsiteRoleResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/WebsiteRole' message: type: string required: - success - data WebsiteSetting: type: object properties: id: type: string website_id: type: string group: type: string type: type: string key: type: string value: type: string created_at: type: string updated_at: type: string WebsiteSettingPaginatedResponse: type: object properties: success: const: true data: type: array items: $ref: '#/components/schemas/WebsiteSetting' message: type: string meta: $ref: '#/components/schemas/PaginationMeta' required: - success - data - meta WebsiteSettingResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/WebsiteSetting' message: type: string required: - success - data WebsiteSubscription: type: object properties: id: type: string status: type: string status_label: type: string is_live: type: boolean current_period_start: type: string current_period_end: type: string cancel_at_period_end: type: boolean payment_warning_at: type: - string - 'null' price: type: object properties: id: type: string code: type: string kind: type: string label: type: string currency: type: string interval: type: string amount_minor: type: integer is_custom: type: boolean billing_profile_id: type: string billing_profile_label: type: string WebsiteSubscriptionResponse: type: object properties: success: const: true data: $ref: '#/components/schemas/WebsiteSubscription' message: type: string required: - success - data responses: Forbidden: description: Forbidden. content: application/json: schema: $ref: '#/components/schemas/Error' InternalServerError: description: 'Internal server error.' content: application/json: schema: $ref: '#/components/schemas/Error' NotFound: description: 'Not found.' content: application/json: schema: $ref: '#/components/schemas/Error' Unauthenticated: description: Unauthenticated. content: application/json: schema: $ref: '#/components/schemas/Error' ValidationFailed: description: 'Validation failed.' content: application/json: schema: $ref: '#/components/schemas/ValidationError' security: - default: [] paths: /api/v1/auth/register: post: summary: Register operationId: postApiV1AuthRegister description: "Create an account and its false-default 's library." parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/RegisteredAccountResponse' example: success: true data: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 email: jennings.orn@example.net message: 'Account registered successfully' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] Authentication' security: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RegisterRequest' /api/v1/auth/login: post: summary: Login operationId: postApiV1AuthLogin description: 'Authenticate with email and password. Factor accounts receive a login challenge instead of tokens.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LoginResultResponse' example: success: true data: token_type: Bearer access_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.YBCLu1qW1Xp1suAI9VcUADH4NzoFBhqWJYMK6nKqmjMynaPox92mZ8wTM3FtC9BLT5HPWvfFW5n0AF6wx7bEuXcl8PtnBn6DTnDM refresh_token: 1|X92mxzpThc43WsrjNAZfjO58aDL4WbFbwYoCQRMC expires_in: 1800 account: acc_03gb9a796thtl6untrsf4893vczmp53b challenge: token: E4fGUGTGbocfle9B8G8qzHjmacetny1ni5UCkbYqrgBLcwBbrbhy4BmVQeiDgcQB expires_at: '2026-01-01T00:05:00+00:00' factors: - passkey - totp message: 'Logged in successfully' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] Authentication' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/LoginRequest' security: [] /api/v1/auth/factor/passkey/options: post: summary: 'Get Login Passkey Options' operationId: postApiV1AuthFactorPasskeyOptions description: 'Create WebAuthn assertion options for an active login challenge.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/PasskeyAssertionOptionsResponse' example: success: true data: challenge: yxIXA-o4hxl7Ac8CtngOiVlI1PuzlvCGBw_6yZ8yiXg rpId: solid.test allowCredentials: - type: public-key id: jqBvy0hGaZCRt5EbF1TJtpQjJlQ5jgM3aEfL3yYr_hKfhP7pSr575EO1G5LgqD7fLhGKlESp1rKBjZKruS1R6C userVerification: preferred timeout: 60000 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] Authentication' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GetLoginPasskeyOptionsRequest' security: [] /api/v1/auth/factor/email/send: post: summary: 'Send E-mail Code' operationId: postApiV1AuthFactorEmailSend description: 'Send a one-time code to the account e-mail for an active login challenge.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/EmailFactorSentResponse' example: success: true data: resend_in_seconds: 60 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] Authentication' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SendEmailFactorRequest' security: [] /api/v1/auth/factor/verify: post: summary: 'Verify Login Factor' operationId: postApiV1AuthFactorVerify description: 'Complete a login challenge with TOTP, a passkey, an e-mail code, or a recovery code.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AuthTokenResponse' example: success: true data: token_type: Bearer access_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.YBCLu1qW1Xp1suAI9VcUADH4NzoFBhqWJYMK6nKqmjMynaPox92mZ8wTM3FtC9BLT5HPWvfFW5n0AF6wx7bEuXcl8PtnBn6DTnDM refresh_token: 1|X92mxzpThc43WsrjNAZfjO58aDL4WbFbwYoCQRMC expires_in: 1800 account: acc_03gb9a796thtl6untrsf4893vczmp53b message: 'Logged in successfully' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] Authentication' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/VerifyLoginFactorRequest' security: [] /api/v1/auth/factor/recovery: post: summary: 'Start Factor Recovery' operationId: postApiV1AuthFactorRecovery description: 'Request recovery guidance without revealing whether the account exists.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object properties: success: type: boolean examples: - true message: type: string examples: - 'If the account exists, recovery instructions will be sent.' examples: - success: true message: 'If the account exists, recovery instructions will be sent.' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] Authentication' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/StartFactorRecoveryRequest' security: [] /api/v1/auth/logout: post: summary: Logout operationId: postApiV1AuthLogout description: 'Revoke current refresh token and invalidate session.' parameters: [] responses: 204: description: '' content: application/json: schema: $ref: '#/components/schemas/AuthTokenResponse' example: success: true data: token_type: Bearer access_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.YBCLu1qW1Xp1suAI9VcUADH4NzoFBhqWJYMK6nKqmjMynaPox92mZ8wTM3FtC9BLT5HPWvfFW5n0AF6wx7bEuXcl8PtnBn6DTnDM refresh_token: 1|X92mxzpThc43WsrjNAZfjO58aDL4WbFbwYoCQRMC expires_in: 1800 account: acc_03gb9a796thtl6untrsf4893vczmp53b message: 'Logged out successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] Authentication' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/LogoutRequest' /api/v1/auth/password/forgot: post: summary: 'Forgot Password' operationId: postApiV1AuthPasswordForgot description: 'Request a password reset link. Always returns success to prevent account enumeration.' parameters: [] responses: 200: description: 'Password reset link sent (or email not found - same response for security).' content: application/json: schema: type: object properties: data: type: - string - 'null' examples: - null success: type: boolean examples: - true message: type: string examples: - 'If an account exists with this email, a password reset link has been sent.' examples: - data: null success: true message: 'If an account exists with this email, a password reset link has been sent.' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] Password Reset' security: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ForgotPasswordRequest' /api/v1/auth/password/reset: post: summary: 'Reset Password' operationId: postApiV1AuthPasswordReset description: 'Reset password using a valid token received via email.' parameters: [] responses: 200: description: 'Password reset successfully.' content: application/json: schema: type: object properties: data: type: - string - 'null' examples: - null success: type: boolean examples: - true message: type: string examples: - 'Password has been reset successfully.' examples: - data: null success: true message: 'Password has been reset successfully.' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] Password Reset' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ResetPasswordRequest' security: [] /api/v1/auth/token: post: summary: 'Mint Account Token' operationId: postApiV1AuthToken description: 'Mint a first-party account JWT. Requires a personal access token with the jwt:mint ability. The account must be the PAT owner.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/MintTokenResponse' example: success: true data: token_type: Bearer access_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.YBCLu1qW1Xp1suAI9VcUADH4NzoFBhqWJYMK6nKqmjMynaPox92mZ8wTM3FtC9BLT5HPWvfFW5n0AF6wx7bEuXcl8PtnBn6DTnDM expires_in: 3600 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] JWT Tokens' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MintAccountTokenRequest' /api/v1/auth/permissions: get: summary: 'List permissions' operationId: getApiV1AuthPermissions description: 'Returns the effective permissions granted by the current account token.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/PermissionListResponse' example: success: true data: type: website id: web_0123456789abcdefghijklmnopqrstuv permissions: - 'ai:use' - 'website:show' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] JWT Tokens' /api/v1/auth/permissions/check: post: summary: 'Check permissions' operationId: postApiV1AuthPermissionsCheck description: 'Maps each requested permission name to whether the current account token grants it.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/PermissionCheckResponse' example: success: true data: type: website id: web_0123456789abcdefghijklmnopqrstuv permissions: 'ai:use': true 'website:delete': false 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] JWT Tokens' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CheckPermissionsRequest' '/api/v1/auth/permissions/website/{website}': get: summary: 'List website permissions' operationId: getApiV1AuthPermissionsWebsiteByWebsite description: 'Returns effective permissions for one website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/PermissionListResponse' example: success: true data: type: website id: web_0123456789abcdefghijklmnopqrstuv permissions: - 'ai:use' - 'website:show' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] JWT Tokens' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_0123456789abcdefghijklmnopqrstuv '/api/v1/auth/permissions/library/{library}': get: summary: 'List library permissions' operationId: getApiV1AuthPermissionsLibraryByLibrary description: 'Returns effective permissions for one library.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryPermissionListResponse' example: success: true data: type: library id: lib_0123456789abcdefghijklmnopqrstuv permissions: - 'ai:use' - 'library:show' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] JWT Tokens' parameters: - in: path name: library description: 'Prefixed library ID.' required: true schema: type: string examples: - lib_0123456789abcdefghijklmnopqrstuv '/api/v1/auth/permissions/check/website/{website}': post: summary: 'Check website permissions' operationId: postApiV1AuthPermissionsCheckWebsiteByWebsite description: 'Checks permission names for one website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/PermissionCheckResponse' example: success: true data: type: website id: web_0123456789abcdefghijklmnopqrstuv permissions: 'ai:use': true 'website:delete': false 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] JWT Tokens' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CheckPermissionsRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_0123456789abcdefghijklmnopqrstuv '/api/v1/auth/permissions/check/library/{library}': post: summary: 'Check library permissions' operationId: postApiV1AuthPermissionsCheckLibraryByLibrary description: 'Checks permission names for one library.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryPermissionCheckResponse' example: success: true data: type: library id: lib_0123456789abcdefghijklmnopqrstuv permissions: 'ai:use': true 'library:delete': false 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] JWT Tokens' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CheckPermissionsRequest' parameters: - in: path name: library description: 'Prefixed library ID.' required: true schema: type: string examples: - lib_0123456789abcdefghijklmnopqrstuv /api/v1/auth/permissions/resources: get: summary: 'List permission resources' operationId: getApiV1AuthPermissionsResources description: 'Returns discoverable website and library permission contexts.' parameters: - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/PermissionListPaginatedResponse' example: success: true data: - type: website id: web_0123456789abcdefghijklmnopqrstuv permissions: - 'ai:use' - 'website:show' - type: website id: web_0123456789abcdefghijklmnopqrstuv permissions: - 'ai:use' - 'website:show' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] JWT Tokens' /api/v1/auth/token/jwks: get: summary: 'Get JWKS' operationId: getApiV1AuthTokenJwks description: 'Get JWT public key in JWKS (JSON Web Key Set) format for token verification.' parameters: [] responses: 200: description: 'JWKS returned.' content: application/json: schema: type: object properties: keys: type: array items: type: object properties: kty: type: string examples: - RSA 'n': type: string examples: - ... e: type: string examples: - AQAB alg: type: string examples: - RS256 use: type: string examples: - sig examples: - - kty: RSA 'n': ... e: AQAB alg: RS256 use: sig examples: - keys: - kty: RSA 'n': ... e: AQAB alg: RS256 use: sig 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] JWT Tokens' security: [] /api/v1/auth/token/public-key: get: summary: 'Get Public Key' operationId: getApiV1AuthTokenPublicKey description: 'Get JWT public key in PEM format for token verification.' parameters: [] responses: 200: description: 'PEM public key returned.' content: text/plain: schema: type: string examples: - '-----BEGIN PUBLIC KEY-----\nMIIBI...' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] JWT Tokens' security: [] /api/v1/me/tokens: get: summary: 'List Tokens' operationId: getApiV1MeTokens description: 'Get all personal access tokens for the authenticated account.' parameters: - in: query name: search description: 'Search term (searches name).' required: false schema: type: string description: 'Search term (searches name).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/PersonalAccessTokenPaginatedResponse' example: success: true data: - id: pat_YBCLu1qW1Xp1suAI9VcUADH4NzoFBhqW name: api-token abilities: - '*' created_at: '2026-01-01T00:00:00+00:00' expires_at: '2026-02-01T00:00:00+00:00' last_used_at: null - id: pat_YBCLu1qW1Xp1suAI9VcUADH4NzoFBhqW name: api-token abilities: - '*' created_at: '2026-01-01T00:00:00+00:00' expires_at: '2026-02-01T00:00:00+00:00' last_used_at: null meta: current_page: 1 last_page: 5 per_page: 15 total: 73 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] Personal Access Tokens' post: summary: 'Create Token' operationId: postApiV1MeTokens description: 'Create a new personal access token.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/PersonalAccessTokenCreatedResponse' example: success: true data: token: 1|YBCLu1qW1Xp1suAI9VcUADH4NzoFBhqWJYMK6nKq id: pat_ynaPox92mZ8wTM3FtC9BLT5HPWvfFW5n message: 'Token created successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] Personal Access Tokens' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreatePersonalAccessTokenRequest' '/api/v1/me/tokens/{id}': delete: summary: 'Delete Token' operationId: deleteApiV1MeTokensById description: 'Revoke and delete a personal access token.' parameters: [] responses: 204: description: 'Token deleted.' content: text/plain: schema: type: string examples: - '' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] Personal Access Tokens' parameters: - in: path name: id description: 'Public token ID to delete.' required: true schema: type: string examples: - pat_0123456789abcdef0123456789abcdef /api/v1/auth/sso/create-code: post: summary: 'Create SSO Code' operationId: postApiV1AuthSsoCreateCode description: 'Create a one-time code for SSO redirect to another frontend service.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/SSOCodeResponse' example: success: true data: code: YBCLu1qW1Xp1suAI9VcUADH4NzoFBhqW expires_in: 60 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] SSO' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateSSOCodeRequest' /api/v1/auth/sso/exchange: post: summary: 'Exchange SSO Code' operationId: postApiV1AuthSsoExchange description: 'Exchange a one-time SSO code for access and refresh tokens.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AuthTokenResponse' example: success: true data: token_type: Bearer access_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.YBCLu1qW1Xp1suAI9VcUADH4NzoFBhqWJYMK6nKqmjMynaPox92mZ8wTM3FtC9BLT5HPWvfFW5n0AF6wx7bEuXcl8PtnBn6DTnDM refresh_token: 1|X92mxzpThc43WsrjNAZfjO58aDL4WbFbwYoCQRMC expires_in: 1800 account: acc_03gb9a796thtl6untrsf4893vczmp53b 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] SSO' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ExchangeSSOCodeRequest' security: [] /api/v1/auth/impersonation/end: post: summary: 'End Account Impersonation' operationId: postApiV1AuthImpersonationEnd description: 'Use the original staff login refresh token. Returns a fresh staff JWT and retains the original refresh credential.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountImpersonationReturnResponse' example: success: true data: token_type: Bearer access_token: eyJhbGciOiJSUzI1NiJ9.example.signature refresh_token: null expires_in: 3600 account: acc_ybclU1Qw1xP1SUai9vCuadh4nZOfbHQw 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] Impersonation' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/EndAccountImpersonationRequest' '/api/v1/accounts/{account}/impersonate': post: summary: 'Start Account Impersonation' operationId: postApiV1AccountsByAccountImpersonate description: 'Requires the original staff login refresh token and current account impersonation authority.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountImpersonationResponse' example: success: true data: token_type: Bearer access_token: eyJhbGciOiJSUzI1NiJ9.example.signature refresh_token: 1|YBCLu1qW1Xp1suAI9VcUADH4NzoFBhqWJYMK6nKq expires_in: 3600 account: acc_ynaPox92mZ8wTM3FtC9BLT5HPWvfFW5n session_id: pat_6wx7bEuXcl8PtnBn6DTnDMCNYX92mxzp 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 409: description: '' content: application/json: schema: type: object properties: success: type: boolean examples: - false message: type: string examples: - 'Account impersonation is already active' meta: type: object properties: session_id: type: string examples: - pat_0123456789abcdef0123456789abcdef examples: - success: false message: 'Account impersonation is already active' meta: session_id: pat_0123456789abcdef0123456789abcdef 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] Impersonation' parameters: - in: path name: account description: 'Target public account ID.' required: true schema: type: string examples: - acc_0123456789abcdef0123456789abcdef /api/v1/oauth/clients: get: summary: 'List Clients' operationId: getApiV1OauthClients description: 'Get all OAuth clients owned by the authenticated account.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/OauthClientCollectionResponse' example: success: true data: - id: cli_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: 'Rowe-Runolfsdottir App' type: confidential redirect_uris: - 'https://example.com/callback' is_active: true component: files created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: cli_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: 'Rowe-Runolfsdottir App' type: confidential redirect_uris: - 'https://example.com/callback' is_active: true component: files created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] OAuth Clients' post: summary: 'Create Client' operationId: postApiV1OauthClients description: 'Register a new OAuth client.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/OauthClientCreatedResponse' example: success: true data: id: cli_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: 'Rowe-Runolfsdottir App' type: confidential client_secret: KqmjMynaPox92mZ8wTM3FtC9BLT5HPWvfFW5n0AF6wx7bEuXcl8PtnBn6DTnDMCN redirect_uris: - 'https://example.com/callback' is_active: true component: files created_at: '2026-01-01T00:00:00+00:00' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] OAuth Clients' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateOAuthClientRequest' /api/v1/oauth/clients/batch: post: summary: 'Batch Clients' operationId: postApiV1OauthClientsBatch description: 'Create, update, and delete OAuth clients in a single request.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] OAuth Clients' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/BatchOAuthClientsRequest' '/api/v1/oauth/clients/{oauth_client}': get: summary: 'Get Client' operationId: getApiV1OauthClientsByOauthClient description: 'Get details of a specific OAuth client.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/OauthClientResponse' example: success: true data: id: cli_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: 'Rowe-Runolfsdottir App' type: confidential redirect_uris: - 'https://example.com/callback' is_active: true component: files created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] OAuth Clients' put: summary: 'Update Client' operationId: putApiV1OauthClientsByOauthClient description: 'Update an existing OAuth client.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/OauthClientResponse' example: success: true data: id: cli_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: 'Rowe-Runolfsdottir App' type: confidential redirect_uris: - 'https://example.com/callback' is_active: true component: files created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] OAuth Clients' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateOAuthClientRequest' delete: summary: 'Delete Client' operationId: deleteApiV1OauthClientsByOauthClient description: 'Delete an OAuth client and revoke all associated grants.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] OAuth Clients' parameters: - in: path name: oauth_client description: '' required: true schema: type: string examples: - cli_ybclU1Qw1xP1SUai9vCuadh4nZOfbHQw '/api/v1/oauth/clients/{oauth_client}/rotate-secret': post: summary: 'Rotate Secret' operationId: postApiV1OauthClientsByOauthClientRotateSecret description: 'Generate a new client secret. Previous secret is invalidated.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/OauthClientCreatedResponse' example: success: true data: id: cli_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: 'Rowe-Runolfsdottir App' type: confidential client_secret: KqmjMynaPox92mZ8wTM3FtC9BLT5HPWvfFW5n0AF6wx7bEuXcl8PtnBn6DTnDMCN redirect_uris: - 'https://example.com/callback' is_active: true component: files created_at: '2026-01-01T00:00:00+00:00' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] OAuth Clients' parameters: - in: path name: oauth_client description: '' required: true schema: type: string examples: - cli_ybclU1Qw1xP1SUai9vCuadh4nZOfbHQw /api/v1/oauth/grants: get: summary: 'List Authorized Apps' operationId: getApiV1OauthGrants description: 'Get all OAuth apps the authenticated user has authorized.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/OauthGrantCollectionResponse' example: success: true data: - id: 2H8Q0Z8R1H5V0WW2D70E2N58NF client_id: cli_d84bq84oju80peu12xkf9k6n0wbsnzve client_name: 'Bins and Sons App' scopes: - role: 'console:account' created_at: '2026-01-01T00:00:00+00:00' - id: 2H8Q0Z8R1H5V0WW2D70E2N58NF client_id: cli_d84bq84oju80peu12xkf9k6n0wbsnzve client_name: 'Bins and Sons App' scopes: - role: 'console:account' created_at: '2026-01-01T00:00:00+00:00' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] OAuth Grants' '/api/v1/oauth/grants/{grant}': delete: summary: 'Revoke Grant' operationId: deleteApiV1OauthGrantsByGrant description: 'Revoke an OAuth app authorization, its authorization codes, and refresh tokens. Existing access JWTs remain valid until expiry.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] OAuth Grants' parameters: - in: path name: grant description: 'The grant.' required: true schema: type: string examples: - aspernatur /oauth/authorize: get: summary: 'Authorization Info' operationId: getOauthAuthorize description: 'Validate authorization request and return info for consent screen.' parameters: - in: query name: client_id description: '' required: true schema: type: string description: '' examples: - aspernatur - in: query name: redirect_uri description: '' required: true schema: type: string description: '' examples: - aspernatur - in: query name: response_type description: '' required: true schema: type: string description: '' examples: - code - in: query name: scope description: '' required: true schema: type: string description: '' examples: - aspernatur - in: query name: state description: '' required: false schema: type: string description: '' examples: - aspernatur - in: query name: code_challenge description: 'Required for public clients.' required: false schema: type: string description: 'Required for public clients.' examples: - aspernatur - in: query name: code_challenge_method description: 'Required when code_challenge is supplied.' required: false schema: type: string description: 'Required when code_challenge is supplied.' examples: - S256 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AuthorizeInfoResponse' example: success: true data: client_id: cli_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 client_name: 'Rowe-Runolfsdottir App' scopes: - role: 'console:account' roles_requiring_resource_selection: [] redirect_uri: 'https://example.com/callback' state: KqmjMynaPox92mZ8wTM3FtC9BLT5HPWv 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] OAuth Protocol' post: summary: 'Approve Authorization' operationId: postOauthAuthorize description: 'User approves the authorization request. Returns redirect with code.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/OauthRedirectResponse' example: success: true data: redirect_uri: 'com.example.app:/callback?tenant=one' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] OAuth Protocol' delete: summary: 'Deny Authorization' operationId: deleteOauthAuthorize description: 'Deny authorization for an active client and its exact registered callback. Invalid clients or callbacks return 422 without a redirect destination.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/OauthRedirectResponse' example: success: true data: redirect_uri: 'com.example.app:/callback?tenant=one' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[auth] OAuth Protocol' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DenyOAuthAuthorizationRequest' /api/v1/accounts: get: summary: 'List Accounts' operationId: getApiV1Accounts description: 'Get accounts with pagination. Internal component tokens have read-only access.' parameters: - in: query name: search description: 'Search term (searches name, surname, email).' required: false schema: type: string description: 'Search term (searches name, surname, email).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 15 - in: query name: include description: 'Comma-separated relations to include.' required: false schema: type: string description: 'Comma-separated relations to include.' examples: - 'websites,settings' responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountPaginatedResponse' example: success: true data: - id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - 'console:account' permissions: - 'ai:use' websites_count: 3 websites: null tags: - id: tag_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' avatar_file_id: null - id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - 'console:account' permissions: - 'ai:use' websites_count: 3 websites: null tags: - id: tag_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' avatar_file_id: null meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Accounts retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Accounts' post: summary: 'Create Account' operationId: postApiV1Accounts description: "Create an account and its false-default 's library." parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountResponse' example: success: true data: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - 'console:account' permissions: - 'ai:use' websites_count: 3 websites: null tags: - id: tag_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' avatar_file_id: null message: 'Account created successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Accounts' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateAccountRequest' '/api/v1/accounts/{account}': get: summary: 'Get Account' operationId: getApiV1AccountsByAccount description: 'Get an account by ID. Internal component reads include target global permissions and no mutation actions.' parameters: - in: query name: include description: 'Comma-separated relations to include (websites, settings).' required: false schema: type: string description: 'Comma-separated relations to include (websites, settings).' examples: - 'websites,settings' responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountResponse' example: success: true data: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - 'console:account' permissions: - 'ai:use' websites_count: 3 websites: null tags: - id: tag_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' avatar_file_id: null message: 'Account retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Accounts' put: summary: 'Update Account' operationId: putApiV1AccountsByAccount description: 'Update an existing account.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountResponse' example: success: true data: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - 'console:account' permissions: - 'ai:use' websites_count: 3 websites: null tags: - id: tag_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' avatar_file_id: null message: 'Account updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Accounts' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateAccountRequest' patch: summary: 'Update Account' operationId: patchApiV1AccountsByAccount description: 'Update an existing account.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountResponse' example: success: true data: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - 'console:account' permissions: - 'ai:use' websites_count: 3 websites: null tags: - id: tag_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' avatar_file_id: null message: 'Account updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Accounts' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateAccountRequest' delete: summary: 'Delete Account' operationId: deleteApiV1AccountsByAccount description: 'Delete an account.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountResponse' example: success: true data: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - 'console:account' permissions: - 'ai:use' websites_count: 3 websites: null tags: - id: tag_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' avatar_file_id: null message: 'Account deleted successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Accounts' parameters: - in: path name: account description: 'Prefixed account ID.' required: true schema: type: string examples: - acc_abc123 /api/v1/accounts/batch: post: summary: 'Batch Accounts' operationId: postApiV1AccountsBatch description: 'Create, update, and delete accounts in a single request.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Accounts' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/BatchAccountsRequest' '/api/v1/accounts/{account}/owned': get: summary: 'Get Account Ownership Blockers' operationId: getApiV1AccountsByAccountOwned description: 'List the websites and standalone libraries an account owns.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Accounts' parameters: - in: path name: account description: 'Prefixed account ID.' required: true schema: type: string examples: - acc_abc123 '/api/v1/accounts/{account}/roles': put: summary: 'Replace Account Roles' operationId: putApiV1AccountsByAccountRoles description: 'Replace global Console roles for an account. Website and Library roles are unchanged.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountResponse' example: success: true data: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - 'console:account' permissions: - 'ai:use' websites_count: 3 websites: null tags: - id: tag_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' avatar_file_id: null message: 'Account roles replaced successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Accounts' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ReplaceAccountRolesRequest' parameters: - in: path name: account description: 'Prefixed account ID.' required: true schema: type: string examples: - acc_abc123 '/api/v1/accounts/{account}/websites': get: summary: 'List Account Websites' operationId: getApiV1AccountsByAccountWebsites description: 'Search and list websites attached to an account, with optional pagination.' parameters: - in: query name: search description: 'Search term (searches name and domain).' required: false schema: type: string description: 'Search term (searches name and domain).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number. Supplying this enables pagination.' required: false schema: type: integer description: 'Page number. Supplying this enables pagination.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100). Supplying this enables pagination.' required: false schema: type: integer description: 'Items per page (max 100). Supplying this enables pagination.' examples: - 15 responses: 200: description: 'Website collection. Paginated requests also include pagination metadata.' content: application/json: schema: $ref: '#/components/schemas/WebsiteCollectionResponse' example: success: true data: - id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Websites retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Accounts' parameters: - in: path name: account description: 'Account prefixed ID.' required: true schema: type: string examples: - acc_abc123 '/api/v1/accounts/{account}/libraries': get: summary: 'List Account Libraries' operationId: getApiV1AccountsByAccountLibraries description: 'List libraries attached to an account.' parameters: - in: query name: search description: 'Search term (searches name).' required: false schema: type: string description: 'Search term (searches name).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 25 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryPaginatedResponse' example: success: true data: - id: lib_cb21a922bbf5a66c71a8cff2f98df9c0 name: 'reprehenderit qui' is_system: false is_website_library: false items_count: 25 websites_count: 7 owner_account_id: acc_cc1ae9ad4b9ceb043cb73e5ffd373ad3 owner: firstname: Susana lastname: Grimes email: upton.marcelina@gmail.com roles: - 'library:owner' tags: - id: tag_w6pgb8pnh17o5r1byozkr5qglt1l740z name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: lib_cb21a922bbf5a66c71a8cff2f98df9c0 name: 'reprehenderit qui' is_system: false is_website_library: false items_count: 25 websites_count: 7 owner_account_id: acc_cc1ae9ad4b9ceb043cb73e5ffd373ad3 owner: firstname: Susana lastname: Grimes email: upton.marcelina@gmail.com roles: - 'library:owner' tags: - id: tag_w6pgb8pnh17o5r1byozkr5qglt1l740z name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Libraries retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Accounts' parameters: - in: path name: account description: 'Account prefixed ID.' required: true schema: type: string examples: - acc_abc123 '/api/v1/accounts/{account}/enable': post: summary: 'Enable Account' operationId: postApiV1AccountsByAccountEnable description: 'Enable a disabled account.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountResponse' example: success: true data: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - 'console:account' permissions: - 'ai:use' websites_count: 3 websites: null tags: - id: tag_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' avatar_file_id: null message: 'Account enabled successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Accounts' parameters: - in: path name: account description: 'Prefixed account ID.' required: true schema: type: string examples: - acc_abc123 '/api/v1/accounts/{account}/disable': post: summary: 'Disable Account' operationId: postApiV1AccountsByAccountDisable description: 'Disable an enabled account.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountResponse' example: success: true data: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - 'console:account' permissions: - 'ai:use' websites_count: 3 websites: null tags: - id: tag_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' avatar_file_id: null message: 'Account disabled successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Accounts' parameters: - in: path name: account description: 'Prefixed account ID.' required: true schema: type: string examples: - acc_abc123 '/api/v1/accounts/{account}/change-password': post: summary: 'Change Password' operationId: postApiV1AccountsByAccountChangePassword description: 'Force-set a new password for an account. No current password required (admin action). Revokes all active sessions.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountResponse' example: success: true data: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - 'console:account' permissions: - 'ai:use' websites_count: 3 websites: null tags: - id: tag_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' avatar_file_id: null message: 'Password changed successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Accounts' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ChangeAccountPasswordRequest' parameters: - in: path name: account description: 'Prefixed account ID.' required: true schema: type: string examples: - acc_abc123 '/api/v1/accounts/{account}/password-reset': post: summary: 'Password Reset Email' operationId: postApiV1AccountsByAccountPasswordReset description: 'Send a password reset email for an account and return the generated URL.' parameters: [] responses: 200: description: 'Password reset email sent.' content: application/json: schema: $ref: '#/components/schemas/PasswordResetUrlResponse' example: success: true data: url: 'https://console.app.solidpixels.com/auth/reset-password/wIy1Ar7VCGBw9n7mOybi9=.pOX92Mz8Wtm3fTc9blt5hpw' message: 'Password reset email sent' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Accounts' parameters: - in: path name: account description: 'Prefixed account ID.' required: true schema: type: string examples: - acc_abc123 '/api/v1/accounts/{account}/password-reset-link': post: summary: 'Password Reset Link' operationId: postApiV1AccountsByAccountPasswordResetLink description: 'Generate a password reset URL for an account without sending an email.' parameters: [] responses: 200: description: 'Password reset link generated.' content: application/json: schema: $ref: '#/components/schemas/PasswordResetUrlResponse' example: success: true data: url: 'https://console.app.solidpixels.com/auth/reset-password/wIy1Ar7VCGBw9n7mOybi9=.pOX92Mz8Wtm3fTc9blt5hpw' message: 'Password reset link generated' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Accounts' parameters: - in: path name: account description: 'Prefixed account ID.' required: true schema: type: string examples: - acc_abc123 /api/v1/me: get: summary: 'Get Profile' operationId: getApiV1Me description: 'Get the authenticated account profile.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountResponse' example: success: true data: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - 'console:account' permissions: - 'ai:use' websites_count: 3 websites: null tags: - id: tag_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' avatar_file_id: null message: 'Account retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Current Account' put: summary: 'Update Profile' operationId: putApiV1Me description: 'Update the authenticated account profile.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountResponse' example: success: true data: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - 'console:account' permissions: - 'ai:use' websites_count: 3 websites: null tags: - id: tag_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' avatar_file_id: null message: 'Account updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Current Account' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateCurrentAccountRequest' /api/v1/me/factors: get: summary: 'List Two-Factor Methods' operationId: getApiV1MeFactors description: 'List the current account factors and unused recovery-code count.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/ListAccountFactorsResponse' example: success: true data: factors: - id: fac_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 type: passkey name: Laptop last_used_at: null recovery_codes_remaining: 10 available_types: - totp - passkey 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Current Account' /api/v1/me/factors/assertion-options: post: summary: 'Get Management Assertion Options' operationId: postApiV1MeFactorsAssertionOptions description: 'Create passkey assertion options for a management proof.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/ManagementAssertionOptionsResponse' example: success: true data: token: ybclU1Qw1xP1SUai9vCuadh4nZOfbHQwjymk6NkQMJmYNApOX92Mz8Wtm3fTc9bl options: challenge: pQjJlQ5jgM3aEfL3yYr_hKfhP7pSr575EO1G5LgqD7f rpId: solid.test allowCredentials: - type: public-key id: credential-id userVerification: preferred timeout: 60000 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Current Account' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GetManagementAssertionOptionsRequest' /api/v1/me/factors/totp: post: summary: 'Start TOTP Enrollment' operationId: postApiV1MeFactorsTotp description: 'Create a pending TOTP enrollment challenge.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/TotpEnrollmentResponse' example: success: true data: token: ybclU1Qw1xP1SUai9vCuadh4nZOfbHQwjymk6NkQMJmYNApOX92Mz8Wtm3fTc9bl otpauth_uri: 'otpauth://totp/Solidpixels%3Auser%40example.com?secret=ABC&issuer=Solidpixels' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Current Account' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/StartTotpEnrollmentRequest' /api/v1/me/factors/totp/confirm: post: summary: 'Confirm TOTP Enrollment' operationId: postApiV1MeFactorsTotpConfirm description: 'Activate a pending TOTP enrollment.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/FactorActivationResponse' example: success: true data: factor: id: fac_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 type: passkey name: Laptop last_used_at: null recovery_codes: - srpoh2mn-gtokcck2tfqkdhbazymhvb-fqwyp6injwfrsls 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Current Account' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ConfirmTotpEnrollmentRequest' /api/v1/me/factors/passkey/options: post: summary: 'Start Passkey Enrollment' operationId: postApiV1MeFactorsPasskeyOptions description: 'Create WebAuthn options for a pending passkey enrollment.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/PasskeyEnrollmentOptionsResponse' example: success: true data: token: ybclU1Qw1xP1SUai9vCuadh4nZOfbHQwjymk6NkQMJmYNApOX92Mz8Wtm3fTc9bl options: challenge: pQjJlQ5jgM3aEfL3yYr_hKfhP7pSr575EO1G5LgqD7f rp: name: Solidpixels id: solid.test user: id: account-id name: user@example.com displayName: User pubKeyCredParams: - type: public-key alg: -7 attestation: none excludeCredentials: [] 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Current Account' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/StartPasskeyEnrollmentRequest' /api/v1/me/factors/passkey: post: summary: 'Confirm Passkey Enrollment' operationId: postApiV1MeFactorsPasskey description: 'Activate a pending passkey enrollment.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/FactorActivationResponse' example: success: true data: factor: id: fac_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 type: passkey name: Laptop last_used_at: null recovery_codes: - srpoh2mn-gtokcck2tfqkdhbazymhvb-fqwyp6injwfrsls 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Current Account' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ConfirmPasskeyEnrollmentRequest' /api/v1/me/factors/email: post: summary: 'Start E-mail Code Enrollment' operationId: postApiV1MeFactorsEmail description: 'Create a pending e-mail code enrollment challenge and send the code.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/EmailFactorEnrollmentStartedResponse' example: success: true data: token: ybclU1Qw1xP1SUai9vCuadh4nZOfbHQwjymk6NkQMJmYNApOX92Mz8Wtm3fTc9bl resend_in_seconds: 60 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Current Account' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/StartEmailEnrollmentRequest' /api/v1/me/factors/email/confirm: post: summary: 'Confirm E-mail Code Enrollment' operationId: postApiV1MeFactorsEmailConfirm description: 'Activate a pending e-mail code enrollment.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/FactorActivationResponse' example: success: true data: factor: id: fac_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 type: passkey name: Laptop last_used_at: null recovery_codes: - srpoh2mn-gtokcck2tfqkdhbazymhvb-fqwyp6injwfrsls 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Current Account' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ConfirmEmailEnrollmentRequest' /api/v1/me/factors/email/send: post: summary: 'Resend E-mail Code' operationId: postApiV1MeFactorsEmailSend description: 'Resend the enrollment code for a pending e-mail code challenge.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/EmailFactorSentResponse' example: success: true data: resend_in_seconds: 60 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Current Account' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ResendEmailEnrollmentRequest' '/api/v1/me/factors/{id}/remove': post: summary: 'Remove Two-Factor Method' operationId: postApiV1MeFactorsByIdRemove description: 'Remove an account-owned factor.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Current Account' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RemoveAccountFactorRequest' parameters: - in: path name: id description: 'Factor prefixed ID.' required: true schema: type: string examples: - fac_example /api/v1/me/recovery-codes: post: summary: 'Regenerate Recovery Codes' operationId: postApiV1MeRecoveryCodes description: 'Replace all recovery codes and return the new codes once.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/RecoveryCodesResponse' example: success: true data: recovery_codes: - abcde-fghij-klmno-pqrst-uvwxy-23456-72345-abcde - abcde-fghij-klmno-pqrst-uvwxy-23456-72345-abcde - abcde-fghij-klmno-pqrst-uvwxy-23456-72345-abcde - abcde-fghij-klmno-pqrst-uvwxy-23456-72345-abcde - abcde-fghij-klmno-pqrst-uvwxy-23456-72345-abcde - abcde-fghij-klmno-pqrst-uvwxy-23456-72345-abcde - abcde-fghij-klmno-pqrst-uvwxy-23456-72345-abcde - abcde-fghij-klmno-pqrst-uvwxy-23456-72345-abcde - abcde-fghij-klmno-pqrst-uvwxy-23456-72345-abcde - abcde-fghij-klmno-pqrst-uvwxy-23456-72345-abcde 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Current Account' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RegenerateRecoveryCodesRequest' /api/v1/me/settings: get: summary: 'Get Settings' operationId: getApiV1MeSettings description: 'Get all settings for the authenticated account as a flat key-value map.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Current Account Settings' put: summary: 'Update Settings' operationId: putApiV1MeSettings description: 'Upsert settings for the authenticated account. Accepts a partial flat object.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Current Account Settings' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/UpdateCurrentAccountSettingsRequest' '/api/v1/accounts/{account}/settings': get: summary: 'List Account Settings' operationId: getApiV1AccountsByAccountSettings description: 'List configuration settings for an account.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountSettingPaginatedResponse' example: success: true data: - id: aset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 group: default type: text key: theme value: dark created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: aset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 group: default type: text key: theme value: dark created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Account settings retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Account Settings' post: summary: 'Create Account Setting' operationId: postApiV1AccountsByAccountSettings description: 'Create a configuration setting for an account.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountSettingResponse' example: success: true data: id: aset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 group: default type: text key: theme value: dark created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Account setting created successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Account Settings' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateAccountSettingRequest' parameters: - in: path name: account description: 'Prefixed account ID.' required: true schema: type: string examples: - acc_abc123 '/api/v1/accounts/{account}/settings/{account_setting}': get: summary: 'Get Account Setting' operationId: getApiV1AccountsByAccountSettingsByAccountSetting description: 'Get a specific account setting.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountSettingResponse' example: success: true data: id: aset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 group: default type: text key: theme value: dark created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Account setting retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Account Settings' put: summary: 'Update Account Setting' operationId: putApiV1AccountsByAccountSettingsByAccountSetting description: 'Update an account setting value.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountSettingResponse' example: success: true data: id: aset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 group: default type: text key: theme value: dark created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Account setting updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Account Settings' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateAccountSettingRequest' delete: summary: 'Delete Account Setting' operationId: deleteApiV1AccountsByAccountSettingsByAccountSetting description: 'Delete an account setting.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountSettingResponse' example: success: true data: id: aset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 group: default type: text key: theme value: dark created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Account setting deleted successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Account Settings' parameters: - in: path name: account description: 'Prefixed account ID.' required: true schema: type: string examples: - acc_abc123 - in: path name: account_setting description: 'Prefixed account setting ID.' required: true schema: type: string examples: - aset_abc123 '/api/v1/accounts/{account}/settings/batch': post: summary: 'Batch Account Settings' operationId: postApiV1AccountsByAccountSettingsBatch description: 'Create, update, and delete account settings in a single request.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Account Settings' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/BatchAccountSettingsRequest' parameters: - in: path name: account description: 'Prefixed account ID.' required: true schema: type: string examples: - acc_abc123 '/api/v1/accounts/{account}/admin-settings': get: summary: 'List Account Admin Settings' operationId: getApiV1AccountsByAccountAdminSettings description: 'List the admin-managed configuration settings for an account.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountAdminSettingResponse' example: success: true data: key: factors.email.enabled value: true message: 'Admin settings retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Account Admin Settings' put: summary: 'Upsert Account Admin Setting' operationId: putApiV1AccountsByAccountAdminSettings description: 'Set the value of one registered admin setting for an account.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountAdminSettingResponse' example: success: true data: key: factors.email.enabled value: true message: 'Admin setting updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Account Admin Settings' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpsertAccountAdminSettingRequest' parameters: - in: path name: account description: 'Account prefixed ID.' required: true schema: type: string examples: - acc_abc123 '/api/v1/accounts/{account}/admin-settings/{key}': delete: summary: 'Delete Account Admin Setting' operationId: deleteApiV1AccountsByAccountAdminSettingsByKey description: 'Remove one registered admin setting for an account.' parameters: [] responses: 204: description: 'Admin setting deleted.' content: application/json: schema: type: - object - 'null' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[account] Account Admin Settings' parameters: - in: path name: account description: 'Account prefixed ID.' required: true schema: type: string examples: - acc_abc123 - in: path name: key description: 'Registered admin setting key.' required: true schema: type: string examples: - factors.email.enabled /api/v1/websites: get: summary: 'List Websites' operationId: getApiV1Websites description: 'Get all websites for the authenticated account.' parameters: - in: query name: search description: 'Search term (searches name, domain).' required: false schema: type: string description: 'Search term (searches name, domain).' examples: - aspernatur - in: query name: 'filter[domain_kind]' description: 'Filter by the default domain kind. Custom means own domain. Hosted means temporary domain. Omit for all domains. Invalid values return 422.' required: false schema: type: string description: 'Filter by the default domain kind. Custom means own domain. Hosted means temporary domain. Omit for all domains. Invalid values return 422.' enum: - hosted - custom examples: - custom - in: query name: 'filter[plan]' description: 'Filter by trial, basic, advanced, or enterprise. Also accepts comma-separated plans. Filters combine with tags and search using AND.' required: false schema: type: string description: 'Filter by trial, basic, advanced, or enterprise. Also accepts comma-separated plans. Filters combine with tags and search using AND.' examples: - basic - in: query name: 'filter[plan][]' description: 'Alternative array form for multiple plans, combined with OR.' required: false schema: type: array description: 'Alternative array form for multiple plans, combined with OR.' items: type: string enum: - trial - basic - advanced - enterprise examples: - - basic - advanced - in: query name: sort description: 'Sort field, prefix with - for descending. Plan order is Trial, Basic, Advanced, Enterprise. Use -plan to reverse it. Equal values use the primary key ascending. Unsupported fields return 422.' required: false schema: type: string description: 'Sort field, prefix with - for descending. Plan order is Trial, Basic, Advanced, Enterprise. Use -plan to reverse it. Equal values use the primary key ascending. Unsupported fields return 422.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsitePaginatedResponse' example: success: true data: - id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Websites retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Websites' post: summary: 'Create Website' operationId: postApiV1Websites description: "Create a website with its own empty library, all system libraries, and the creator's selected defaults." parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteResponse' example: success: true data: id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website created successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Websites' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateWebsiteRequest' /api/v1/websites/batch: post: summary: 'Batch Websites' operationId: postApiV1WebsitesBatch description: 'Create, update, and delete websites in a single request.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 409: description: 'A provisioning operation conflicts with this request.' content: application/json: schema: type: object properties: message: type: string examples: - 'A conflicting operation is in progress.' meta: type: object properties: confirmation_id: type: string examples: - ecf_0123456789abcdef0123456789abcdef entity_type: type: string examples: - backup entity_id: type: string examples: - bak_0123456789abcdef0123456789abcdef operation_key: type: string examples: - restoration status: type: string examples: - pending examples: - message: 'A conflicting operation is in progress.' meta: confirmation_id: ecf_0123456789abcdef0123456789abcdef entity_type: backup entity_id: bak_0123456789abcdef0123456789abcdef operation_key: restoration status: pending 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Websites' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/BatchWebsitesRequest' '/api/v1/websites/{website}': get: summary: 'Get Website' operationId: getApiV1WebsitesByWebsite description: 'Get a specific website by ID.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteResponse' example: success: true data: id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Websites' put: summary: 'Update Website' operationId: putApiV1WebsitesByWebsite description: 'Update an existing website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteResponse' example: success: true data: id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Websites' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateWebsiteRequest' delete: summary: 'Delete Website' operationId: deleteApiV1WebsitesByWebsite description: 'Delete a website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteResponse' example: success: true data: id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website deleted successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 409: description: 'A provisioning operation conflicts with this request.' content: application/json: schema: type: object properties: message: type: string examples: - 'A conflicting operation is in progress.' meta: type: object properties: confirmation_id: type: string examples: - ecf_0123456789abcdef0123456789abcdef entity_type: type: string examples: - backup entity_id: type: string examples: - bak_0123456789abcdef0123456789abcdef operation_key: type: string examples: - restoration status: type: string examples: - pending examples: - message: 'A conflicting operation is in progress.' meta: confirmation_id: ecf_0123456789abcdef0123456789abcdef entity_type: backup entity_id: bak_0123456789abcdef0123456789abcdef operation_key: restoration status: pending 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Websites' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/impersonation-accounts': get: summary: 'List Builder Impersonation Accounts' operationId: getApiV1WebsitesByWebsiteImpersonationAccounts description: 'Use a first-party account JWT with current global website:impersonate authority. List eligible members with the owner first, then name and public account ID. Recovery, OAuth, and nested impersonation are rejected.' parameters: - in: query name: search description: 'Search member names and email addresses.' required: false schema: type: string description: 'Search member names and email addresses.' examples: - aspernatur - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Page size, default 25 and maximum 100.' required: false schema: type: integer description: 'Page size, default 25 and maximum 100.' examples: - 25 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteImpersonationAccountPaginatedResponse' example: success: true data: - id: acc_ybclU1Qw1xP1SUai9vCuadh4nZOfbHQw name: Aisha surname: Runolfsdottir email: grady16@example.org roles: - id: 1 name: 'website:owner' is_owner: true - id: acc_ybclU1Qw1xP1SUai9vCuadh4nZOfbHQw name: Aisha surname: Runolfsdottir email: grady16@example.org roles: - id: 1 name: 'website:owner' is_owner: true meta: current_page: 1 last_page: 5 per_page: 15 total: 73 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 409: description: 'A provisioning operation conflicts with this request.' content: application/json: schema: type: object properties: message: type: string examples: - 'A conflicting operation is in progress.' meta: type: object properties: confirmation_id: type: string examples: - ecf_0123456789abcdef0123456789abcdef entity_type: type: string examples: - backup entity_id: type: string examples: - bak_0123456789abcdef0123456789abcdef operation_key: type: string examples: - restoration status: type: string examples: - pending examples: - message: 'A conflicting operation is in progress.' meta: confirmation_id: ecf_0123456789abcdef0123456789abcdef entity_type: backup entity_id: bak_0123456789abcdef0123456789abcdef operation_key: restoration status: pending 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Administration' parameters: - in: path name: website description: 'Public website ID.' required: true schema: type: string examples: - web_0123456789abcdef0123456789abcdef '/api/v1/websites/{website}/clone': post: summary: 'Clone Website' operationId: postApiV1WebsitesByWebsiteClone description: 'Copy website-owned state and create a fresh empty website-owned library. Reuse source library attachments only when the library is not website-owned. No library folders or items are copied.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteResponse' example: success: true data: id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website cloned successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 409: description: 'A provisioning operation conflicts with this request.' content: application/json: schema: type: object properties: message: type: string examples: - 'A conflicting operation is in progress.' meta: type: object properties: confirmation_id: type: string examples: - ecf_0123456789abcdef0123456789abcdef entity_type: type: string examples: - backup entity_id: type: string examples: - bak_0123456789abcdef0123456789abcdef operation_key: type: string examples: - restoration status: type: string examples: - pending examples: - message: 'A conflicting operation is in progress.' meta: confirmation_id: ecf_0123456789abcdef0123456789abcdef entity_type: backup entity_id: bak_0123456789abcdef0123456789abcdef operation_key: restoration status: pending 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Administration' parameters: - in: path name: website description: 'Source prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/enable': post: summary: 'Enable Website' operationId: postApiV1WebsitesByWebsiteEnable description: 'Enable a disabled website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteResponse' example: success: true data: id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website enabled successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Administration' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/disable': post: summary: 'Disable Website' operationId: postApiV1WebsitesByWebsiteDisable description: 'Disable an enabled website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteResponse' example: success: true data: id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website disabled successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Administration' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/transfer': post: summary: 'Transfer Ownership' operationId: postApiV1WebsitesByWebsiteTransfer description: 'Transfer website ownership to another account.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteResponse' example: success: true data: id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website ownership transferred successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Administration' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TransferWebsiteOwnershipRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/maintenance': put: summary: 'Toggle Website Maintenance' operationId: putApiV1WebsitesByWebsiteMaintenance description: 'Enable or disable maintenance mode for a website.' parameters: [] responses: 200: description: 'Maintenance mode updated.' content: application/json: schema: $ref: '#/components/schemas/MaintenanceStateResponse' example: success: true data: enabled: false html: '

Maintenance

' message: 'Maintenance mode updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Administration' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MaintenanceStateRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/admin/impersonate/{account}/{website}': post: summary: 'Impersonate Website Account' operationId: postApiV1AdminImpersonateByAccountByWebsite description: 'Use a first-party account JWT with current global website:impersonate authority. Create a website-scoped CMS SSO session as the selected assigned account. Self-selection uses normal SSO. Recovery, OAuth, and nested impersonation are rejected.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteImpersonationResponse' example: success: true data: code: example-code expires_in: 60 url: 'https://cms.example.test/auth/sso?code=example-code' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 409: description: 'A provisioning operation conflicts with this request.' content: application/json: schema: type: object properties: message: type: string examples: - 'A conflicting operation is in progress.' meta: type: object properties: confirmation_id: type: string examples: - ecf_0123456789abcdef0123456789abcdef entity_type: type: string examples: - backup entity_id: type: string examples: - bak_0123456789abcdef0123456789abcdef operation_key: type: string examples: - restoration status: type: string examples: - pending examples: - message: 'A conflicting operation is in progress.' meta: confirmation_id: ecf_0123456789abcdef0123456789abcdef entity_type: backup entity_id: bak_0123456789abcdef0123456789abcdef operation_key: restoration status: pending 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Administration' parameters: - in: path name: account description: 'Prefixed target account ID.' required: true schema: type: string examples: - acc_abc123 - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/domains': get: summary: 'List Domains' operationId: getApiV1WebsitesByWebsiteDomains description: 'List the domains of a website (paginated).' parameters: - in: query name: search description: 'Search term (matches the domain).' required: false schema: type: string description: 'Search term (matches the domain).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteDomainPaginatedResponse' example: success: true data: - id: wd_cb21a922bbf5a66c71a8cff2f98df9c0 domain: abshire.com kind: custom role: alias is_apex: false cname_target: null dcv: null cf_status: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: wd_cb21a922bbf5a66c71a8cff2f98df9c0 domain: abshire.com kind: custom role: alias is_apex: false cname_target: null dcv: null cf_status: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Domains' post: summary: 'Add Domain' operationId: postApiV1WebsitesByWebsiteDomains description: 'Add a domain; custom domains are registered with Cloudflare and start pending.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteDomainResponse' example: success: true data: id: wd_cb21a922bbf5a66c71a8cff2f98df9c0 domain: abshire.com kind: custom role: alias is_apex: false cname_target: null dcv: null cf_status: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Domain added' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Domains' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateWebsiteDomainRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/domains/{domain}': get: summary: 'Check Domain' operationId: getApiV1WebsitesByWebsiteDomainsByDomain description: 'Live Cloudflare status refresh with DNS diagnostics; resets the polling window.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteDomainResponse' example: success: true data: id: wd_cb21a922bbf5a66c71a8cff2f98df9c0 domain: abshire.com kind: custom role: alias is_apex: false cname_target: null dcv: null cf_status: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Domains' patch: summary: 'Update Domain Role' operationId: patchApiV1WebsitesByWebsiteDomainsByDomain description: 'Change a domain role; promoting to default requires an active domain.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteDomainResponse' example: success: true data: id: wd_cb21a922bbf5a66c71a8cff2f98df9c0 domain: abshire.com kind: custom role: alias is_apex: false cname_target: null dcv: null cf_status: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Domain updated' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Domains' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateWebsiteDomainRequest' delete: summary: 'Remove Domain' operationId: deleteApiV1WebsitesByWebsiteDomainsByDomain description: 'Remove a non-primary domain and its Cloudflare hostname.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Domains' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 - in: path name: domain description: 'Prefixed domain ID.' required: true schema: type: string examples: - wd_abc123 '/api/v1/websites/{website}/domains/{domain}/pair': post: summary: 'Pair Domain' operationId: postApiV1WebsitesByWebsiteDomainsByDomainPair description: 'Register an unpaired legacy custom domain with Cloudflare.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteDomainResponse' example: success: true data: id: wd_cb21a922bbf5a66c71a8cff2f98df9c0 domain: abshire.com kind: custom role: alias is_apex: false cname_target: null dcv: null cf_status: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Domain pairing started' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Domains' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 - in: path name: domain description: 'Prefixed domain ID.' required: true schema: type: string examples: - wd_abc123 '/api/v1/websites/{website}/assign-account': post: summary: 'Assign Account' operationId: postApiV1WebsitesByWebsiteAssignAccount description: 'Assign an account to the website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteResponse' example: success: true data: id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Account assigned to website successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Accounts' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AssignWebsiteAccountRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/remove-account': post: summary: 'Remove Account' operationId: postApiV1WebsitesByWebsiteRemoveAccount description: 'Remove an account from the website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteResponse' example: success: true data: id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Account removed from website successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Accounts' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RemoveWebsiteAccountRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/accounts': get: summary: 'List Accounts' operationId: getApiV1WebsitesByWebsiteAccounts description: 'List all accounts with access to the website and their roles.' parameters: - in: query name: search description: 'Search term (searches name, surname, email).' required: false schema: type: string description: 'Search term (searches name, surname, email).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteAccountPaginatedResponse' example: success: true data: - account: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled actions: [] roles: - id: 1 name: 'website:owner' is_owner: true joined_at: '2026-01-01T00:00:00+00:00' relationship_actions: [] - account: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled actions: [] roles: - id: 1 name: 'website:owner' is_owner: true joined_at: '2026-01-01T00:00:00+00:00' relationship_actions: [] meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Accounts retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Accounts' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/accounts/{account}/roles': put: summary: 'Replace Account Roles' operationId: putApiV1WebsitesByWebsiteAccountsByAccountRoles description: 'Replace supplied Console and website role sections for a member.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteAccountRolesResponse' example: success: true data: console_roles: - 'console:account' website_roles: - id: 471 name: 'website:publisher' type: custom permissions: - 'website:page:list' assignable: true actions: - update - delete message: 'Account roles updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' description: 'When the actor cannot change a supplied role section.' 404: $ref: '#/components/responses/NotFound' description: 'When the website is inaccessible or the target membership does not exist.' 422: $ref: '#/components/responses/ValidationFailed' description: 'When the request body, target invariant, or section validation fails.' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Accounts' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ReplaceWebsiteAccountRolesRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 - in: path name: account description: 'Prefixed account ID.' required: true schema: type: string examples: - acc_abc123 '/api/v1/websites/{website}/accounts/{account_id}': delete: summary: 'Remove Account' operationId: deleteApiV1WebsitesByWebsiteAccountsByAccountId description: 'Remove an account from the website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteResponse' example: success: true data: id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Account removed from website successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Accounts' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 - in: path name: account_id description: 'Prefixed account ID to remove.' required: true schema: type: string examples: - acc_abc123 '/api/v1/websites/{website}/roles': get: summary: 'List Roles' operationId: getApiV1WebsitesByWebsiteRoles description: 'List built-in and custom roles available in the website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteRoleCollectionResponse' example: success: true data: - id: 471 name: 'website:publisher' type: custom permissions: - 'website:page:list' assignable: true actions: - update - delete - id: 471 name: 'website:publisher' type: custom permissions: - 'website:page:list' assignable: true actions: - update - delete message: 'Roles retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Roles' post: summary: 'Create Role' operationId: postApiV1WebsitesByWebsiteRoles description: 'Create a custom role in the website.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteRoleResponse' example: success: true data: id: 471 name: 'website:publisher' type: custom permissions: - 'website:page:list' assignable: true actions: - update - delete message: 'Role created successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Roles' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateWebsiteRoleRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/roles/permissions': get: summary: 'List Grantable Permissions' operationId: getApiV1WebsitesByWebsiteRolesPermissions description: 'List permission groups that the current account can grant to a custom role.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteRolePermissionGroupCollectionResponse' example: success: true data: - group: website.pages permissions: - 'website:page:create' - 'website:page:list' - group: website.pages permissions: - 'website:page:create' - 'website:page:list' message: 'Grantable permissions retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Roles' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/roles/{role}': put: summary: 'Update Role' operationId: putApiV1WebsitesByWebsiteRolesByRole description: 'Replace all permissions on a custom website role.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteRoleResponse' example: success: true data: id: 471 name: 'website:publisher' type: custom permissions: - 'website:page:list' assignable: true actions: - update - delete message: 'Role updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Roles' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateWebsiteRoleRequest' delete: summary: 'Delete Role' operationId: deleteApiV1WebsitesByWebsiteRolesByRole description: 'Delete an unused custom website role.' parameters: [] responses: 200: description: 'Role deleted successfully.' content: application/json: schema: type: object properties: success: type: boolean const: true data: type: 'null' message: type: string const: 'Role deleted successfully' required: - success - data - message 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 409: description: 'The role is still in use.' content: application/json: schema: type: object properties: success: type: boolean examples: - false message: type: string examples: - 'The role is assigned to a member or pending invitation and cannot be deleted.' examples: - success: false message: 'The role is assigned to a member or pending invitation and cannot be deleted.' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Roles' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 - in: path name: role description: 'Custom role ID.' required: true schema: type: integer examples: - 12 '/api/v1/websites/{website}/invitations/roles': get: summary: 'List Assignable Roles' operationId: getApiV1WebsitesByWebsiteInvitationsRoles description: 'List roles that can be assigned via invitation.' parameters: - in: query name: search description: 'Search term (searches name).' required: false schema: type: string description: 'Search term (searches name).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - name - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteRolePaginatedResponse' example: success: true data: - id: 471 name: 'website:publisher' type: custom permissions: - 'website:page:list' assignable: true actions: - update - delete - id: 471 name: 'website:publisher' type: custom permissions: - 'website:page:list' assignable: true actions: - update - delete meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Assignable roles retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Invitations' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_0123456789abcdef0123456789abcdef '/api/v1/websites/{website}/invitations': get: summary: 'List Invitations' operationId: getApiV1WebsitesByWebsiteInvitations description: 'List invitations for a website.' parameters: - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteInvitationPaginatedResponse' example: success: true data: - id: winv_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 email: runolfsdottir.jeffrey@gmail.com token: peu12xkf9k6n0wbsnzve1jb1b3retjvy35a2x0a9dpw6pgb8pnh17o5r1byozkr5 roles: - id: 360 name: 'website:publisher' type: custom permissions: - 'website:page:list' assignable: true actions: - update - delete status: pending invited_by: id: acc_1l740z603v5gzx7wlkojfwg3n3koga23 name: 'Watson Anderson' expires_at: '2026-01-08T00:00:00+00:00' accepted_at: null is_expired: false created_at: '2026-01-01T00:00:00+00:00' - id: winv_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 email: runolfsdottir.jeffrey@gmail.com token: peu12xkf9k6n0wbsnzve1jb1b3retjvy35a2x0a9dpw6pgb8pnh17o5r1byozkr5 roles: - id: 360 name: 'website:publisher' type: custom permissions: - 'website:page:list' assignable: true actions: - update - delete status: pending invited_by: id: acc_1l740z603v5gzx7wlkojfwg3n3koga23 name: 'Watson Anderson' expires_at: '2026-01-08T00:00:00+00:00' accepted_at: null is_expired: false created_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Invitations retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Invitations' post: summary: 'Create Invitation' operationId: postApiV1WebsitesByWebsiteInvitations description: 'Create a new invitation to grant website access with specified roles.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteInvitationResponse' example: success: true data: id: winv_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 email: runolfsdottir.jeffrey@gmail.com token: peu12xkf9k6n0wbsnzve1jb1b3retjvy35a2x0a9dpw6pgb8pnh17o5r1byozkr5 roles: - id: 360 name: 'website:publisher' type: custom permissions: - 'website:page:list' assignable: true actions: - update - delete status: pending invited_by: id: acc_1l740z603v5gzx7wlkojfwg3n3koga23 name: 'Watson Anderson' expires_at: '2026-01-08T00:00:00+00:00' accepted_at: null is_expired: false created_at: '2026-01-01T00:00:00+00:00' message: 'Invitation sent successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Invitations' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateWebsiteInvitationRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_0123456789abcdef0123456789abcdef '/api/v1/websites/{website}/invitations/{website_invitation}': delete: summary: 'Revoke Invitation' operationId: deleteApiV1WebsitesByWebsiteInvitationsByWebsiteInvitation description: 'Revoke a pending invitation.' parameters: [] responses: 200: description: 'Invitation revoked successfully.' content: application/json: schema: type: object properties: success: type: boolean examples: - true message: type: string examples: - 'Invitation revoked successfully' examples: - success: true message: 'Invitation revoked successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Invitations' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_0123456789abcdef0123456789abcdef - in: path name: website_invitation description: 'Prefixed invitation ID.' required: true schema: type: string examples: - winv_0123456789abcdef0123456789abcdef '/api/v1/invitations/{token}': get: summary: 'Get Invitation by Token' operationId: getApiV1InvitationsByToken description: 'Get invitation details by token. Public endpoint for displaying invitation info before accepting.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteInvitationDetailsResponse' example: success: true data: email: cortez69@hotmail.com roles: - name: 'website:admin' status: pending website_name: 'Wisozk Ltd' website_domain: fahey.com invited_by: 'Emmett Windler' expires_at: '2026-01-08T00:00:00+00:00' is_expired: false requires_registration: true message: 'Invitation details retrieved successfully' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Invitations' security: [] parameters: - in: path name: token description: 'Invitation token.' required: true schema: type: string examples: - abc123... '/api/v1/invitations/{token}/accept': post: summary: 'Accept Invitation' operationId: postApiV1InvitationsByTokenAccept description: 'Accept an invitation. Requires authenticated user with matching email.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteInvitationResponse' example: success: true data: id: winv_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 email: runolfsdottir.jeffrey@gmail.com token: peu12xkf9k6n0wbsnzve1jb1b3retjvy35a2x0a9dpw6pgb8pnh17o5r1byozkr5 roles: - id: 360 name: 'website:publisher' type: custom permissions: - 'website:page:list' assignable: true actions: - update - delete status: pending invited_by: id: acc_1l740z603v5gzx7wlkojfwg3n3koga23 name: 'Watson Anderson' expires_at: '2026-01-08T00:00:00+00:00' accepted_at: null is_expired: false created_at: '2026-01-01T00:00:00+00:00' message: 'Invitation accepted successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Invitations' parameters: - in: path name: token description: 'Invitation token.' required: true schema: type: string examples: - abc123... '/api/v1/websites/{website}/redirects': get: summary: 'List Redirects' operationId: getApiV1WebsitesByWebsiteRedirects description: 'Get all redirects for a website.' parameters: - in: query name: search description: 'Search term (searches source_path, destination_url).' required: false schema: type: string description: 'Search term (searches source_path, destination_url).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteRedirectPaginatedResponse' example: success: true data: - id: wred_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 source_path: /old-page destination_url: /new-page type: '301' is_active: true is_source_case_sensitive: false is_destination_case_sensitive: false created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: wred_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 source_path: /old-page destination_url: /new-page type: '301' is_active: true is_source_case_sensitive: false is_destination_case_sensitive: false created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Website redirects retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Redirects' post: summary: 'Create Redirect' operationId: postApiV1WebsitesByWebsiteRedirects description: 'Create a new redirect for a website.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteRedirectResponse' example: success: true data: id: wred_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 source_path: /old-page destination_url: /new-page type: '301' is_active: true is_source_case_sensitive: false is_destination_case_sensitive: false created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website redirect created successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Redirects' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateWebsiteRedirectRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/redirects/batch': post: summary: 'Batch Redirects' operationId: postApiV1WebsitesByWebsiteRedirectsBatch description: 'Create, update, and delete redirects in a single request.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Redirects' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/BatchWebsiteRedirectsRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/redirects/{website_redirect}': get: summary: 'Get Redirect' operationId: getApiV1WebsitesByWebsiteRedirectsByWebsiteRedirect description: 'Get a specific redirect for a website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteRedirectResponse' example: success: true data: id: wred_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 source_path: /old-page destination_url: /new-page type: '301' is_active: true is_source_case_sensitive: false is_destination_case_sensitive: false created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website redirect retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Redirects' put: summary: 'Update Redirect' operationId: putApiV1WebsitesByWebsiteRedirectsByWebsiteRedirect description: 'Update a specific redirect for a website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteRedirectResponse' example: success: true data: id: wred_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 source_path: /old-page destination_url: /new-page type: '301' is_active: true is_source_case_sensitive: false is_destination_case_sensitive: false created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website redirect updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Redirects' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateWebsiteRedirectRequest' delete: summary: 'Delete Redirect' operationId: deleteApiV1WebsitesByWebsiteRedirectsByWebsiteRedirect description: 'Delete a specific redirect for a website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteRedirectResponse' example: success: true data: id: wred_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 source_path: /old-page destination_url: /new-page type: '301' is_active: true is_source_case_sensitive: false is_destination_case_sensitive: false created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website redirect deleted successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Redirects' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 - in: path name: website_redirect description: 'Prefixed redirect ID.' required: true schema: type: string examples: - rdr_abc123 '/api/v1/websites/{website}/redirects/{website_redirect}/activate': post: summary: 'Activate Redirect' operationId: postApiV1WebsitesByWebsiteRedirectsByWebsiteRedirectActivate description: 'Activate a specific redirect.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteRedirectResponse' example: success: true data: id: wred_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 source_path: /old-page destination_url: /new-page type: '301' is_active: true is_source_case_sensitive: false is_destination_case_sensitive: false created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website redirect activated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Redirects' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 - in: path name: website_redirect description: 'Prefixed redirect ID.' required: true schema: type: string examples: - rdr_abc123 '/api/v1/websites/{website}/redirects/{website_redirect}/deactivate': post: summary: 'Deactivate Redirect' operationId: postApiV1WebsitesByWebsiteRedirectsByWebsiteRedirectDeactivate description: 'Deactivate a specific redirect.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteRedirectResponse' example: success: true data: id: wred_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 source_path: /old-page destination_url: /new-page type: '301' is_active: true is_source_case_sensitive: false is_destination_case_sensitive: false created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website redirect deactivated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Redirects' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 - in: path name: website_redirect description: 'Prefixed redirect ID.' required: true schema: type: string examples: - rdr_abc123 '/api/v1/websites/{website}/redirects/{website_redirect}/toggle': post: summary: 'Toggle Redirect' operationId: postApiV1WebsitesByWebsiteRedirectsByWebsiteRedirectToggle description: 'Toggle active state of a specific redirect.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteRedirectResponse' example: success: true data: id: wred_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 source_path: /old-page destination_url: /new-page type: '301' is_active: true is_source_case_sensitive: false is_destination_case_sensitive: false created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website redirect toggled successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Redirects' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 - in: path name: website_redirect description: 'Prefixed redirect ID.' required: true schema: type: string examples: - rdr_abc123 '/api/v1/websites/{website}/headers': get: summary: 'List Headers' operationId: getApiV1WebsitesByWebsiteHeaders description: 'Get all response headers for a website.' parameters: - in: query name: search description: 'Search term (searches name).' required: false schema: type: string description: 'Search term (searches name).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteHeaderPaginatedResponse' example: success: true data: - id: wh_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 name: X-Custom-Header value: custom-value created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: wh_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 name: X-Custom-Header value: custom-value created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Website headers retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Headers' post: summary: 'Create Header' operationId: postApiV1WebsitesByWebsiteHeaders description: 'Create a new response header for a website.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteHeaderResponse' example: success: true data: id: wh_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 name: X-Custom-Header value: custom-value created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website header created successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Headers' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateWebsiteHeaderRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/headers/batch': post: summary: 'Batch Headers' operationId: postApiV1WebsitesByWebsiteHeadersBatch description: 'Create, update, and delete headers in a single request.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Headers' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/BatchWebsiteHeadersRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/headers/{website_header}': get: summary: 'Get Header' operationId: getApiV1WebsitesByWebsiteHeadersByWebsiteHeader description: 'Get a specific response header for a website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteHeaderResponse' example: success: true data: id: wh_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 name: X-Custom-Header value: custom-value created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website header retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Headers' put: summary: 'Update Header' operationId: putApiV1WebsitesByWebsiteHeadersByWebsiteHeader description: 'Update a specific response header for a website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteHeaderResponse' example: success: true data: id: wh_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 name: X-Custom-Header value: custom-value created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website header updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Headers' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateWebsiteHeaderRequest' delete: summary: 'Delete Header' operationId: deleteApiV1WebsitesByWebsiteHeadersByWebsiteHeader description: 'Delete a specific response header for a website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteHeaderResponse' example: success: true data: id: wh_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 name: X-Custom-Header value: custom-value created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website header deleted successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Headers' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 - in: path name: website_header description: 'Prefixed header ID.' required: true schema: type: string examples: - wh_abc123 '/api/v1/websites/{website}/languages': get: summary: 'List Languages' operationId: getApiV1WebsitesByWebsiteLanguages description: 'Get all languages for a website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteLanguagePaginatedResponse' example: success: true data: - id: lng_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 code: en slug: en is_default: false provisioning: id: ecf_3fa3da614e951c258b49b953c5353e8f status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: lng_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 code: en slug: en is_default: false provisioning: id: ecf_3fa3da614e951c258b49b953c5353e8f status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Languages retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Languages' post: summary: 'Create Language' operationId: postApiV1WebsitesByWebsiteLanguages description: 'Add a language to a website.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteLanguageResponse' example: success: true data: id: lng_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 code: en slug: en is_default: false provisioning: id: ecf_3fa3da614e951c258b49b953c5353e8f status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Language created successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Languages' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateWebsiteLanguageRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/languages/{website_language}': get: summary: 'Get Language' operationId: getApiV1WebsitesByWebsiteLanguagesByWebsiteLanguage description: 'Get a specific language for a website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteLanguageResponse' example: success: true data: id: lng_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 code: en slug: en is_default: false provisioning: id: ecf_3fa3da614e951c258b49b953c5353e8f status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Language retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Languages' put: summary: 'Update Language' operationId: putApiV1WebsitesByWebsiteLanguagesByWebsiteLanguage description: 'Update a language slug or default flag. Code is immutable.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteLanguageResponse' example: success: true data: id: lng_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 code: en slug: en is_default: false provisioning: id: ecf_3fa3da614e951c258b49b953c5353e8f status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Language updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 409: description: 'A provisioning operation conflicts with this request.' content: application/json: schema: type: object properties: message: type: string examples: - 'A conflicting operation is in progress.' meta: type: object properties: confirmation_id: type: string examples: - ecf_0123456789abcdef0123456789abcdef entity_type: type: string examples: - backup entity_id: type: string examples: - bak_0123456789abcdef0123456789abcdef operation_key: type: string examples: - restoration status: type: string examples: - pending examples: - message: 'A conflicting operation is in progress.' meta: confirmation_id: ecf_0123456789abcdef0123456789abcdef entity_type: backup entity_id: bak_0123456789abcdef0123456789abcdef operation_key: restoration status: pending 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Languages' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateWebsiteLanguageRequest' delete: summary: 'Delete Language' operationId: deleteApiV1WebsitesByWebsiteLanguagesByWebsiteLanguage description: 'Remove a language from a website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteLanguageResponse' example: success: true data: id: lng_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 code: en slug: en is_default: false provisioning: id: ecf_3fa3da614e951c258b49b953c5353e8f status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Language deleted successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 409: description: 'A provisioning operation conflicts with this request.' content: application/json: schema: type: object properties: message: type: string examples: - 'A conflicting operation is in progress.' meta: type: object properties: confirmation_id: type: string examples: - ecf_0123456789abcdef0123456789abcdef entity_type: type: string examples: - backup entity_id: type: string examples: - bak_0123456789abcdef0123456789abcdef operation_key: type: string examples: - restoration status: type: string examples: - pending examples: - message: 'A conflicting operation is in progress.' meta: confirmation_id: ecf_0123456789abcdef0123456789abcdef entity_type: backup entity_id: bak_0123456789abcdef0123456789abcdef operation_key: restoration status: pending 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Languages' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 - in: path name: website_language description: 'Prefixed language ID.' required: true schema: type: string examples: - lng_abc123 '/api/v1/websites/{website}/languages/batch': post: summary: 'Batch Languages' operationId: postApiV1WebsitesByWebsiteLanguagesBatch description: 'Create, update, and delete languages in a single request.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 409: description: 'A provisioning operation conflicts with this request.' content: application/json: schema: type: object properties: message: type: string examples: - 'A conflicting operation is in progress.' meta: type: object properties: confirmation_id: type: string examples: - ecf_0123456789abcdef0123456789abcdef entity_type: type: string examples: - backup entity_id: type: string examples: - bak_0123456789abcdef0123456789abcdef operation_key: type: string examples: - restoration status: type: string examples: - pending examples: - message: 'A conflicting operation is in progress.' meta: confirmation_id: ecf_0123456789abcdef0123456789abcdef entity_type: backup entity_id: bak_0123456789abcdef0123456789abcdef operation_key: restoration status: pending 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Languages' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/BatchWebsiteLanguagesRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/backups': get: summary: 'List Backups' operationId: getApiV1WebsitesByWebsiteBackups description: 'Get all backups for a website.' parameters: - in: query name: search description: 'Search term (searches label, prefixed_id).' required: false schema: type: string description: 'Search term (searches label, prefixed_id).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteBackupPaginatedResponse' example: success: true data: - id: bak_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 label: beforelaunch provisioning: id: ecf_3fa3da614e951c258b49b953c5353e8f status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null restoration: id: ecf_a4d595b04fec3f54bd3458cfb4c37b8c status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: bak_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 label: beforelaunch provisioning: id: ecf_3fa3da614e951c258b49b953c5353e8f status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null restoration: id: ecf_a4d595b04fec3f54bd3458cfb4c37b8c status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Website backups retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Backups' post: summary: 'Create Backup' operationId: postApiV1WebsitesByWebsiteBackups description: 'Create a new backup for a website.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteBackupResponse' example: success: true data: id: bak_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 label: beforelaunch provisioning: id: ecf_3fa3da614e951c258b49b953c5353e8f status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null restoration: id: ecf_a4d595b04fec3f54bd3458cfb4c37b8c status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website backup created successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 409: description: 'A provisioning operation conflicts with this request.' content: application/json: schema: type: object properties: message: type: string examples: - 'A conflicting operation is in progress.' meta: type: object properties: confirmation_id: type: string examples: - ecf_0123456789abcdef0123456789abcdef entity_type: type: string examples: - backup entity_id: type: string examples: - bak_0123456789abcdef0123456789abcdef operation_key: type: string examples: - restoration status: type: string examples: - pending examples: - message: 'A conflicting operation is in progress.' meta: confirmation_id: ecf_0123456789abcdef0123456789abcdef entity_type: backup entity_id: bak_0123456789abcdef0123456789abcdef operation_key: restoration status: pending 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Backups' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateWebsiteBackupRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/backups/{website_backup}/restore': post: summary: 'Restore Backup' operationId: postApiV1WebsitesByWebsiteBackupsByWebsiteBackupRestore description: 'Restore a website from a ready backup.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteBackupResponse' example: success: true data: id: bak_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 label: beforelaunch provisioning: id: ecf_3fa3da614e951c258b49b953c5353e8f status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null restoration: id: ecf_a4d595b04fec3f54bd3458cfb4c37b8c status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website backup restored successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 409: description: 'A provisioning operation conflicts with this request.' content: application/json: schema: type: object properties: message: type: string examples: - 'A conflicting operation is in progress.' meta: type: object properties: confirmation_id: type: string examples: - ecf_0123456789abcdef0123456789abcdef entity_type: type: string examples: - backup entity_id: type: string examples: - bak_0123456789abcdef0123456789abcdef operation_key: type: string examples: - restoration status: type: string examples: - pending examples: - message: 'A conflicting operation is in progress.' meta: confirmation_id: ecf_0123456789abcdef0123456789abcdef entity_type: backup entity_id: bak_0123456789abcdef0123456789abcdef operation_key: restoration status: pending 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Backups' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 - in: path name: website_backup description: 'Prefixed backup ID.' required: true schema: type: string examples: - bak_abc123 '/api/v1/websites/{website}/languages/{website_language}/settings': get: summary: 'List Language Settings' operationId: getApiV1WebsitesByWebsiteLanguagesByWebsiteLanguageSettings description: 'Get all settings for a website language.' parameters: - in: query name: 'filter[group]' description: 'Filter by setting group.' required: false schema: type: string description: 'Filter by setting group.' examples: - default - in: query name: 'filter[key]' description: 'Filter by setting key.' required: false schema: type: string description: 'Filter by setting key.' examples: - headline - in: query name: search description: 'Search term for group or key.' required: false schema: type: string description: 'Search term for group or key.' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - key - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page.' required: false schema: type: integer description: 'Items per page.' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteLanguageSettingPaginatedResponse' example: success: true data: - id: wlset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 website_language_id: lng_jvy35a2x0a9dpw6pgb8pnh17o5r1byoz group: default key: headline value: text: Hello created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: wlset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 website_language_id: lng_jvy35a2x0a9dpw6pgb8pnh17o5r1byoz group: default key: headline value: text: Hello created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Language settings retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Language Settings' post: summary: 'Create Language Setting' operationId: postApiV1WebsitesByWebsiteLanguagesByWebsiteLanguageSettings description: 'Create a setting for a website language.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteLanguageSettingResponse' example: success: true data: id: wlset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 website_language_id: lng_jvy35a2x0a9dpw6pgb8pnh17o5r1byoz group: default key: headline value: text: Hello created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Language setting created successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Language Settings' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateWebsiteLanguageSettingRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 - in: path name: website_language description: 'Prefixed language ID.' required: true schema: type: string examples: - lng_abc123 '/api/v1/websites/{website}/languages/{website_language}/settings/{website_language_setting}': get: summary: 'Get Language Setting' operationId: getApiV1WebsitesByWebsiteLanguagesByWebsiteLanguageSettingsByWebsiteLanguageSetting description: 'Get a specific setting for a website language.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteLanguageSettingResponse' example: success: true data: id: wlset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 website_language_id: lng_jvy35a2x0a9dpw6pgb8pnh17o5r1byoz group: default key: headline value: text: Hello created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Language setting retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Language Settings' put: summary: 'Update Language Setting' operationId: putApiV1WebsitesByWebsiteLanguagesByWebsiteLanguageSettingsByWebsiteLanguageSetting description: 'Update a specific setting value for a website language.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteLanguageSettingResponse' example: success: true data: id: wlset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 website_language_id: lng_jvy35a2x0a9dpw6pgb8pnh17o5r1byoz group: default key: headline value: text: Hello created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Language setting updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Language Settings' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateWebsiteLanguageSettingRequest' delete: summary: 'Delete Language Setting' operationId: deleteApiV1WebsitesByWebsiteLanguagesByWebsiteLanguageSettingsByWebsiteLanguageSetting description: 'Delete a specific setting for a website language.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteLanguageSettingResponse' example: success: true data: id: wlset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 website_language_id: lng_jvy35a2x0a9dpw6pgb8pnh17o5r1byoz group: default key: headline value: text: Hello created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Language setting deleted successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Language Settings' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 - in: path name: website_language description: 'Prefixed language ID.' required: true schema: type: string examples: - lng_abc123 - in: path name: website_language_setting description: 'Prefixed language setting ID.' required: true schema: type: string examples: - wlset_abc123 '/api/v1/websites/{website}/languages/{website_language}/settings/batch': post: summary: 'Batch Language Settings' operationId: postApiV1WebsitesByWebsiteLanguagesByWebsiteLanguageSettingsBatch description: 'Create, update, and delete language settings in a single request.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Language Settings' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/BatchWebsiteLanguageSettingsRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 - in: path name: website_language description: 'Prefixed language ID.' required: true schema: type: string examples: - lng_abc123 '/api/v1/websites/{website}/settings': get: summary: 'List Website Settings' operationId: getApiV1WebsitesByWebsiteSettings description: 'List configuration settings for a website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteSettingPaginatedResponse' example: success: true data: - id: wset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 group: default type: text key: theme value: dark created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: wset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 group: default type: text key: theme value: dark created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Website settings retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Settings' post: summary: 'Create Website Setting' operationId: postApiV1WebsitesByWebsiteSettings description: 'Create a configuration setting for a website.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteSettingResponse' example: success: true data: id: wset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 group: default type: text key: theme value: dark created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website setting created successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Settings' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateWebsiteSettingRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/settings/{website_setting}': get: summary: 'Get Website Setting' operationId: getApiV1WebsitesByWebsiteSettingsByWebsiteSetting description: 'Get a specific website setting.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteSettingResponse' example: success: true data: id: wset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 group: default type: text key: theme value: dark created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website setting retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Settings' put: summary: 'Update Website Setting' operationId: putApiV1WebsitesByWebsiteSettingsByWebsiteSetting description: 'Update a website setting value.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteSettingResponse' example: success: true data: id: wset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 group: default type: text key: theme value: dark created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website setting updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Settings' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateWebsiteSettingRequest' delete: summary: 'Delete Website Setting' operationId: deleteApiV1WebsitesByWebsiteSettingsByWebsiteSetting description: 'Delete a website setting.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteSettingResponse' example: success: true data: id: wset_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 website_id: web_4oju80peu12xkf9k6n0wbsnzve1jb1b3 group: default type: text key: theme value: dark created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Website setting deleted successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Settings' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 - in: path name: website_setting description: 'Prefixed website setting ID.' required: true schema: type: string examples: - wset_abc123 '/api/v1/websites/{website}/settings/batch': post: summary: 'Batch Website Settings' operationId: postApiV1WebsitesByWebsiteSettingsBatch description: 'Create, update, and delete website settings in a single request.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Settings' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/BatchWebsiteSettingsRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 '/api/v1/websites/{website}/entitlements': get: summary: 'Website Entitlements' operationId: getApiV1WebsitesByWebsiteEntitlements description: 'Get the current resolved feature set for a website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteEntitlementsResponse' example: success: true data: website_id: web_00000000000000000000000000000001 features: - custom_domain resolved_at: '2026-07-03T12:00:00+00:00' message: 'Website entitlements retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[website] Entitlements' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_xyz789 /api/v1/me/billing/profiles: get: summary: 'List Billing Profiles' operationId: getApiV1MeBillingProfiles description: 'List the current account billing profiles.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/BillingProfilePaginatedResponse' example: success: true data: - id: bpro_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 label: 'Rowe-Runolfsdottir Billing' is_default: true billing_email: grady16@kuvalis.com phone: '+1 (216) 419-1378' name: 'Rebeca Roob IV' company: Dickinson-Rowe street: '10164 Wisozk Cliffs Suite 789' city: 'New Gerry' postal_code: 44790-4400 country: CZ currency: CZK company_identification_number: '12345678' company_vatin: CZ12345678 has_stripe_customer: true created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: bpro_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 label: 'Rowe-Runolfsdottir Billing' is_default: true billing_email: grady16@kuvalis.com phone: '+1 (216) 419-1378' name: 'Rebeca Roob IV' company: Dickinson-Rowe street: '10164 Wisozk Cliffs Suite 789' city: 'New Gerry' postal_code: 44790-4400 country: CZ currency: CZK company_identification_number: '12345678' company_vatin: CZ12345678 has_stripe_customer: true created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[billing] Profiles' post: summary: 'Create Billing Profile' operationId: postApiV1MeBillingProfiles description: 'Create a billing profile for the current account.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/BillingProfileResponse' example: success: true data: id: bpro_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 label: 'Rowe-Runolfsdottir Billing' is_default: true billing_email: grady16@kuvalis.com phone: '+1 (216) 419-1378' name: 'Rebeca Roob IV' company: Dickinson-Rowe street: '10164 Wisozk Cliffs Suite 789' city: 'New Gerry' postal_code: 44790-4400 country: CZ currency: CZK company_identification_number: '12345678' company_vatin: CZ12345678 has_stripe_customer: true created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Billing profile created successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[billing] Profiles' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateBillingProfileRequest' '/api/v1/me/billing/profiles/{billing_profile}': get: summary: 'Get Billing Profile' operationId: getApiV1MeBillingProfilesByBillingProfile description: 'Get one billing profile owned by the current account.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/BillingProfileResponse' example: success: true data: id: bpro_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 label: 'Rowe-Runolfsdottir Billing' is_default: true billing_email: grady16@kuvalis.com phone: '+1 (216) 419-1378' name: 'Rebeca Roob IV' company: Dickinson-Rowe street: '10164 Wisozk Cliffs Suite 789' city: 'New Gerry' postal_code: 44790-4400 country: CZ currency: CZK company_identification_number: '12345678' company_vatin: CZ12345678 has_stripe_customer: true created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[billing] Profiles' put: summary: 'Update Billing Profile' operationId: putApiV1MeBillingProfilesByBillingProfile description: 'Update one billing profile owned by the current account.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/BillingProfileResponse' example: success: true data: id: bpro_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 label: 'Rowe-Runolfsdottir Billing' is_default: true billing_email: grady16@kuvalis.com phone: '+1 (216) 419-1378' name: 'Rebeca Roob IV' company: Dickinson-Rowe street: '10164 Wisozk Cliffs Suite 789' city: 'New Gerry' postal_code: 44790-4400 country: CZ currency: CZK company_identification_number: '12345678' company_vatin: CZ12345678 has_stripe_customer: true created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Billing profile updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[billing] Profiles' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateBillingProfileRequest' delete: summary: 'Archive Billing Profile' operationId: deleteApiV1MeBillingProfilesByBillingProfile description: 'Archive one billing profile owned by the current account.' parameters: [] responses: 200: description: 'Billing profile archived.' content: application/json: schema: type: object properties: data: type: - string - 'null' examples: - null success: type: boolean examples: - true message: type: string examples: - 'Billing profile archived successfully' examples: - data: null success: true message: 'Billing profile archived successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[billing] Profiles' parameters: - in: path name: billing_profile description: 'Prefixed billing profile ID.' required: true schema: type: string examples: - bpro_abc123 '/api/v1/me/billing/profiles/{billing_profile}/portal': post: summary: 'Open Stripe Portal' operationId: postApiV1MeBillingProfilesByBillingProfilePortal description: 'Create a Stripe Billing Portal session for the profile.' parameters: [] responses: 200: description: 'Portal session created.' content: application/json: schema: $ref: '#/components/schemas/BillingPortalSessionResponse' example: success: true data: portal_url: 'https://billing.stripe.com/p/session/test_ybclU1Qw1xP1SUai9vCuadh4' message: 'Portal session created' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[billing] Profiles' parameters: - in: path name: billing_profile description: 'Prefixed billing profile ID.' required: true schema: type: string examples: - bpro_abc123 '/api/v1/websites/{website}/billing': get: summary: 'Website Billing' operationId: getApiV1WebsitesByWebsiteBilling description: 'Current subscription, available prices, selectable profiles, recent invoices.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteBillingResponse' example: success: true data: plan: basic paid_until: '2026-01-26T00:00:00+00:00' active_until: '2026-01-26T00:00:00+00:00' subscription: id: bsub_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 status: active status_label: Active is_live: true current_period_start: '2025-12-27T00:00:00+00:00' current_period_end: '2026-01-26T00:00:00+00:00' cancel_at_period_end: false payment_warning_at: null price: id: bpri_4oju80peu12xkf9k6n0wbsnzve1jb1b3 code: plans.basic kind: plan label: Basic currency: EUR interval: monthly amount_minor: 1000 is_custom: false billing_profile_id: bpro_jvy35a2x0a9dpw6pgb8pnh17o5r1byoz billing_profile_label: Default prices: - id: bpri_qglt1l740z603v5gzx7wlkojfwg3n3ko code: plans.basic kind: plan label: Basic currency: EUR interval: monthly amount_minor: 1000 is_custom: false feature_prices: - id: bpri_340faf03gb9a796thtl6untrsf4893vc code: plans.basic kind: plan label: Basic currency: EUR interval: monthly amount_minor: 1000 is_custom: false entitlements: - priority_support profiles: - id: bpro_53bz9bmqtusqb6d6izbkz5sii6x39o0k label: "Leffler, O'Conner and Cruickshank Billing" is_default: true billing_email: roselyn.schultz@harvey.com phone: '+19347321766' name: 'Nannie Ferry' company: Veum-Connelly street: '71924 Caleb Freeway' city: 'New Hendersonside' postal_code: 21644-5240 country: CZ currency: CZK company_identification_number: '12345678' company_vatin: CZ12345678 has_stripe_customer: true created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' invoices: - id: binv_eihw9zetunkqxde531dezi3rr18zdflq number: INV-0001 status: paid currency: EUR amount_due_minor: 1000 amount_paid_minor: 1000 period_start: '2025-12-27T00:00:00+00:00' period_end: '2026-01-26T00:00:00+00:00' invoice_number: FV-2026-0001 invoice_url: 'https://app.fakturoid.cz/solidpixels/invoices/1' created_at: '2026-01-01T00:00:00+00:00' message: 'Website billing retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[billing] Website Billing' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_abc123 '/api/v1/websites/{website}/billing/checkout': post: summary: 'Start Checkout' operationId: postApiV1WebsitesByWebsiteBillingCheckout description: 'Create a Stripe Checkout session for a price + profile.' parameters: [] responses: 200: description: 'Checkout session created.' content: application/json: schema: $ref: '#/components/schemas/CheckoutSessionResponse' example: success: true data: checkout_url: 'https://checkout.stripe.com/c/pay/cs_test_ybclU1Qw1xP1SUai9vCuadh4' message: 'Checkout session created' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[billing] Website Billing' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/StartWebsiteCheckoutRequest' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_abc123 '/api/v1/websites/{website}/billing/unsubscribe': post: summary: Unsubscribe operationId: postApiV1WebsitesByWebsiteBillingUnsubscribe description: 'Cancel the website subscription at the end of the paid period.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteSubscriptionResponse' example: success: true data: id: bsub_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 status: active status_label: Active is_live: true current_period_start: '2025-12-27T00:00:00+00:00' current_period_end: '2026-01-26T00:00:00+00:00' cancel_at_period_end: false payment_warning_at: null price: id: bpri_4oju80peu12xkf9k6n0wbsnzve1jb1b3 code: plans.basic kind: plan label: Basic currency: EUR interval: monthly amount_minor: 1000 is_custom: false billing_profile_id: bpro_jvy35a2x0a9dpw6pgb8pnh17o5r1byoz billing_profile_label: Default message: 'Subscription will cancel at the end of the paid period' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[billing] Website Billing' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_abc123 '/api/v1/websites/{website}/billing/resubscribe': post: summary: Resubscribe operationId: postApiV1WebsitesByWebsiteBillingResubscribe description: 'Clear a pending cancellation so the subscription renews again.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteSubscriptionResponse' example: success: true data: id: bsub_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 status: active status_label: Active is_live: true current_period_start: '2025-12-27T00:00:00+00:00' current_period_end: '2026-01-26T00:00:00+00:00' cancel_at_period_end: false payment_warning_at: null price: id: bpri_4oju80peu12xkf9k6n0wbsnzve1jb1b3 code: plans.basic kind: plan label: Basic currency: EUR interval: monthly amount_minor: 1000 is_custom: false billing_profile_id: bpro_jvy35a2x0a9dpw6pgb8pnh17o5r1byoz billing_profile_label: Default message: 'Subscription will renew again' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[billing] Website Billing' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_abc123 '/api/v1/websites/{website}/billing/invoices': get: summary: 'List Invoices' operationId: getApiV1WebsitesByWebsiteBillingInvoices description: 'List invoices for the website subscription.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/BillingInvoicePaginatedResponse' example: success: true data: - id: binv_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 number: INV-0001 status: paid currency: EUR amount_due_minor: 1000 amount_paid_minor: 1000 period_start: '2025-12-27T00:00:00+00:00' period_end: '2026-01-26T00:00:00+00:00' invoice_number: FV-2026-0001 invoice_url: 'https://app.fakturoid.cz/solidpixels/invoices/1' created_at: '2026-01-01T00:00:00+00:00' - id: binv_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 number: INV-0001 status: paid currency: EUR amount_due_minor: 1000 amount_paid_minor: 1000 period_start: '2025-12-27T00:00:00+00:00' period_end: '2026-01-26T00:00:00+00:00' invoice_number: FV-2026-0001 invoice_url: 'https://app.fakturoid.cz/solidpixels/invoices/1' created_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Invoices retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[billing] Website Billing' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_abc123 '/api/v1/websites/{website}/billing/custom-price': put: summary: 'Set Custom Price' operationId: putApiV1WebsitesByWebsiteBillingCustomPrice description: 'Set or replace the negotiated price for a website product.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/BillingPriceResponse' example: success: true data: id: bpri_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: plans.basic kind: plan label: Basic currency: EUR interval: monthly amount_minor: 1000 is_custom: false message: 'Custom price set' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[billing] Website Pricing' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SetWebsitePriceRequest' delete: summary: 'Clear Custom Price' operationId: deleteApiV1WebsitesByWebsiteBillingCustomPrice description: 'Remove the negotiated price for a product; the website reverts to the catalog.' parameters: - in: query name: code description: 'Product code to clear (e.g. plans.advanced).' required: true schema: type: string description: 'Product code to clear (e.g. plans.advanced).' examples: - plans.advanced responses: 200: description: 'Custom price cleared.' content: application/json: schema: type: object properties: data: type: - string - 'null' examples: - null success: type: boolean examples: - true message: type: string examples: - 'Custom price cleared' examples: - data: null success: true message: 'Custom price cleared' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[billing] Website Pricing' parameters: - in: path name: website description: 'Prefixed website ID.' required: true schema: type: string examples: - web_abc123 /api/v1/billing/stripe/webhook: post: summary: 'Process Stripe Webhook' operationId: postApiV1BillingStripeWebhook description: 'Verify and process a Stripe billing event.' parameters: - in: header name: Stripe-Signature description: '' schema: type: string examples: - 't=1710000000,v1=signature' responses: 400: description: '' content: application/json: schema: type: object properties: message: type: string examples: - 'Invalid signature' examples: - message: 'Invalid signature' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[billing] Stripe Webhooks' security: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/StripeWebhookEventRequest' /api/v1/feedback: post: summary: 'Submit Feedback' operationId: postApiV1Feedback description: 'Submit authenticated console feedback with optional context and images.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[feedback] Reports' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateFeedbackRequest' /api/v1/feedback/slack: post: summary: 'Submit Slack Feedback' operationId: postApiV1FeedbackSlack description: 'Submit feedback from a verified Slack slash command.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[feedback] Reports' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateSlackFeedbackRequest' security: [] /api/v1/libraries: get: summary: 'List Libraries' operationId: getApiV1Libraries description: 'List libraries for the authenticated account.' parameters: - in: query name: search description: 'Search term (searches name).' required: false schema: type: string description: 'Search term (searches name).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - '-created_at' - in: query name: exclude_website_libraries description: 'Exclude website own libraries from the result.' required: false schema: type: boolean description: 'Exclude website own libraries from the result.' examples: - true - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryPaginatedResponse' example: success: true data: - id: lib_cb21a922bbf5a66c71a8cff2f98df9c0 name: 'reprehenderit qui' is_system: false is_website_library: false items_count: 25 websites_count: 7 owner_account_id: acc_cc1ae9ad4b9ceb043cb73e5ffd373ad3 owner: firstname: Susana lastname: Grimes email: upton.marcelina@gmail.com roles: - 'library:owner' tags: - id: tag_w6pgb8pnh17o5r1byozkr5qglt1l740z name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: lib_cb21a922bbf5a66c71a8cff2f98df9c0 name: 'reprehenderit qui' is_system: false is_website_library: false items_count: 25 websites_count: 7 owner_account_id: acc_cc1ae9ad4b9ceb043cb73e5ffd373ad3 owner: firstname: Susana lastname: Grimes email: upton.marcelina@gmail.com roles: - 'library:owner' tags: - id: tag_w6pgb8pnh17o5r1byozkr5qglt1l740z name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Libraries retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Libraries' post: summary: 'Create Library' operationId: postApiV1Libraries description: 'Create a new library and assign to authenticated account.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryResponse' example: success: true data: id: lib_cb21a922bbf5a66c71a8cff2f98df9c0 name: 'reprehenderit qui' is_system: false is_website_library: false items_count: 25 websites_count: 7 owner_account_id: acc_cc1ae9ad4b9ceb043cb73e5ffd373ad3 owner: firstname: Susana lastname: Grimes email: upton.marcelina@gmail.com roles: - 'library:owner' tags: - id: tag_w6pgb8pnh17o5r1byozkr5qglt1l740z name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Library created successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Libraries' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateLibraryRequest' /api/v1/libraries/batch: post: summary: 'Batch Libraries' operationId: postApiV1LibrariesBatch description: 'Create, update, and delete libraries in a single request.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Libraries' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/BatchLibrariesRequest' /api/v1/libraries/export: post: summary: 'Export Library' operationId: postApiV1LibrariesExport description: 'Export libraries and their contents as a portable payload.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Libraries' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ExportLibraryRequest' /api/v1/libraries/import: post: summary: 'Import Library' operationId: postApiV1LibrariesImport description: 'Import libraries from a previously exported payload.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Libraries' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ImportLibraryRequest' '/api/v1/libraries/{library}': get: summary: 'Get Library' operationId: getApiV1LibrariesByLibrary description: 'Get a specific library.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryResponse' example: success: true data: id: lib_cb21a922bbf5a66c71a8cff2f98df9c0 name: 'reprehenderit qui' is_system: false is_website_library: false items_count: 25 websites_count: 7 owner_account_id: acc_cc1ae9ad4b9ceb043cb73e5ffd373ad3 owner: firstname: Susana lastname: Grimes email: upton.marcelina@gmail.com roles: - 'library:owner' tags: - id: tag_w6pgb8pnh17o5r1byozkr5qglt1l740z name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Library retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Libraries' put: summary: 'Update Library' operationId: putApiV1LibrariesByLibrary description: 'Update library details.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryResponse' example: success: true data: id: lib_cb21a922bbf5a66c71a8cff2f98df9c0 name: 'reprehenderit qui' is_system: false is_website_library: false items_count: 25 websites_count: 7 owner_account_id: acc_cc1ae9ad4b9ceb043cb73e5ffd373ad3 owner: firstname: Susana lastname: Grimes email: upton.marcelina@gmail.com roles: - 'library:owner' tags: - id: tag_w6pgb8pnh17o5r1byozkr5qglt1l740z name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Library updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Libraries' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateLibraryRequest' delete: summary: 'Delete Library' operationId: deleteApiV1LibrariesByLibrary description: 'Delete a library.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryResponse' example: success: true data: id: lib_cb21a922bbf5a66c71a8cff2f98df9c0 name: 'reprehenderit qui' is_system: false is_website_library: false items_count: 25 websites_count: 7 owner_account_id: acc_cc1ae9ad4b9ceb043cb73e5ffd373ad3 owner: firstname: Susana lastname: Grimes email: upton.marcelina@gmail.com roles: - 'library:owner' tags: - id: tag_w6pgb8pnh17o5r1byozkr5qglt1l740z name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Library deleted successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Libraries' parameters: - in: path name: library description: 'Library prefixed ID.' required: true schema: type: string examples: - lib_abc123 '/api/v1/libraries/{library}/thumbnails': post: summary: 'Regenerate Library Thumbnails' operationId: postApiV1LibrariesByLibraryThumbnails description: 'Dispatch thumbnail regeneration for every item in a library.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Libraries' parameters: - in: path name: library description: 'Library prefixed ID.' required: true schema: type: string examples: - lib_abc123 '/api/v1/libraries/{library}/transfer': post: summary: 'Transfer Ownership' operationId: postApiV1LibrariesByLibraryTransfer description: 'Transfer library ownership to another account.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryResponse' example: success: true data: id: lib_cb21a922bbf5a66c71a8cff2f98df9c0 name: 'reprehenderit qui' is_system: false is_website_library: false items_count: 25 websites_count: 7 owner_account_id: acc_cc1ae9ad4b9ceb043cb73e5ffd373ad3 owner: firstname: Susana lastname: Grimes email: upton.marcelina@gmail.com roles: - 'library:owner' tags: - id: tag_w6pgb8pnh17o5r1byozkr5qglt1l740z name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Library ownership transferred successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Ownership' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TransferLibraryOwnershipRequest' parameters: - in: path name: library description: 'Prefixed library ID.' required: true schema: type: string examples: - lib_xyz789 '/api/v1/libraries/{library_id}/accounts': get: summary: 'List Accounts' operationId: getApiV1LibrariesByLibraryIdAccounts description: 'List all accounts with access to the library and their roles.' parameters: - in: query name: search description: 'Search term (searches name, surname, email).' required: false schema: type: string description: 'Search term (searches name, surname, email).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryAccountPaginatedResponse' example: success: true data: - account: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - name: 'library:editor' is_owner: false is_default: false joined_at: '2026-01-01T00:00:00+00:00' - account: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - name: 'library:editor' is_owner: false is_default: false joined_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Accounts retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Accounts' parameters: - in: path name: library_id description: 'Prefixed library ID.' required: true schema: type: string examples: - lib_xyz789 '/api/v1/libraries/{library}/accounts/{account}': patch: summary: 'Update Account Membership' operationId: patchApiV1LibrariesByLibraryAccountsByAccount description: "Update a member's default-library preference. Updates only the existing membership; it never creates a membership or changes roles." parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryAccountResponse' example: success: true data: account: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - name: 'library:editor' is_owner: false is_default: false joined_at: '2026-01-01T00:00:00+00:00' message: 'Library account updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Accounts' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateLibraryAccountRequest' parameters: - in: path name: library description: 'Prefixed library ID.' required: true schema: type: string examples: - lib_xyz789 - in: path name: account description: 'Prefixed account ID.' required: true schema: type: string examples: - acc_abc123 '/api/v1/libraries/{library_id}/remove-account': post: summary: 'Remove Account' operationId: postApiV1LibrariesByLibraryIdRemoveAccount description: 'Remove an account from the library.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryAccountResponse' example: success: true data: account: id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - name: 'library:editor' is_owner: false is_default: false joined_at: '2026-01-01T00:00:00+00:00' message: 'Account removed from library successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Accounts' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RemoveLibraryAccountRequest' parameters: - in: path name: library_id description: 'Prefixed library ID.' required: true schema: type: string examples: - lib_xyz789 '/api/v1/libraries/{library}/invitations/roles': get: summary: 'List Assignable Roles' operationId: getApiV1LibrariesByLibraryInvitationsRoles description: 'List library roles that can be assigned via invitation.' parameters: - in: query name: search description: 'Search term (searches name).' required: false schema: type: string description: 'Search term (searches name).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - name - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryRolePaginatedResponse' example: success: true data: - id: 471 name: 'library:admin' - id: 471 name: 'library:admin' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Assignable roles retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Invitations' parameters: - in: path name: library description: 'Prefixed library ID.' required: true schema: type: string examples: - lib_0123456789abcdef0123456789abcdef '/api/v1/libraries/{library_id}/invitations': get: summary: 'List Invitations' operationId: getApiV1LibrariesByLibraryIdInvitations description: 'List invitations for a library.' parameters: - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryInvitationPaginatedResponse' example: success: true data: - id: linv_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 email: runolfsdottir.jeffrey@gmail.com token: peu12xkf9k6n0wbsnzve1jb1b3retjvy35a2x0a9dpw6pgb8pnh17o5r1byozkr5 roles: - id: 360 name: 'library:admin' status: pending invited_by: id: acc_1l740z603v5gzx7wlkojfwg3n3koga23 name: 'Watson Anderson' expires_at: '2026-01-08T00:00:00+00:00' accepted_at: null is_expired: false created_at: '2026-01-01T00:00:00+00:00' - id: linv_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 email: runolfsdottir.jeffrey@gmail.com token: peu12xkf9k6n0wbsnzve1jb1b3retjvy35a2x0a9dpw6pgb8pnh17o5r1byozkr5 roles: - id: 360 name: 'library:admin' status: pending invited_by: id: acc_1l740z603v5gzx7wlkojfwg3n3koga23 name: 'Watson Anderson' expires_at: '2026-01-08T00:00:00+00:00' accepted_at: null is_expired: false created_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Invitations retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Invitations' post: summary: 'Create Invitation' operationId: postApiV1LibrariesByLibraryIdInvitations description: 'Create a new invitation to grant library access with specified roles.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryInvitationResponse' example: success: true data: id: linv_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 email: runolfsdottir.jeffrey@gmail.com token: peu12xkf9k6n0wbsnzve1jb1b3retjvy35a2x0a9dpw6pgb8pnh17o5r1byozkr5 roles: - id: 360 name: 'library:admin' status: pending invited_by: id: acc_1l740z603v5gzx7wlkojfwg3n3koga23 name: 'Watson Anderson' expires_at: '2026-01-08T00:00:00+00:00' accepted_at: null is_expired: false created_at: '2026-01-01T00:00:00+00:00' message: 'Invitation sent successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Invitations' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateLibraryInvitationRequest' parameters: - in: path name: library_id description: 'Prefixed library ID.' required: true schema: type: string examples: - lib_0123456789abcdef0123456789abcdef '/api/v1/libraries/{library_id}/invitations/{library_invitation}': delete: summary: 'Revoke Invitation' operationId: deleteApiV1LibrariesByLibraryIdInvitationsByLibraryInvitation description: 'Revoke a pending invitation.' parameters: [] responses: 200: description: 'Invitation revoked successfully.' content: application/json: schema: type: object properties: success: type: boolean examples: - true message: type: string examples: - 'Invitation revoked successfully' examples: - success: true message: 'Invitation revoked successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Invitations' parameters: - in: path name: library_id description: 'Prefixed library ID.' required: true schema: type: string examples: - lib_0123456789abcdef0123456789abcdef - in: path name: library_invitation description: 'Prefixed invitation ID.' required: true schema: type: string examples: - linv_0123456789abcdef0123456789abcdef '/api/v1/invitations/library/{token}': get: summary: 'Get Invitation by Token' operationId: getApiV1InvitationsLibraryByToken description: 'Get invitation details by token before accepting.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryInvitationDetailsResponse' example: success: true data: email: cortez69@hotmail.com roles: - name: 'library:admin' status: pending library_name: 'iure quos' invited_by: 'Mrs. Leslie Rempel' expires_at: '2026-01-08T00:00:00+00:00' is_expired: false requires_registration: true message: 'Invitation details retrieved successfully' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Invitations' security: [] parameters: - in: path name: token description: 'Invitation token.' required: true schema: type: string examples: - abc123... '/api/v1/invitations/library/{token}/accept': post: summary: 'Accept Invitation' operationId: postApiV1InvitationsLibraryByTokenAccept description: 'Accept an invitation with the authenticated matching account.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryInvitationResponse' example: success: true data: id: linv_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 email: runolfsdottir.jeffrey@gmail.com token: peu12xkf9k6n0wbsnzve1jb1b3retjvy35a2x0a9dpw6pgb8pnh17o5r1byozkr5 roles: - id: 360 name: 'library:admin' status: pending invited_by: id: acc_1l740z603v5gzx7wlkojfwg3n3koga23 name: 'Watson Anderson' expires_at: '2026-01-08T00:00:00+00:00' accepted_at: null is_expired: false created_at: '2026-01-01T00:00:00+00:00' message: 'Invitation accepted successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Invitations' parameters: - in: path name: token description: 'Invitation token.' required: true schema: type: string examples: - abc123... '/api/v1/libraries/{library}/folders': get: summary: 'List Folders' operationId: getApiV1LibrariesByLibraryFolders description: 'List folders in a library.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryFolderPaginatedResponse' example: success: true data: - id: lf_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 parent_id: null name: labore position: 0 created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: lf_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 parent_id: null name: labore position: 0 created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Folders retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Folders' post: summary: 'Create Folder' operationId: postApiV1LibrariesByLibraryFolders description: 'Create a new folder in a library.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryFolderResponse' example: success: true data: id: lf_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 parent_id: null name: labore position: 0 created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Folder created successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Folders' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateLibraryFolderRequest' parameters: - in: path name: library description: 'Library prefixed ID.' required: true schema: type: string examples: - lib_abc123 '/api/v1/libraries/{library}/folders/batch': post: summary: 'Batch Folders' operationId: postApiV1LibrariesByLibraryFoldersBatch description: 'Create, update, and delete library folders in a single request.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Folders' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/BatchLibraryFoldersRequest' parameters: - in: path name: library description: 'Prefixed library ID.' required: true schema: type: string examples: - lib_abc123 '/api/v1/libraries/{library}/folders/{library_folder}': put: summary: 'Update Folder' operationId: putApiV1LibrariesByLibraryFoldersByLibraryFolder description: 'Update a library folder.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryFolderResponse' example: success: true data: id: lf_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 parent_id: null name: labore position: 0 created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Folder updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Folders' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateLibraryFolderRequest' delete: summary: 'Delete Folder' operationId: deleteApiV1LibrariesByLibraryFoldersByLibraryFolder description: 'Delete a library folder.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryFolderResponse' example: success: true data: id: lf_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 parent_id: null name: labore position: 0 created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Folder deleted successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Folders' parameters: - in: path name: library description: 'Library prefixed ID.' required: true schema: type: string examples: - lib_abc123 - in: path name: library_folder description: 'Folder prefixed ID.' required: true schema: type: string examples: - lf_abc123 '/api/v1/libraries/{library}/items': get: summary: 'List Items' operationId: getApiV1LibrariesByLibraryItems description: 'List items in a library.' parameters: - in: query name: 'filter[folder_id]' description: 'Filter by folder prefixed ID.' required: false schema: type: string description: 'Filter by folder prefixed ID.' examples: - lf_abc123 - in: query name: search description: 'Search term (searches name).' required: false schema: type: string description: 'Search term (searches name).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 400).' required: false schema: type: integer description: 'Items per page (max 400).' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryItemPaginatedResponse' example: success: true data: - id: li_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 name: 'labore fugit' folder_id: null content: blocks: [] thumbnail_url: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: li_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 name: 'labore fugit' folder_id: null content: blocks: [] thumbnail_url: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Items retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Items' post: summary: 'Create Item' operationId: postApiV1LibrariesByLibraryItems description: 'Create a new item in a library.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryItemResponse' example: success: true data: id: li_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 name: 'labore fugit' folder_id: null content: blocks: [] thumbnail_url: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Item created successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Items' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateLibraryItemRequest' parameters: - in: path name: library description: 'Library prefixed ID.' required: true schema: type: string examples: - lib_abc123 '/api/v1/libraries/{library}/items/batch': post: summary: 'Batch Items' operationId: postApiV1LibrariesByLibraryItemsBatch description: 'Batch create, update, and delete library items.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Items' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/BatchLibraryItemsRequest' parameters: - in: path name: library description: 'Library prefixed ID.' required: true schema: type: string examples: - lib_abc123 '/api/v1/libraries/{library}/items/{library_item}': get: summary: 'Get Item' operationId: getApiV1LibrariesByLibraryItemsByLibraryItem description: 'Get a specific library item.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryItemResponse' example: success: true data: id: li_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 name: 'labore fugit' folder_id: null content: blocks: [] thumbnail_url: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Item retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Items' put: summary: 'Update Item' operationId: putApiV1LibrariesByLibraryItemsByLibraryItem description: 'Update a library item.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryItemResponse' example: success: true data: id: li_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 name: 'labore fugit' folder_id: null content: blocks: [] thumbnail_url: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Item updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Items' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateLibraryItemRequest' delete: summary: 'Delete Item' operationId: deleteApiV1LibrariesByLibraryItemsByLibraryItem description: 'Delete a library item.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryItemResponse' example: success: true data: id: li_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 name: 'labore fugit' folder_id: null content: blocks: [] thumbnail_url: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Item deleted successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Items' parameters: - in: path name: library description: 'Library prefixed ID.' required: true schema: type: string examples: - lib_abc123 - in: path name: library_item description: 'Item prefixed ID.' required: true schema: type: string examples: - li_abc123 '/api/v1/libraries/{library}/items/{library_item}/copy': post: summary: 'Copy Item' operationId: postApiV1LibrariesByLibraryItemsByLibraryItemCopy description: 'Copy a library item to another library.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryItemResponse' example: success: true data: id: li_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 name: 'labore fugit' folder_id: null content: blocks: [] thumbnail_url: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Item copied successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Items' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CopyLibraryItemRequest' parameters: - in: path name: library description: 'Source library prefixed ID.' required: true schema: type: string examples: - lib_abc123 - in: path name: library_item description: 'Item prefixed ID.' required: true schema: type: string examples: - li_abc123 '/api/v1/libraries/{library}/items/{library_item}/move': post: summary: 'Move Item' operationId: postApiV1LibrariesByLibraryItemsByLibraryItemMove description: 'Move a library item to another library.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryItemResponse' example: success: true data: id: li_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 name: 'labore fugit' folder_id: null content: blocks: [] thumbnail_url: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Item moved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Items' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MoveLibraryItemRequest' parameters: - in: path name: library description: 'Source library prefixed ID.' required: true schema: type: string examples: - lib_abc123 - in: path name: library_item description: 'Item prefixed ID.' required: true schema: type: string examples: - li_abc123 '/api/v1/libraries/{library}/items/{library_item}/thumbnail': post: summary: 'Regenerate Item Thumbnail' operationId: postApiV1LibrariesByLibraryItemsByLibraryItemThumbnail description: 'Dispatch thumbnail regeneration for a single library item.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Items' parameters: - in: path name: library description: 'Library prefixed ID.' required: true schema: type: string examples: - lib_abc123 - in: path name: library_item description: 'Item prefixed ID.' required: true schema: type: string examples: - li_abc123 '/api/v1/libraries/{library}/websites': get: summary: 'List Library Websites' operationId: getApiV1LibrariesByLibraryWebsites description: 'List websites attached to a library.' parameters: - in: query name: search description: 'Search term (searches name and domain).' required: false schema: type: string description: 'Search term (searches name and domain).' examples: - aspernatur - in: query name: sort description: 'Sort by name, domain, status, or created_at; prefix with - for descending.' required: false schema: type: string description: 'Sort by name, domain, status, or created_at; prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsitePaginatedResponse' example: success: true data: - id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Websites retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Website Libraries' parameters: - in: path name: library description: 'Library prefixed ID.' required: true schema: type: string examples: - lib_abc123 '/api/v1/websites/{website}/libraries': get: summary: 'List Website Libraries' operationId: getApiV1WebsitesByWebsiteLibraries description: 'Search and list libraries attached to a website, with optional pagination.' parameters: - in: query name: search description: 'Search term (searches name).' required: false schema: type: string description: 'Search term (searches name).' examples: - aspernatur - in: query name: sort description: 'Sort by name or created_at; prefix with - for descending.' required: false schema: type: string description: 'Sort by name or created_at; prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number. Supplying this enables pagination.' required: false schema: type: integer description: 'Page number. Supplying this enables pagination.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100). Supplying this enables pagination.' required: false schema: type: integer description: 'Items per page (max 100). Supplying this enables pagination.' examples: - 15 responses: 200: description: 'Library collection. Paginated requests also include pagination metadata.' content: application/json: schema: $ref: '#/components/schemas/LibraryCollectionResponse' example: success: true data: - id: lib_cb21a922bbf5a66c71a8cff2f98df9c0 name: 'reprehenderit qui' is_system: false is_website_library: false items_count: 25 websites_count: 7 owner_account_id: acc_cc1ae9ad4b9ceb043cb73e5ffd373ad3 owner: firstname: Susana lastname: Grimes email: upton.marcelina@gmail.com roles: - 'library:owner' tags: - id: tag_w6pgb8pnh17o5r1byozkr5qglt1l740z name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: lib_cb21a922bbf5a66c71a8cff2f98df9c0 name: 'reprehenderit qui' is_system: false is_website_library: false items_count: 25 websites_count: 7 owner_account_id: acc_cc1ae9ad4b9ceb043cb73e5ffd373ad3 owner: firstname: Susana lastname: Grimes email: upton.marcelina@gmail.com roles: - 'library:owner' tags: - id: tag_w6pgb8pnh17o5r1byozkr5qglt1l740z name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Libraries retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Website Libraries' post: summary: 'Attach Library' operationId: postApiV1WebsitesByWebsiteLibraries description: 'Attach a library to a website.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryResponse' example: success: true data: id: lib_cb21a922bbf5a66c71a8cff2f98df9c0 name: 'reprehenderit qui' is_system: false is_website_library: false items_count: 25 websites_count: 7 owner_account_id: acc_cc1ae9ad4b9ceb043cb73e5ffd373ad3 owner: firstname: Susana lastname: Grimes email: upton.marcelina@gmail.com roles: - 'library:owner' tags: - id: tag_w6pgb8pnh17o5r1byozkr5qglt1l740z name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Library attached successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Website Libraries' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AttachLibraryToWebsiteRequest' parameters: - in: path name: website description: 'Website prefixed ID.' required: true schema: type: string examples: - web_abc123 '/api/v1/websites/{website}/libraries/{library}': delete: summary: 'Detach Library' operationId: deleteApiV1WebsitesByWebsiteLibrariesByLibrary description: 'Detach a library from a website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryResponse' example: success: true data: id: lib_cb21a922bbf5a66c71a8cff2f98df9c0 name: 'reprehenderit qui' is_system: false is_website_library: false items_count: 25 websites_count: 7 owner_account_id: acc_cc1ae9ad4b9ceb043cb73e5ffd373ad3 owner: firstname: Susana lastname: Grimes email: upton.marcelina@gmail.com roles: - 'library:owner' tags: - id: tag_w6pgb8pnh17o5r1byozkr5qglt1l740z name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Library detached successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Website Libraries' parameters: - in: path name: website description: 'Website prefixed ID.' required: true schema: type: string examples: - web_abc123 - in: path name: library description: 'Library prefixed ID.' required: true schema: type: string examples: - lib_abc123 '/api/v1/websites/{website}/libraries/{library}/items': get: summary: 'List Items (Website Scope)' operationId: getApiV1WebsitesByWebsiteLibrariesByLibraryItems description: 'List items in a library attached to a website.' parameters: - in: query name: 'filter[folder_id]' description: 'Filter by folder prefixed ID.' required: false schema: type: string description: 'Filter by folder prefixed ID.' examples: - lf_abc123 - in: query name: search description: 'Search term (searches name).' required: false schema: type: string description: 'Search term (searches name).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 400).' required: false schema: type: integer description: 'Items per page (max 400).' examples: - 15 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryItemPaginatedResponse' example: success: true data: - id: li_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 name: 'labore fugit' folder_id: null content: blocks: [] thumbnail_url: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: li_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 name: 'labore fugit' folder_id: null content: blocks: [] thumbnail_url: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Items retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Website Content' parameters: - in: path name: website description: 'Website prefixed ID.' required: true schema: type: string examples: - web_abc123 - in: path name: library description: 'Library prefixed ID.' required: true schema: type: string examples: - lib_abc123 '/api/v1/websites/{website}/libraries/{library}/items/{item}': get: summary: 'Show Item (Website Scope)' operationId: getApiV1WebsitesByWebsiteLibrariesByLibraryItemsByItem description: 'Get a specific item from a library attached to a website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryItemResponse' example: success: true data: id: li_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 name: 'labore fugit' folder_id: null content: blocks: [] thumbnail_url: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Item retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Website Content' parameters: - in: path name: website description: 'Website prefixed ID.' required: true schema: type: string examples: - web_abc123 - in: path name: library description: 'Library prefixed ID.' required: true schema: type: string examples: - lib_abc123 - in: path name: item description: 'Item prefixed ID.' required: true schema: type: string examples: - li_abc123 '/api/v1/websites/{website}/libraries/{library}/folders': get: summary: 'List Folders (Website Scope)' operationId: getApiV1WebsitesByWebsiteLibrariesByLibraryFolders description: 'List folders in a library attached to a website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryFolderCollectionResponse' example: success: true data: - id: lf_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 parent_id: null name: labore position: 0 created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: lf_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 parent_id: null name: labore position: 0 created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Folders retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[library] Website Content' parameters: - in: path name: website description: 'Website prefixed ID.' required: true schema: type: string examples: - web_abc123 - in: path name: library description: 'Library prefixed ID.' required: true schema: type: string examples: - lib_abc123 /api/v1/admin/limits: get: summary: 'Get Component Limits' operationId: getApiV1AdminLimits description: 'Get the platform component-limit document with defaults and per-IP overrides. The response also lists the registered components and the allowed limit values.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/PlatformComponentLimitsResponse' example: success: true data: services: data: default: 100 overrides: [] components: - data - files values: - 20 - 50 - 100 - 200 - 500 - 1000 message: 'Component limits retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[platform] Administration' put: summary: 'Update Component Limits' operationId: putApiV1AdminLimits description: 'Replace the platform component-limit document.' parameters: [] responses: 200: description: 'Component limits document updated.' content: application/json: schema: type: object properties: data: type: object properties: services: type: object properties: data: type: object properties: default: type: integer examples: - 100 overrides: type: array examples: - [] examples: - data: services: data: default: 100 overrides: [] 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[platform] Administration' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateComponentLimitsRequest' /api/v1/platform/identifiers: get: summary: 'Get Platform Identifiers' operationId: getApiV1PlatformIdentifiers description: 'Returns platform account, system library, and website prefixed IDs.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/PlatformIdentifiersResponse' example: success: true data: library: library_id: lib_cb21a922bbf5a66c71a8cff2f98df9c0 account_id: acc_4c36cc1ae9ad4b9ceb043cb73e5ffd37 account_email: royal.haag@example.com website_id: web_a614e951c258b49b953c5353e8f035a4 message: 'Platform identifiers retrieved' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[platform] Administration' /api/v1/platform/maintenance: get: summary: 'Get Platform Maintenance' operationId: getApiV1PlatformMaintenance description: 'Returns whether platform-wide maintenance is active.' parameters: [] responses: 200: description: 'Platform maintenance status.' content: application/json: schema: $ref: '#/components/schemas/MaintenanceStateResponse' example: success: true data: enabled: false html: '

Maintenance

' message: 'Platform maintenance status retrieved' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[platform] Administration' put: summary: 'Toggle Platform Maintenance' operationId: putApiV1PlatformMaintenance description: 'Enable or disable maintenance mode for the entire platform.' parameters: [] responses: 200: description: 'Platform maintenance mode updated.' content: application/json: schema: $ref: '#/components/schemas/MaintenanceStateResponse' example: success: true data: enabled: false html: '

Maintenance

' message: 'Platform maintenance mode updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[platform] Administration' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MaintenanceStateRequest' /api/v1/admin/websites/expired: get: summary: 'List Expired Websites' operationId: getApiV1AdminWebsitesExpired description: 'Get all websites with expired payment (admin).' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteCollectionResponse' example: success: true data: - id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Expired websites retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[admin] Websites' /api/v1/admin/websites/expiring-soon: get: summary: 'List Expiring Soon Websites' operationId: getApiV1AdminWebsitesExpiringSoon description: 'Get websites expiring within 7 days (admin).' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteCollectionResponse' example: success: true data: - id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Expiring soon websites retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[admin] Websites' /api/v1/admin/websites/should-turn-off: get: summary: 'List Should Turn Off Websites' operationId: getApiV1AdminWebsitesShouldTurnOff description: 'Get websites past their active_until date (admin).' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsiteCollectionResponse' example: success: true data: - id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Websites to turn off retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[admin] Websites' /api/v1/admin/websites/process-turn-offs: post: summary: 'Process Turn Offs' operationId: postApiV1AdminWebsitesProcessTurnOffs description: 'Disable all websites past their active_until date (admin).' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[admin] Websites' '/api/v1/admin/websites/{website}/limits': get: summary: 'Get Website Serve Limit' operationId: getApiV1AdminWebsitesByWebsiteLimits description: 'Get the effective serve request limit for a website.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/ServeLimitResponse' example: success: true data: key: limits.serve value: 10 source: plan message: 'Serve limit retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[admin] Websites' put: summary: 'Update Website Serve Limit' operationId: putApiV1AdminWebsitesByWebsiteLimits description: 'Set an override for the website serve limit.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/ServeLimitResponse' example: success: true data: key: limits.serve value: 10 source: plan message: 'Serve limit updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[admin] Websites' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateWebsiteServeLimitRequest' delete: summary: 'Delete Website Serve Limit' operationId: deleteApiV1AdminWebsitesByWebsiteLimits description: 'Remove the website serve-limit override.' parameters: [] responses: 204: description: 'Override deleted.' content: application/json: schema: type: - object - 'null' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[admin] Websites' parameters: - in: path name: website description: 'Website prefixed ID.' required: true schema: type: string examples: - web_abc123 /api/v1/internal/caddy/validation: get: summary: 'Validate Host' operationId: getApiV1InternalCaddyValidation description: 'Check if a domain is allowed for hosting.' parameters: - in: query name: domain description: 'Domain to validate.' required: true schema: type: string description: 'Domain to validate.' examples: - example.com responses: 200: description: 'Domain is valid.' content: application/json: schema: type: object properties: valid: type: boolean examples: - true reason: type: string examples: - website_domain examples: - valid: true reason: website_domain 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[internal] Caddy' security: [] x-discoverable: false /api/v1/internal/caddy/domain: get: summary: 'Get Domain Meta' operationId: getApiV1InternalCaddyDomain description: 'Get website id, languages, headers, and limits to inject for a domain.' parameters: - in: query name: domain description: 'Domain to resolve.' required: true schema: type: string description: 'Domain to resolve.' examples: - example.com - in: query name: route_type description: 'Route type hint (serve, service, tool).' required: false schema: type: string description: 'Route type hint (serve, service, tool).' examples: - serve responses: 200: description: '' content: application/json: schema: oneOf: - description: 'Domain meta for website.' type: object properties: websiteId: type: string examples: - web_abc123 languages: type: array items: type: object properties: id: type: string examples: - lng_abc123 slug: type: string examples: - en isDefault: type: boolean examples: - true code: type: string examples: - en examples: - - id: lng_abc123 slug: en isDefault: true code: en headers: type: object properties: request: type: object properties: x-solidpixels-website: type: string examples: - web_abc123 response: type: object properties: {} limits: type: object properties: limits.serve: type: integer examples: - 10 examples: - websiteId: web_abc123 languages: - id: lng_abc123 slug: en isDefault: true code: en headers: request: x-solidpixels-website: web_abc123 response: {} limits: limits.serve: 10 - description: 'Empty domain meta for unknown domain.' type: object properties: languages: type: array examples: - [] headers: type: object properties: request: type: object properties: {} response: type: object properties: {} examples: - languages: [] headers: request: {} response: {} 500: $ref: '#/components/responses/InternalServerError' tags: - '[internal] Caddy' security: [] x-discoverable: false /api/v1/internal/caddy/resolve: get: summary: 'Resolve Website-Host' operationId: getApiV1InternalCaddyResolve description: 'Bidirectional lookup between website_id and hosts.' parameters: - in: query name: website_id description: 'Website prefixed id.' required: false schema: type: string description: 'Website prefixed id.' examples: - web_abc123 - in: query name: host description: 'Domain hostname.' required: false schema: type: string description: 'Domain hostname.' examples: - example.com responses: 200: description: Resolved. content: application/json: schema: type: object properties: website_id: type: string examples: - web_abc123 hosts: type: array items: type: string examples: - - example.com examples: - website_id: web_abc123 hosts: - example.com 400: description: 'Missing both parameters.' content: application/json: schema: type: object properties: error: type: string examples: - 'either website_id or host is required' examples: - error: 'either website_id or host is required' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[internal] Caddy' security: [] x-discoverable: false /api/v1/internal/caddy/redirects: get: summary: 'Get Redirects' operationId: getApiV1InternalCaddyRedirects description: 'Get flattened active redirect and alias rules for a domain.' parameters: - in: query name: domain description: 'Domain to get redirects for.' required: true schema: type: string description: 'Domain to get redirects for.' examples: - example.com responses: 200: description: 'Redirects for domain.' content: application/json: schema: type: object properties: redirect: type: - string - 'null' examples: - null redirects: type: array items: type: object properties: source_path: type: string examples: - /old destination_url: type: string examples: - /new status_code: type: integer examples: - 301 examples: - - source_path: /old destination_url: /new status_code: 301 aliases: type: array examples: - [] examples: - redirect: null redirects: - source_path: /old destination_url: /new status_code: 301 aliases: [] 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[internal] Caddy' security: [] x-discoverable: false /api/v1/internal/caddy/apex-validation: get: summary: 'Validate Apex Redirect Host' operationId: getApiV1InternalCaddyApexValidation description: 'Approve on-demand TLS for an apex pointed at the redirect server: the host must be a registered apex with a redirect role and a real redirect target.' parameters: - in: query name: domain description: 'Apex host to validate.' required: true schema: type: string description: 'Apex host to validate.' examples: - acme.com responses: 200: description: 'Apex allowed.' content: application/json: schema: type: object properties: valid: type: boolean examples: - true reason: type: string examples: - apex_redirect target: type: string examples: - www.acme.com examples: - valid: true reason: apex_redirect target: www.acme.com 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[internal] Caddy' security: [] x-discoverable: false /api/v1/internal/caddy/platform/limits: get: summary: 'Get Component Limits' operationId: getApiV1InternalCaddyPlatformLimits description: 'Get the platform component-limits document with defaults and per-IP overrides.' parameters: [] responses: 200: description: 'Component limits document.' content: application/json: schema: type: object properties: limits: type: object properties: services: type: object properties: data: type: object properties: default: type: integer examples: - 100 overrides: type: array examples: - [] examples: - limits: services: data: default: 100 overrides: [] 500: $ref: '#/components/responses/InternalServerError' tags: - '[internal] Caddy' security: [] x-discoverable: false /api/v1/internal/library-items: get: summary: 'List Items' operationId: getApiV1InternalLibraryItems description: 'List library items, optionally filtered by website. Internal only.' parameters: - in: query name: 'filter[website_id]' description: 'Filter by website prefixed ID.' required: false schema: type: string description: 'Filter by website prefixed ID.' examples: - web_abc123 - in: query name: search description: 'Search term (searches name).' required: false schema: type: string description: 'Search term (searches name).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 15 - in: query name: include description: 'Comma-separated relations (library, folder).' required: false schema: type: string description: 'Comma-separated relations (library, folder).' examples: - 'library,folder' responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryItemPaginatedResponse' example: success: true data: - id: li_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 name: 'labore fugit' folder_id: null content: blocks: [] thumbnail_url: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: li_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 name: 'labore fugit' folder_id: null content: blocks: [] thumbnail_url: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Items retrieved successfully' 500: $ref: '#/components/responses/InternalServerError' tags: - '[internal] Library' security: [] x-discoverable: false '/api/v1/internal/library-items/{item}': get: summary: 'Get Item' operationId: getApiV1InternalLibraryItemsByItem description: 'Fetch a library item by prefixed ID. Internal only.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryItemResponse' example: success: true data: id: li_cb21a922bbf5a66c71a8cff2f98df9c0 library_id: lib_4c36cc1ae9ad4b9ceb043cb73e5ffd37 name: 'labore fugit' folder_id: null content: blocks: [] thumbnail_url: null created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Item retrieved successfully' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[internal] Library' security: [] x-discoverable: false parameters: - in: path name: item description: 'Item prefixed ID.' required: true schema: type: string examples: - li_abc123 '/api/v1/internal/websites/{website}/symbol-renames': get: summary: 'Symbol rename map' operationId: getApiV1InternalWebsitesByWebsiteSymbolRenames description: 'Resolve broken symbol references for a website. Internal only.' parameters: [] responses: 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[internal] Library' security: [] x-discoverable: false parameters: - in: path name: website description: 'Website prefixed ID.' required: true schema: type: string examples: - web_abc123 /api/v1/internal/platform/identifiers: get: summary: 'Get Platform Identifiers' operationId: getApiV1InternalPlatformIdentifiers description: 'Returns platform account, system library, and website prefixed IDs.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/PlatformIdentifiersResponse' example: success: true data: library: library_id: lib_cb21a922bbf5a66c71a8cff2f98df9c0 account_id: acc_4c36cc1ae9ad4b9ceb043cb73e5ffd37 account_email: royal.haag@example.com website_id: web_a614e951c258b49b953c5353e8f035a4 message: 'Platform identifiers retrieved' 500: $ref: '#/components/responses/InternalServerError' tags: - '[internal] Platform' security: [] x-discoverable: false /api/v1/internal/platform/maintenance: put: summary: 'Toggle Platform Maintenance' operationId: putApiV1InternalPlatformMaintenance description: 'Enable or disable maintenance mode for the entire platform.' parameters: [] responses: 200: description: 'Platform maintenance mode updated.' content: application/json: schema: $ref: '#/components/schemas/MaintenanceStateResponse' example: success: true data: enabled: false html: '

Maintenance

' message: 'Platform maintenance mode updated successfully' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[internal] Platform' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MaintenanceStateRequest' security: [] x-discoverable: false '/api/v1/internal/token/{component}': post: summary: 'Mint component JWT' operationId: postApiV1InternalTokenByComponent description: 'Mints a component-actor JWT for an account and/or website context. At least one of account or website is required. Internal requests only.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/MintTokenResponse' example: success: true data: token_type: Bearer access_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.YBCLu1qW1Xp1suAI9VcUADH4NzoFBhqWJYMK6nKqmjMynaPox92mZ8wTM3FtC9BLT5HPWvfFW5n0AF6wx7bEuXcl8PtnBn6DTnDM expires_in: 3600 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[internal] Tokens' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/MintComponentJwtRequest' security: [] x-discoverable: false parameters: - in: path name: component description: '' required: true schema: type: string examples: - aspernatur /api/v1/admin/tasks: get: summary: 'List Tasks' operationId: getApiV1AdminTasks description: 'Get registered tasks, including parameter definitions. Supports category filter, search, sort, and pagination.' parameters: - in: query name: 'filter[category]' description: 'Task category, e.g. platform.' required: false schema: type: string description: 'Task category, e.g. platform.' examples: - platform - in: query name: search description: 'Search tasks by name, command, or description.' required: false schema: type: string description: 'Search tasks by name, command, or description.' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending. Allowed: key, name, status, last_run_at, created_at.' required: false schema: type: string description: 'Sort field, prefix with - for descending. Allowed: key, name, status, last_run_at, created_at.' examples: - key - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page.' required: false schema: type: integer description: 'Items per page.' examples: - 25 responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[admin] Administration' '/api/v1/admin/tasks/{task}': get: summary: 'Get Task' operationId: getApiV1AdminTasksByTask description: 'Get a single task including the output of its current or last run.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/TaskResponse' example: success: true data: id: tsk_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 key: 'entitlements:resync' name: 'Resync entitlements' description: 'Recompute and re-publish website entitlements' command: 'entitlements:resync' category: platform parameters: - name: website label: Website type: argument required: false default: null status: idle current_output: "Re-published 42 website events\n" last_run_at: '2026-01-01T00:00:00+00:00' last_run_status: succeeded last_exit_code: 0 last_triggered_by: acc_4oju80peu12xkf9k6n0wbsnzve1jb1b3 created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Task retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[admin] Administration' parameters: - in: path name: task description: 'Prefixed task ID.' required: true schema: type: string examples: - tsk_abc123 '/api/v1/admin/tasks/{task}/run': post: summary: 'Run Task' operationId: postApiV1AdminTasksByTaskRun description: 'Start a task run. Returns 409 while the task is already running.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/TaskResponse' example: success: true data: id: tsk_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 key: 'entitlements:resync' name: 'Resync entitlements' description: 'Recompute and re-publish website entitlements' command: 'entitlements:resync' category: platform parameters: - name: website label: Website type: argument required: false default: null status: idle current_output: "Re-published 42 website events\n" last_run_at: '2026-01-01T00:00:00+00:00' last_run_status: succeeded last_exit_code: 0 last_triggered_by: acc_4oju80peu12xkf9k6n0wbsnzve1jb1b3 created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Task started' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[admin] Administration' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/RunTaskRequest' parameters: - in: path name: task description: 'Prefixed task ID.' required: true schema: type: string examples: - tsk_abc123 '/api/v1/accounts/{account}/tags': post: summary: 'Attach Tags to Account' operationId: postApiV1AccountsByAccountTags description: 'Attach tags to an account.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[tag] Tags' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AttachTagsRequest' parameters: - in: path name: account description: 'Account prefixed ID.' required: true schema: type: string examples: - acc_abc123 '/api/v1/accounts/{account}/tags/{tag}': delete: summary: 'Detach Tag from Account' operationId: deleteApiV1AccountsByAccountTagsByTag description: 'Detach a tag from an account.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[tag] Tags' parameters: - in: path name: account description: 'Account prefixed ID.' required: true schema: type: string examples: - acc_abc123 - in: path name: tag description: 'Prefixed tag ID.' required: true schema: type: string examples: - tag_abc123 '/api/v1/websites/{website}/tags': post: summary: 'Attach Tags to Website' operationId: postApiV1WebsitesByWebsiteTags description: 'Attach tags to a website.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[tag] Tags' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AttachTagsRequest' parameters: - in: path name: website description: 'Website prefixed ID.' required: true schema: type: string examples: - web_abc123 '/api/v1/websites/{website}/tags/{tag}': delete: summary: 'Detach Tag from Website' operationId: deleteApiV1WebsitesByWebsiteTagsByTag description: 'Detach a tag from a website.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[tag] Tags' parameters: - in: path name: website description: 'Website prefixed ID.' required: true schema: type: string examples: - web_abc123 - in: path name: tag description: 'Prefixed tag ID.' required: true schema: type: string examples: - tag_abc123 '/api/v1/libraries/{library}/tags': post: summary: 'Attach Tags to Library' operationId: postApiV1LibrariesByLibraryTags description: 'Attach tags to a library.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[tag] Tags' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AttachTagsRequest' parameters: - in: path name: library description: 'Library prefixed ID.' required: true schema: type: string examples: - lib_abc123 '/api/v1/libraries/{library}/tags/{tag}': delete: summary: 'Detach Tag from Library' operationId: deleteApiV1LibrariesByLibraryTagsByTag description: 'Detach a tag from a library.' parameters: [] responses: 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[tag] Tags' parameters: - in: path name: library description: 'Library prefixed ID.' required: true schema: type: string examples: - lib_abc123 - in: path name: tag description: 'Prefixed tag ID.' required: true schema: type: string examples: - tag_abc123 /api/v1/tags: get: summary: 'List Tags' operationId: getApiV1Tags description: 'Search and list tags with optional entity-type filtering and pagination.' parameters: - in: query name: 'filter[entity_type]' description: 'Return tags applicable to this entity type.' required: false schema: type: string description: 'Return tags applicable to this entity type.' enum: - website - account - library examples: - website - in: query name: search description: 'Search term (searches name).' required: false schema: type: string description: 'Search term (searches name).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - name - in: query name: 'page[number]' description: 'Page number. Supplying this enables pagination.' required: false schema: type: integer description: 'Page number. Supplying this enables pagination.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100). Supplying this enables pagination.' required: false schema: type: integer description: 'Items per page (max 100). Supplying this enables pagination.' examples: - 25 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/TagCollectionResponse' example: success: true data: - id: tag_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: internal color: '#ff0000' icon: hash entity_type: website usage_count: 0 created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: tag_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: internal color: '#ff0000' icon: hash entity_type: website usage_count: 0 created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Tags retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 500: $ref: '#/components/responses/InternalServerError' tags: - '[tag] Tags' post: summary: 'Create Tag' operationId: postApiV1Tags description: 'Create a tag.' parameters: [] responses: 201: description: '' content: application/json: schema: $ref: '#/components/schemas/TagResponse' example: success: true data: id: tag_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: internal color: '#ff0000' icon: hash entity_type: website usage_count: 0 created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Tag created successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[tag] Tags' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateTagRequest' '/api/v1/tags/{tag}': get: summary: 'Get Tag' operationId: getApiV1TagsByTag description: 'Get a single tag.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/TagResponse' example: success: true data: id: tag_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: internal color: '#ff0000' icon: hash entity_type: website usage_count: 0 created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Tag retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[tag] Tags' patch: summary: 'Update Tag' operationId: patchApiV1TagsByTag description: 'Update a tag.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/TagResponse' example: success: true data: id: tag_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: internal color: '#ff0000' icon: hash entity_type: website usage_count: 0 created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Tag updated successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 422: $ref: '#/components/responses/ValidationFailed' 500: $ref: '#/components/responses/InternalServerError' tags: - '[tag] Tags' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/UpdateTagRequest' delete: summary: 'Delete Tag' operationId: deleteApiV1TagsByTag description: 'Delete a tag.' parameters: [] responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/TagResponse' example: success: true data: id: tag_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: internal color: '#ff0000' icon: hash entity_type: website usage_count: 0 created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' message: 'Tag deleted successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[tag] Tags' parameters: - in: path name: tag description: 'Prefixed tag ID.' required: true schema: type: string examples: - tag_abc123 '/api/v1/tags/{tag}/websites': get: summary: 'List Websites Using a Tag' operationId: getApiV1TagsByTagWebsites description: 'List websites carrying the tag.' parameters: - in: query name: search description: 'Search term (searches name, domain).' required: false schema: type: string description: 'Search term (searches name, domain).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 25 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/WebsitePaginatedResponse' example: success: true data: - id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: web_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 code: myro name: Fisher-Gerhold domain: parisian.com status: enabled plan: trial paid_until: '2027-01-01T00:00:00+00:00' active_until: null owner: id: acc_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 firstname: Izaiah lastname: Walker email: kenneth78@yahoo.com provisioning: id: ecf_953c5353e8f035a4d595b04fec3f54bd status: pending progress: ready: 2 total: 4 started_at: '2026-01-01T00:00:00+00:00' deadline_at: '2026-01-01T00:02:00+00:00' completed_at: null maintenance: false maintenance_html: null roles: - 'website:admin' tags: - id: tag_kojfwg3n3koga2340faf03gb9a796tht name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Websites retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[tag] Tags' parameters: - in: path name: tag description: 'Prefixed tag ID.' required: true schema: type: string examples: - tag_abc123 '/api/v1/tags/{tag}/accounts': get: summary: 'List Accounts Using a Tag' operationId: getApiV1TagsByTagAccounts description: 'List accounts carrying the tag.' parameters: - in: query name: search description: 'Search term (searches name, surname, email).' required: false schema: type: string description: 'Search term (searches name, surname, email).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 25 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/AccountPaginatedResponse' example: success: true data: - id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - 'console:account' permissions: - 'ai:use' websites_count: 3 websites: null tags: - id: tag_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' avatar_file_id: null - id: acc_gzu16lymnbzhqmyw7hikcnvqf9kxfd84 name: Aisha surname: Runolfsdottir username: grady16 email: green16@example.net status: enabled roles: - 'console:account' permissions: - 'ai:use' websites_count: 3 websites: null tags: - id: tag_kf9k6n0wbsnzve1jb1b3retjvy35a2x0 name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' avatar_file_id: null meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Accounts retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[tag] Tags' parameters: - in: path name: tag description: 'Prefixed tag ID.' required: true schema: type: string examples: - tag_abc123 '/api/v1/tags/{tag}/libraries': get: summary: 'List Libraries Using a Tag' operationId: getApiV1TagsByTagLibraries description: 'List libraries carrying the tag.' parameters: - in: query name: search description: 'Search term (searches name).' required: false schema: type: string description: 'Search term (searches name).' examples: - aspernatur - in: query name: sort description: 'Sort field, prefix with - for descending.' required: false schema: type: string description: 'Sort field, prefix with - for descending.' examples: - '-created_at' - in: query name: 'page[number]' description: 'Page number.' required: false schema: type: integer description: 'Page number.' examples: - 1 - in: query name: 'page[size]' description: 'Items per page (max 100).' required: false schema: type: integer description: 'Items per page (max 100).' examples: - 25 responses: 200: description: '' content: application/json: schema: $ref: '#/components/schemas/LibraryPaginatedResponse' example: success: true data: - id: lib_cb21a922bbf5a66c71a8cff2f98df9c0 name: 'reprehenderit qui' is_system: false is_website_library: false items_count: 25 websites_count: 7 owner_account_id: acc_cc1ae9ad4b9ceb043cb73e5ffd373ad3 owner: firstname: Susana lastname: Grimes email: upton.marcelina@gmail.com roles: - 'library:owner' tags: - id: tag_w6pgb8pnh17o5r1byozkr5qglt1l740z name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' - id: lib_cb21a922bbf5a66c71a8cff2f98df9c0 name: 'reprehenderit qui' is_system: false is_website_library: false items_count: 25 websites_count: 7 owner_account_id: acc_cc1ae9ad4b9ceb043cb73e5ffd373ad3 owner: firstname: Susana lastname: Grimes email: upton.marcelina@gmail.com roles: - 'library:owner' tags: - id: tag_w6pgb8pnh17o5r1byozkr5qglt1l740z name: internal color: '#ff0000' icon: hash created_at: '2026-01-01T00:00:00+00:00' updated_at: '2026-01-01T00:00:00+00:00' meta: current_page: 1 last_page: 5 per_page: 15 total: 73 message: 'Libraries retrieved successfully' 401: $ref: '#/components/responses/Unauthenticated' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' 500: $ref: '#/components/responses/InternalServerError' tags: - '[tag] Tags' parameters: - in: path name: tag description: 'Prefixed tag ID.' required: true schema: type: string examples: - tag_abc123