openapi: 3.0.3 info: title: 'RosettaChat API Documentation' description: 'RosettaChat V1 API for authentication, file staging, Workspace Channel chat, Direct Chat, attachments, automation, and webhooks.' version: 1.0.0 servers: - url: 'http://localhost' tags: - name: 'App Authentication' description: "\nToken-based authentication APIs for native mobile/desktop applications" - name: 'App Authentication - Social' description: "\nToken-based social authentication APIs for native mobile/desktop applications" - name: Devices description: '' - name: 'Email Verification' description: "\nVerify and resend email verification links." - name: Endpoints description: '' - name: 'External Temporary Rooms' description: '' - name: Files description: '' - name: Me description: '' - name: 'Shared Authentication' description: "\nShared authentication APIs that work with both token and cookie-based authentication" - name: 'Web Authentication' description: "\nCookie-based authentication APIs for Single Page Applications (SPA)" - name: 'Web Authentication - Social' description: "\nCookie-based social authentication APIs for Single Page Applications (SPA)" components: securitySchemes: default: type: http scheme: bearer description: 'Most application endpoints use Laravel Sanctum bearer tokens. Workspace automation endpoints require a token with the documented automation ability. Webhook endpoints authenticate with their webhook secret instead of bearer auth.' security: - default: [] paths: /api/v1/auth/app/register: post: summary: Register operationId: register description: 'Create a new user account and return an access token.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: access_token: 1|abc123... token_type: Bearer user: id: 1 name: 'John Doe' email: john@example.com properties: access_token: type: string example: 1|abc123... token_type: type: string example: Bearer user: type: object properties: id: type: integer example: 1 name: type: string example: 'John Doe' email: type: string example: john@example.com 422: description: 'Validation error' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: email: - 'This email is already registered.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: email: type: array example: - 'This email is already registered.' items: type: string tags: - 'App Authentication' requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: "The user's full name." example: 'John Doe' email: type: string description: "The user's email address. Must be unique." example: john@example.com password: type: string description: 'The password. Must be at least 8 characters.' example: secretpassword preferred_language: type: string description: '' example: id enum: - en - zh-CN - ja - th - id nullable: true password_confirmation: type: string description: 'Password confirmation. Must match password.' example: secretpassword device_name: type: string description: 'The device name for the token.' example: 'iPhone 15 Pro' required: - name - email - password - password_confirmation security: [] /api/v1/auth/app/login: post: summary: Login operationId: login description: 'Authenticate user with email and password, return an access token.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: access_token: 1|abc123... token_type: Bearer user: id: 1 name: 'John Doe' email: john@example.com properties: access_token: type: string example: 1|abc123... token_type: type: string example: Bearer user: type: object properties: id: type: integer example: 1 name: type: string example: 'John Doe' email: type: string example: john@example.com 403: description: 'Account inactive' content: application/json: schema: type: object example: message: 'Account is inactive.' properties: message: type: string example: 'Account is inactive.' 422: description: 'Invalid credentials' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: email: - 'The provided credentials are incorrect.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: email: type: array example: - 'The provided credentials are incorrect.' items: type: string tags: - 'App Authentication' requestBody: required: true content: application/json: schema: type: object properties: email: type: string description: "The user's email address." example: john@example.com password: type: string description: "The user's password." example: secretpassword device_name: type: string description: 'The device name for the token.' example: 'iPhone 15 Pro' required: - email - password security: [] /api/v1/auth/app/otp: post: summary: 'Request OTP' operationId: requestOTP description: "Send a One-Time Password to the user's email for passwordless authentication." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'OTP sent to your email.' properties: message: type: string example: 'OTP sent to your email.' 422: description: 'Validation error' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: email: - 'The email field must be a valid email address.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: email: type: array example: - 'The email field must be a valid email address.' items: type: string tags: - 'App Authentication' requestBody: required: true content: application/json: schema: type: object properties: email: type: string description: 'The email address to send the OTP to.' example: john@example.com required: - email security: [] /api/v1/auth/app/otp/verify: post: summary: 'Verify OTP' operationId: verifyOTP description: "Verify the One-Time Password and return an access token.\nCreates a new account if the email is not registered." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: access_token: 1|abc123... token_type: Bearer user: id: 1 name: john email: john@example.com properties: access_token: type: string example: 1|abc123... token_type: type: string example: Bearer user: type: object properties: id: type: integer example: 1 name: type: string example: john email: type: string example: john@example.com 403: description: 'Account inactive' content: application/json: schema: type: object example: message: 'Account is inactive.' properties: message: type: string example: 'Account is inactive.' 422: description: 'Invalid OTP' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: token: - 'Invalid or expired OTP.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: token: type: array example: - 'Invalid or expired OTP.' items: type: string tags: - 'App Authentication' requestBody: required: true content: application/json: schema: type: object properties: email: type: string description: 'The email address.' example: john@example.com token: type: string description: 'The 6-digit OTP code.' example: '123456' device_name: type: string description: 'The device name for the token.' example: 'iPhone 15 Pro' required: - email - token security: [] /api/v1/auth/app/forgot-password: post: summary: 'Forgot Password' operationId: forgotPassword description: "Send a password reset link to the user's email." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Password reset link sent to your email.' properties: message: type: string example: 'Password reset link sent to your email.' 422: description: 'Email not found' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: email: - 'We could not find an account with that email.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: email: type: array example: - 'We could not find an account with that email.' items: type: string tags: - 'App Authentication' requestBody: required: true content: application/json: schema: type: object properties: email: type: string description: 'The registered email address.' example: john@example.com required: - email security: [] /api/v1/auth/app/reset-password: post: summary: 'Reset Password' operationId: resetPassword description: "Reset the user's password using the reset token." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Password has been reset successfully.' properties: message: type: string example: 'Password has been reset successfully.' 422: description: 'Invalid token' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: email: - 'This password reset token is invalid.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: email: type: array example: - 'This password reset token is invalid.' items: type: string tags: - 'App Authentication' requestBody: required: true content: application/json: schema: type: object properties: token: type: string description: 'The password reset token from email.' example: abc123def456... email: type: string description: "The user's email address." example: john@example.com password: type: string description: 'The new password. Must be at least 8 characters.' example: newsecretpassword password_confirmation: type: string description: 'Password confirmation. Must match password.' example: newsecretpassword required: - token - email - password - password_confirmation security: [] /api/v1/auth/app/logout: post: summary: Logout operationId: logout description: 'Revoke the current access token.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Logged out successfully.' properties: message: type: string example: 'Logged out successfully.' 401: description: Unauthenticated content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - 'App Authentication' /api/v1/auth/app/change-password: post: summary: 'Change Password' operationId: changePassword description: "Change the authenticated user's password." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Password changed successfully.' properties: message: type: string example: 'Password changed successfully.' 401: description: Unauthenticated content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 422: description: 'Wrong current password' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: current_password: - 'The current password is incorrect.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: current_password: type: array example: - 'The current password is incorrect.' items: type: string tags: - 'App Authentication' requestBody: required: true content: application/json: schema: type: object properties: current_password: type: string description: 'The current password.' example: oldsecretpassword password: type: string description: 'The new password. Must be at least 8 characters.' example: newsecretpassword password_confirmation: type: string description: 'New password confirmation. Must match password.' example: newsecretpassword required: - current_password - password - password_confirmation '/api/v1/auth/app/social/{provider}/redirect': post: summary: 'Get OAuth Redirect URL' operationId: getOAuthRedirectURL description: "Get the OAuth redirect URL for the specified provider.\nThe client should open this URL in a browser to start the OAuth flow." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: redirect_url: 'https://accounts.google.com/o/oauth2/v2/auth?...' properties: redirect_url: type: string example: 'https://accounts.google.com/o/oauth2/v2/auth?...' 422: description: 'Invalid provider' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: provider: - 'The selected provider is invalid.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: provider: type: array example: - 'The selected provider is invalid.' items: type: string tags: - 'App Authentication - Social' security: [] parameters: - in: path name: provider description: 'The OAuth provider name.' example: google required: true schema: type: string '/api/v1/auth/app/social/{provider}/callback': post: summary: 'OAuth Callback' operationId: oAuthCallback description: "Exchange the OAuth code for an access token and authenticate the user.\nReturns a Bearer token for subsequent API requests." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: access_token: 1|abc123... token_type: Bearer user: id: 1 name: 'John Doe' email: john@example.com properties: access_token: type: string example: 1|abc123... token_type: type: string example: Bearer user: type: object properties: id: type: integer example: 1 name: type: string example: 'John Doe' email: type: string example: john@example.com 403: description: 'Account inactive' content: application/json: schema: type: object example: message: 'Account is inactive.' properties: message: type: string example: 'Account is inactive.' 422: description: 'Invalid provider' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: provider: - 'The selected provider is invalid.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: provider: type: array example: - 'The selected provider is invalid.' items: type: string tags: - 'App Authentication - Social' requestBody: required: true content: application/json: schema: type: object properties: code: type: string description: 'The OAuth authorization code from the provider.' example: 4/0AfJohXn... state: type: string description: 'The state parameter for CSRF protection.' example: xyz123 device_name: type: string description: 'Device name for the token.' example: 'iPhone 15 Pro' required: - code security: [] parameters: - in: path name: provider description: 'The OAuth provider name.' example: google required: true schema: type: string /api/v1/auth/app/social/accounts: get: summary: 'List Linked Accounts' operationId: listLinkedAccounts description: 'Get all social accounts linked to the authenticated user.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: accounts: - id: 1 provider: google provider_email: john@gmail.com name: 'John Doe' avatar: 'https://...' created_at: '2024-01-01T00:00:00.000000Z' properties: accounts: type: array example: - id: 1 provider: google provider_email: john@gmail.com name: 'John Doe' avatar: 'https://...' created_at: '2024-01-01T00:00:00.000000Z' items: type: object properties: id: type: integer example: 1 provider: type: string example: google provider_email: type: string example: john@gmail.com name: type: string example: 'John Doe' avatar: type: string example: 'https://...' created_at: type: string example: '2024-01-01T00:00:00.000000Z' 401: description: Unauthenticated content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - 'App Authentication - Social' '/api/v1/auth/app/social/{provider}/link': post: summary: 'Link Social Account' operationId: linkSocialAccount description: "Link a new social account to the authenticated user.\nReturns the OAuth redirect URL for the linking flow." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: redirect_url: 'https://accounts.google.com/o/oauth2/v2/auth?...' properties: redirect_url: type: string example: 'https://accounts.google.com/o/oauth2/v2/auth?...' 401: description: Unauthenticated content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 422: description: 'Invalid provider' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: provider: - 'The selected provider is invalid.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: provider: type: array example: - 'The selected provider is invalid.' items: type: string tags: - 'App Authentication - Social' parameters: - in: path name: provider description: 'The OAuth provider name.' example: google required: true schema: type: string '/api/v1/auth/app/social/{provider}/link/callback': post: summary: 'Complete Link Social Account' operationId: completeLinkSocialAccount description: 'Complete the social account linking after OAuth callback.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: account: id: 1 provider: google provider_email: john@gmail.com name: 'John Doe' message: 'Social account linked successfully.' properties: account: type: object properties: id: type: integer example: 1 provider: type: string example: google provider_email: type: string example: john@gmail.com name: type: string example: 'John Doe' message: type: string example: 'Social account linked successfully.' 401: description: Unauthenticated content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 422: description: '' content: application/json: schema: oneOf: - description: 'Already linked' type: object example: message: 'This social account is already linked to your account.' properties: message: type: string example: 'This social account is already linked to your account.' - description: 'Linked to another user' type: object example: message: 'This social account is already linked to another user.' properties: message: type: string example: 'This social account is already linked to another user.' tags: - 'App Authentication - Social' requestBody: required: true content: application/json: schema: type: object properties: code: type: string description: 'The OAuth authorization code from the provider.' example: 4/0AfJohXn... state: type: string description: '' example: architecto device_name: type: string description: 'Must not be greater than 255 characters.' example: 'n' required: - code parameters: - in: path name: provider description: 'The OAuth provider name.' example: google required: true schema: type: string '/api/v1/auth/app/social/{provider}/unlink': delete: summary: 'Unlink Social Account' operationId: unlinkSocialAccount description: 'Remove a linked social account from the authenticated user.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Social account unlinked successfully.' properties: message: type: string example: 'Social account unlinked successfully.' 401: description: Unauthenticated content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 404: description: 'Not found' content: application/json: schema: type: object example: message: 'Social account not found.' properties: message: type: string example: 'Social account not found.' 422: description: 'Last auth method' content: application/json: schema: type: object example: message: 'Cannot unlink the last authentication method. Please set a password first.' properties: message: type: string example: 'Cannot unlink the last authentication method. Please set a password first.' tags: - 'App Authentication - Social' parameters: - in: path name: provider description: 'The OAuth provider name.' example: google required: true schema: type: string /api/v1/devices: post: summary: 'Register a push device.' operationId: registerAPushDevice description: "Registers (or refreshes) the calling user's device for push\nnotifications. The push token is the identity: re-sending an existing\ntoken — even from a different account — transfers ownership so a\nrecycled device never receives the previous user's notifications.\nIdempotent; safe to call on every app launch." parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: data: id: 01HX... platform: ios provider: fcm device_name: "John's iPhone" last_used_at: '2026-05-17T10:00:00+00:00' properties: data: type: object properties: id: type: string example: 01HX... platform: type: string example: ios provider: type: string example: fcm device_name: type: string example: "John's iPhone" last_used_at: type: string example: '2026-05-17T10:00:00+00:00' tags: - Devices requestBody: required: true content: application/json: schema: type: object properties: platform: type: string description: 'OS family. One of `ios`, `android`, `web`.' example: ios provider: type: string description: 'Push transport. One of `fcm`, `expo`, `apns`.' example: fcm push_token: type: string description: 'The provider-issued push token.' example: fGc1...token device_id: type: string description: 'Optional stable client device identifier.' example: 7B3F2A10-... nullable: true device_name: type: string description: 'Optional human-readable device label.' example: "John's iPhone" nullable: true app_version: type: string description: 'Optional client app version.' example: 1.4.2 nullable: true required: - platform - provider - push_token '/api/v1/devices/{id}': delete: summary: 'Unregister a push device.' operationId: unregisterAPushDevice description: "Removes one of the caller's registered devices. Only the owner may\ndelete a device." parameters: [] responses: 204: description: '' content: application/json: schema: type: object example: { } properties: { } tags: - Devices parameters: - in: path name: id description: 'The ID of the device.' example: architecto required: true schema: type: string - in: path name: device description: 'The device id.' example: 01HX... required: true schema: type: string '/api/v1/auth/email/verify/{id}/{hash}': get: summary: 'Verify Email' operationId: verifyEmail description: "Confirms ownership of the email address via a temporary signed URL.\nOn success, redirects to the configured frontend URL when set,\notherwise returns a JSON success response." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Email verified successfully.' properties: message: type: string example: 'Email verified successfully.' 404: description: 'Invalid link' content: application/json: schema: type: object example: message: 'Verification link is invalid.' properties: message: type: string example: 'Verification link is invalid.' tags: - 'Email Verification' security: [] parameters: - in: path name: id description: 'The user id encoded into the link.' example: 16 required: true schema: type: integer - in: path name: hash description: 'The sha1(email) hash encoded into the link.' example: architecto required: true schema: type: string /api/v1/auth/email/verification-notification: post: summary: 'Resend Verification Email' operationId: resendVerificationEmail description: "Re-sends the verification email to the authenticated user. Returns 200\neven when the account is already verified (to avoid leaking state)." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Verification email sent.' properties: message: type: string example: 'Verification email sent.' tags: - 'Email Verification' /api/v1/me: patch: summary: '' operationId: patchApiV1Me description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: false content: application/json: schema: type: object properties: name: type: string description: 'Must not be greater than 255 characters.' example: b preferred_language: type: string description: '' example: zh-CN enum: - en - zh-CN - ja - th - id avatar_url: type: string description: 'Must be a valid URL. Must not be greater than 2048 characters.' example: 'http://bailey.com/' nullable: true security: [] get: summary: 'Get Current User' operationId: getCurrentUser description: "Retrieve the authenticated user's information.\nWorks with both token-based and cookie-based authentication." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 1 name: 'John Doe' email: john@example.com email_verified_at: '2024-01-01T00:00:00.000000Z' is_active: true last_login_at: '2024-01-15T10:30:00.000000Z' created_at: '2024-01-01T00:00:00.000000Z' updated_at: '2024-01-15T10:30:00.000000Z' properties: id: type: integer example: 1 name: type: string example: 'John Doe' email: type: string example: john@example.com email_verified_at: type: string example: '2024-01-01T00:00:00.000000Z' is_active: type: boolean example: true last_login_at: type: string example: '2024-01-15T10:30:00.000000Z' created_at: type: string example: '2024-01-01T00:00:00.000000Z' updated_at: type: string example: '2024-01-15T10:30:00.000000Z' 401: description: Unauthenticated content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - 'Shared Authentication' '/api/v1/invites/{token}': get: summary: "Public preview of an invite so the join screen can show what the user is\nabout to join — even before they sign in." operationId: publicPreviewOfAnInviteSoTheJoinScreenCanShowWhatTheUserIsAboutToJoinEvenBeforeTheySignIn description: '' parameters: [] responses: 404: description: '' content: application/json: schema: type: object example: message: 'This invite link is not valid.' properties: message: type: string example: 'This invite link is not valid.' tags: - Endpoints security: [] parameters: - in: path name: token description: '' example: architecto required: true schema: type: string '/api/v1/invites/{token}/accept': post: summary: 'Redeem an invite: add the authenticated user to the workspace.' operationId: redeemAnInviteAddTheAuthenticatedUserToTheWorkspace description: '' parameters: [] responses: { } tags: - Endpoints security: [] parameters: - in: path name: token description: '' example: architecto required: true schema: type: string /api/v1/workspaces: get: summary: '' operationId: getApiV1Workspaces description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] post: summary: '' operationId: postApiV1Workspaces description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: 'Must not be greater than 120 characters.' example: b slug: type: string description: 'Must contain only letters, numbers, dashes and underscores. Must not be greater than 80 characters.' example: 'n' nullable: true visibility: type: string description: '' example: null nullable: true password: type: string description: 'Must be at least 8 characters. Must not be greater than 120 characters.' example: '|{+-0pBNvYgx' nullable: true required: - name security: [] '/api/v1/workspaces/{id}': get: summary: '' operationId: getApiV1WorkspacesId description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] parameters: - in: path name: id description: 'The ID of the workspace.' example: 01ktvxyqmbcm7abv91483q1hfd required: true schema: type: string /api/v1/direct-conversations: get: summary: '' operationId: getApiV1DirectConversations description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] post: summary: '' operationId: postApiV1DirectConversations description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: true content: application/json: schema: type: object properties: participant_user_id: type: string description: '' example: architecto required: - participant_user_id security: [] /api/v1/direct-recipients/resolve: post: summary: '' operationId: postApiV1DirectRecipientsResolve description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: true content: application/json: schema: type: object properties: email: type: string description: 'Must be a valid email address. Must not be greater than 255 characters.' example: gbailey@example.net required: - email security: [] '/api/v1/direct-conversations/{conversation_id}/messages': get: summary: '' operationId: getApiV1DirectConversationsConversation_idMessages description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] post: summary: '' operationId: postApiV1DirectConversationsConversation_idMessages description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: false content: application/json: schema: type: object properties: content: type: string description: 'This field is required when attachment_ids is not present.' example: architecto nullable: true attachment_ids: type: array description: '' example: - architecto items: type: string security: [] parameters: - in: path name: conversation_id description: 'The ID of the conversation.' example: 01ktvxyqq8nx0zyqm8rtrcp3xa required: true schema: type: string '/api/v1/message-attachments/{attachment_id}/download': get: summary: '' operationId: getApiV1MessageAttachmentsAttachment_idDownload description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] parameters: - in: path name: attachment_id description: 'The ID of the attachment.' example: architecto required: true schema: type: string '/api/v1/direct-message-attachments/{attachment_id}/download': get: summary: '' operationId: getApiV1DirectMessageAttachmentsAttachment_idDownload description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] parameters: - in: path name: attachment_id description: 'The ID of the attachment.' example: architecto required: true schema: type: string '/api/v1/workspaces/{workspace_id}/channels': get: summary: '' operationId: getApiV1WorkspacesWorkspace_idChannels description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] post: summary: '' operationId: postApiV1WorkspacesWorkspace_idChannels description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: 'Must not be greater than 120 characters.' example: b slug: type: string description: 'Must contain only letters, numbers, dashes and underscores. Must not be greater than 80 characters.' example: 'n' nullable: true visibility: type: string description: '' example: null nullable: true password: type: string description: 'Must be at least 8 characters. Must not be greater than 120 characters.' example: '|{+-0pBNvYgx' nullable: true required: - name security: [] parameters: - in: path name: workspace_id description: 'The ID of the workspace.' example: 01ktvxyqmbcm7abv91483q1hfd required: true schema: type: string '/api/v1/workspaces/{workspace_id}/channels/{id}': put: summary: '' operationId: putApiV1WorkspacesWorkspace_idChannelsId description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: false content: application/json: schema: type: object properties: name: type: string description: 'Must not be greater than 120 characters.' example: b slug: type: string description: 'Must contain only letters, numbers, dashes and underscores. Must not be greater than 80 characters.' example: 'n' visibility: type: string description: '' example: null password: type: string description: 'Must be at least 8 characters. Must not be greater than 120 characters.' example: '|{+-0pBNvYgx' nullable: true security: [] delete: summary: '' operationId: deleteApiV1WorkspacesWorkspace_idChannelsId description: '' parameters: [] responses: { } tags: - Endpoints security: [] parameters: - in: path name: workspace_id description: 'The ID of the workspace.' example: 01ktvxyqmbcm7abv91483q1hfd required: true schema: type: string - in: path name: id description: 'The ID of the channel.' example: 01ktvxyqn17t8d0w6jx8t2k6e8 required: true schema: type: string '/api/v1/workspaces/{workspace_id}/members': get: summary: '' operationId: getApiV1WorkspacesWorkspace_idMembers description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] parameters: - in: path name: workspace_id description: 'The ID of the workspace.' example: 01ktvxyqmbcm7abv91483q1hfd required: true schema: type: string '/api/v1/workspaces/{workspace_id}/members/{id}': put: summary: '' operationId: putApiV1WorkspacesWorkspace_idMembersId description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: true content: application/json: schema: type: object properties: role: type: string description: '' example: architecto preferred_language: type: string description: '' example: architecto required: - role security: [] delete: summary: '' operationId: deleteApiV1WorkspacesWorkspace_idMembersId description: '' parameters: [] responses: { } tags: - Endpoints security: [] parameters: - in: path name: workspace_id description: 'The ID of the workspace.' example: 01ktvxyqmbcm7abv91483q1hfd required: true schema: type: string - in: path name: id description: 'The ID of the member.' example: 01ktvxyqme70jcjz30my99v5hb required: true schema: type: string '/api/v1/workspaces/{workspace_id}/invites': get: summary: '' operationId: getApiV1WorkspacesWorkspace_idInvites description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] post: summary: '' operationId: postApiV1WorkspacesWorkspace_idInvites description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: false content: application/json: schema: type: object properties: expires_in_days: type: integer description: 'Must be at least 1. Must not be greater than 365.' example: 1 nullable: true security: [] parameters: - in: path name: workspace_id description: 'The ID of the workspace.' example: 01ktvxyqmbcm7abv91483q1hfd required: true schema: type: string '/api/v1/workspaces/{workspace_id}/invites/{id}': delete: summary: '' operationId: deleteApiV1WorkspacesWorkspace_idInvitesId description: '' parameters: [] responses: { } tags: - Endpoints security: [] parameters: - in: path name: workspace_id description: 'The ID of the workspace.' example: 01ktvxyqmbcm7abv91483q1hfd required: true schema: type: string - in: path name: id description: 'The ID of the invite.' example: 01ktwzbyvaea33cwb6grhj3f3e required: true schema: type: string '/api/v1/workspaces/{workspace_id}/webhooks': get: summary: '' operationId: getApiV1WorkspacesWorkspace_idWebhooks description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] post: summary: '' operationId: postApiV1WorkspacesWorkspace_idWebhooks description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: 'Must not be greater than 120 characters.' example: b default_channel_id: type: string description: '' example: architecto nullable: true required: - name security: [] parameters: - in: path name: workspace_id description: 'The ID of the workspace.' example: 01ktvxyqmbcm7abv91483q1hfd required: true schema: type: string '/api/v1/workspaces/{workspace_id}/webhooks/{id}': put: summary: '' operationId: putApiV1WorkspacesWorkspace_idWebhooksId description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: false content: application/json: schema: type: object properties: name: type: string description: 'Must not be greater than 120 characters.' example: b default_channel_id: type: string description: '' example: architecto nullable: true is_active: type: boolean description: '' example: true regenerate_secret: type: boolean description: '' example: false security: [] delete: summary: '' operationId: deleteApiV1WorkspacesWorkspace_idWebhooksId description: '' parameters: [] responses: { } tags: - Endpoints security: [] parameters: - in: path name: workspace_id description: 'The ID of the workspace.' example: 01ktvxyqmbcm7abv91483q1hfd required: true schema: type: string - in: path name: id description: 'The ID of the webhook.' example: architecto required: true schema: type: string '/api/v1/workspaces/{workspace_id}/channels/{channel_id}/messages': get: summary: '' operationId: getApiV1WorkspacesWorkspace_idChannelsChannel_idMessages description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] post: summary: '' operationId: postApiV1WorkspacesWorkspace_idChannelsChannel_idMessages description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: false content: application/json: schema: type: object properties: content: type: string description: 'This field is required when attachment_ids is not present.' example: architecto nullable: true attachment_ids: type: array description: '' example: - architecto items: type: string parent_message_id: type: string description: '' example: null nullable: true type: type: string description: '' example: null nullable: true skip_translation: type: boolean description: '' example: false nullable: true security: [] parameters: - in: path name: workspace_id description: 'The ID of the workspace.' example: 01ktvxyqmbcm7abv91483q1hfd required: true schema: type: string - in: path name: channel_id description: 'The ID of the channel.' example: 01ktvxyqn17t8d0w6jx8t2k6e8 required: true schema: type: string '/api/v1/automation/workspaces/{workspace_id}/channels/{channel_id}/messages': post: summary: '' operationId: postApiV1AutomationWorkspacesWorkspace_idChannelsChannel_idMessages description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: false content: application/json: schema: type: object properties: content: type: string description: 'This field is required when attachment_ids is not present.' example: architecto nullable: true attachment_ids: type: array description: '' example: - architecto items: type: string parent_message_id: type: string description: '' example: null nullable: true skip_translation: type: boolean description: '' example: false nullable: true security: [] parameters: - in: path name: workspace_id description: 'The ID of the workspace.' example: 01ktvxyqmbcm7abv91483q1hfd required: true schema: type: string - in: path name: channel_id description: 'The ID of the channel.' example: 01ktvxyqn17t8d0w6jx8t2k6e8 required: true schema: type: string '/api/v1/webhooks/{webhook_id}/messages': post: summary: '' operationId: postApiV1WebhooksWebhook_idMessages description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: true content: application/json: schema: type: object properties: content: type: string description: '' example: architecto channel_id: type: string description: '' example: architecto nullable: true skip_translation: type: boolean description: '' example: false nullable: true required: - content security: [] parameters: - in: path name: webhook_id description: 'The ID of the webhook.' example: architecto required: true schema: type: string /api/v1/external/rooms: post: summary: 'Create a Temporary Room' operationId: createATemporaryRoom description: 'Creates a developer-owned anonymous Temporary Room. Requires a Sanctum API token with `temporary-rooms:create`.' parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: data: room_id: 01HX... workspace_id: 01HX... channel_id: 01HX... name: 'Customer Support Room' kind: temporary_room status: active external_reference: customer-123 expires_at: '2026-06-12T12:00:00+00:00' max_expires_at: '2026-06-13T00:00:00+00:00' extension_count: 0 join: method: POST endpoint: 'https://api.example.test/api/v1/external/rooms/01HX.../guests' properties: data: type: object properties: room_id: type: string example: 01HX... workspace_id: type: string example: 01HX... channel_id: type: string example: 01HX... name: type: string example: 'Customer Support Room' kind: type: string example: temporary_room status: type: string example: active external_reference: type: string example: customer-123 expires_at: type: string example: '2026-06-12T12:00:00+00:00' max_expires_at: type: string example: '2026-06-13T00:00:00+00:00' extension_count: type: integer example: 0 join: type: object properties: method: type: string example: POST endpoint: type: string example: 'https://api.example.test/api/v1/external/rooms/01HX.../guests' 403: description: 'Temporary Room quota exceeded' content: application/json: schema: type: object example: message: 'Temporary Room active room limit exceeded.' errors: code: - temporary_room_quota_exceeded properties: message: type: string example: 'Temporary Room active room limit exceeded.' errors: type: object properties: code: type: array example: - temporary_room_quota_exceeded items: type: string 422: description: 'TTL exceeds limit' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: ttl_hours: - ttl_hours_exceeds_limit properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: ttl_hours: type: array example: - ttl_hours_exceeds_limit items: type: string tags: - 'External Temporary Rooms' requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: 'Room display name.' example: 'Customer Support Room' external_reference: type: string description: 'Optional developer-side reference id.' example: customer-123 nullable: true ttl_hours: type: integer description: 'Optional room lifetime in hours. Defaults to 24 and is capped by owner limits.' example: 12 nullable: true required: - name get: summary: 'List developer-owned Temporary Rooms' operationId: listDeveloperOwnedTemporaryRooms description: 'Requires a Sanctum API token with `temporary-rooms:read`.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: - room_id: 01HX... kind: temporary_room status: active properties: data: type: array example: - room_id: 01HX... kind: temporary_room status: active items: type: object properties: room_id: type: string example: 01HX... kind: type: string example: temporary_room status: type: string example: active tags: - 'External Temporary Rooms' /api/v1/external/rooms/usage: get: summary: 'Show Temporary Room usage summary' operationId: showTemporaryRoomUsageSummary description: 'Requires a Sanctum API token with `temporary-rooms:read`.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: limits: active_limit: 3 monthly_creation_limit: 10 usage: active_room_count: 1 monthly_creation_count: 2 abuse_signals: active_limit_reached: false monthly_creation_limit_reached: false properties: data: type: object properties: limits: type: object properties: active_limit: type: integer example: 3 monthly_creation_limit: type: integer example: 10 usage: type: object properties: active_room_count: type: integer example: 1 monthly_creation_count: type: integer example: 2 abuse_signals: type: object properties: active_limit_reached: type: boolean example: false monthly_creation_limit_reached: type: boolean example: false tags: - 'External Temporary Rooms' '/api/v1/external/rooms/{room_id}/extend': post: summary: 'Extend a Temporary Room' operationId: extendATemporaryRoom description: 'Requires a Sanctum API token with `temporary-rooms:extend` and paid/developer Temporary Room limits.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: room_id: 01HX... expires_at: '2026-06-13T12:00:00+00:00' max_expires_at: '2026-07-12T12:00:00+00:00' extension_count: 1 properties: data: type: object properties: room_id: type: string example: 01HX... expires_at: type: string example: '2026-06-13T12:00:00+00:00' max_expires_at: type: string example: '2026-07-12T12:00:00+00:00' extension_count: type: integer example: 1 403: description: 'Extension not allowed' content: application/json: schema: type: object example: message: 'Temporary Room extension is not allowed.' errors: code: - temporary_room_extension_not_allowed properties: message: type: string example: 'Temporary Room extension is not allowed.' errors: type: object properties: code: type: array example: - temporary_room_extension_not_allowed items: type: string 422: description: 'Extension exceeds max' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: extension_hours: - extension_hours_exceeds_limit properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: extension_hours: type: array example: - extension_hours_exceeds_limit items: type: string tags: - 'External Temporary Rooms' requestBody: required: false content: application/json: schema: type: object properties: extension_hours: type: integer description: 'Optional extension amount in hours. Defaults to the owner single-extension max.' example: 24 nullable: true parameters: - in: path name: room_id description: 'The ID of the room.' example: 01ktvxyqmbcm7abv91483q1hfd required: true schema: type: string '/api/v1/external/rooms/{room_id}/guests': post: summary: 'Join a Temporary Room as a guest' operationId: joinATemporaryRoomAsAGuest description: 'Creates a restricted guest user and one guest session token scoped to this Temporary Room.' parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: data: guest: id: 01HX... nickname: Mei preferred_language: zh-CN session: token: grst_... token_type: guest header: X-Rosetta-Guest-Token expires_at: '2026-06-12T12:00:00+00:00' room: room_id: 01HX... workspace_id: 01HX... channel_id: 01HX... name: 'Customer Support Room' status: active expires_at: '2026-06-12T12:00:00+00:00' properties: data: type: object properties: guest: type: object properties: id: type: string example: 01HX... nickname: type: string example: Mei preferred_language: type: string example: zh-CN session: type: object properties: token: type: string example: grst_... token_type: type: string example: guest header: type: string example: X-Rosetta-Guest-Token expires_at: type: string example: '2026-06-12T12:00:00+00:00' room: type: object properties: room_id: type: string example: 01HX... workspace_id: type: string example: 01HX... channel_id: type: string example: 01HX... name: type: string example: 'Customer Support Room' status: type: string example: active expires_at: type: string example: '2026-06-12T12:00:00+00:00' 410: description: 'Expired room' content: application/json: schema: type: object example: message: 'Temporary Room is not available.' errors: code: - temporary_room_expired properties: message: type: string example: 'Temporary Room is not available.' errors: type: object properties: code: type: array example: - temporary_room_expired items: type: string tags: - 'External Temporary Rooms' requestBody: required: true content: application/json: schema: type: object properties: nickname: type: string description: 'Guest display nickname.' example: Mei preferred_language: type: string description: 'Guest preferred language.' example: zh-CN required: - nickname - preferred_language security: [] parameters: - in: path name: room_id description: 'The ID of the room.' example: 01ktvxyqmbcm7abv91483q1hfd required: true schema: type: string '/api/v1/external/rooms/{room_id}/messages': get: summary: 'List guest-visible room messages' operationId: listGuestVisibleRoomMessages description: 'Requires `X-Rosetta-Guest-Token`.' parameters: - in: header name: X-Rosetta-Guest-Token description: '' example: 'string required Guest session token.' schema: type: string responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 01HX... display_content: Hello display_source: original properties: data: type: array example: - id: 01HX... display_content: Hello display_source: original items: type: object properties: id: type: string example: 01HX... display_content: type: string example: Hello display_source: type: string example: original tags: - 'External Temporary Rooms' security: [] post: summary: 'Send a guest room message' operationId: sendAGuestRoomMessage description: 'Requires `X-Rosetta-Guest-Token`.' parameters: - in: header name: X-Rosetta-Guest-Token description: '' example: 'string required Guest session token.' schema: type: string responses: 201: description: '' content: application/json: schema: type: object example: data: id: 01HX... original_content: 'Hello team' translation_status: pending properties: data: type: object properties: id: type: string example: 01HX... original_content: type: string example: 'Hello team' translation_status: type: string example: pending tags: - 'External Temporary Rooms' requestBody: required: false content: application/json: schema: type: object properties: content: type: string description: 'Message text. Required unless attachment_ids is present.' example: 'Hello team' nullable: true attachment_ids: type: array description: 'Optional staged file ids.' example: - architecto items: type: string parent_message_id: type: string description: 'Optional parent message id for a thread reply.' example: architecto nullable: true skip_translation: type: boolean description: 'Optional. Defaults to false.' example: false nullable: true security: [] parameters: - in: path name: room_id description: 'The ID of the room.' example: 01ktvxyqmbcm7abv91483q1hfd required: true schema: type: string /api/v1/files: post: summary: 'Upload a file.' operationId: uploadAFile description: "Returns the created file record with a TTL. Persist the returned id on\na parent record and call FileService::claim() to opt out of cleanup." parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: data: id: 01HX... client_name: photo.jpg size: 12345 expires_at: '2026-05-11T05:00:00+00:00' properties: data: type: object properties: id: type: string example: 01HX... client_name: type: string example: photo.jpg size: type: integer example: 12345 expires_at: type: string example: '2026-05-11T05:00:00+00:00' tags: - Files requestBody: required: true content: multipart/form-data: schema: type: object properties: file: type: string format: binary description: 'The file to upload.' visibility: type: string description: 'Optional. `public` or `private`. Defaults to the configured visibility.' example: architecto nullable: true meta: type: object description: 'Optional. Free-form metadata stored alongside the record.' example: [] properties: { } nullable: true required: - file '/api/v1/files/{id}': get: summary: 'Show file metadata.' operationId: showFileMetadata description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Files delete: summary: 'Delete a file (soft delete + remove from disk).' operationId: deleteAFilesoftDelete+RemoveFromDisk description: '' parameters: [] responses: { } tags: - Files parameters: - in: path name: id description: 'The ID of the file.' example: architecto required: true schema: type: string '/api/v1/files/{file_id}/download': get: summary: 'Stream the file contents to the client.' operationId: streamTheFileContentsToTheClient description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Files parameters: - in: path name: file_id description: 'The ID of the file.' example: architecto required: true schema: type: string /api/v1/me/files: get: summary: 'List my files.' operationId: listMyFiles description: "Returns files owned by the authenticated user. By default only claimed\n(persistent) files are listed — pass `?claimed=false` to see files\nthat still carry a TTL. Anonymously uploaded files are never listed\nhere regardless of filters." parameters: - in: query name: claimed description: 'Filter by claim state. `true` = persistent (no TTL), `false` = pending. Defaults to `true`.' example: true required: false schema: type: boolean description: 'Filter by claim state. `true` = persistent (no TTL), `false` = pending. Defaults to `true`.' example: true - in: query name: visibility description: 'Filter by visibility. `public` or `private`.' example: private required: false schema: type: string description: 'Filter by visibility. `public` or `private`.' example: private - in: query name: q description: 'Substring search on the original client filename.' example: invoice required: false schema: type: string description: 'Substring search on the original client filename.' example: invoice - in: query name: sort description: 'One of `created_at`, `-created_at`, `size`, `-size`. Defaults to `-created_at`.' example: '-created_at' required: false schema: type: string description: 'One of `created_at`, `-created_at`, `size`, `-size`. Defaults to `-created_at`.' example: '-created_at' - in: query name: per_page description: '1–100. Defaults to 15.' example: 20 required: false schema: type: integer description: '1–100. Defaults to 15.' example: 20 - in: query name: page description: 1+. example: 1 required: false schema: type: integer description: 1+. example: 1 responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 01HX... client_name: photo.jpg meta: current_page: 1 links: { } properties: data: type: array example: - id: 01HX... client_name: photo.jpg items: type: object properties: id: type: string example: 01HX... client_name: type: string example: photo.jpg meta: type: object properties: current_page: type: integer example: 1 links: type: object properties: { } tags: - Me requestBody: required: false content: application/json: schema: type: object properties: claimed: type: boolean description: '' example: true nullable: true visibility: type: string description: '' example: public enum: - public - private nullable: true q: type: string description: 'Must not be greater than 255 characters.' example: b nullable: true sort: type: string description: '' example: '-created_at' enum: - created_at - '-created_at' - size - '-size' nullable: true per_page: type: integer description: 'Must be at least 1. Must not be greater than 100.' example: 22 nullable: true page: type: integer description: 'Must be at least 1.' example: 67 nullable: true /api/v1/me/devices: get: summary: 'List my push devices.' operationId: listMyPushDevices description: "Returns the push-notification devices registered to the authenticated\nuser. Raw push tokens are never returned." parameters: - in: query name: provider description: 'Filter by push transport. One of `fcm`, `expo`, `apns`.' example: fcm required: false schema: type: string description: 'Filter by push transport. One of `fcm`, `expo`, `apns`.' example: fcm - in: query name: sort description: 'One of `last_used_at`, `-last_used_at`, `created_at`, `-created_at`. Defaults to `-last_used_at`.' example: '-last_used_at' required: false schema: type: string description: 'One of `last_used_at`, `-last_used_at`, `created_at`, `-created_at`. Defaults to `-last_used_at`.' example: '-last_used_at' - in: query name: per_page description: '1–100. Defaults to 15.' example: 20 required: false schema: type: integer description: '1–100. Defaults to 15.' example: 20 - in: query name: page description: 1+. example: 1 required: false schema: type: integer description: 1+. example: 1 responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 01HX... platform: ios provider: fcm meta: current_page: 1 links: { } properties: data: type: array example: - id: 01HX... platform: ios provider: fcm items: type: object properties: id: type: string example: 01HX... platform: type: string example: ios provider: type: string example: fcm meta: type: object properties: current_page: type: integer example: 1 links: type: object properties: { } tags: - Me requestBody: required: false content: application/json: schema: type: object properties: provider: type: string description: '' example: expo enum: - fcm - expo - apns nullable: true sort: type: string description: '' example: '-last_used_at' enum: - last_used_at - '-last_used_at' - created_at - '-created_at' nullable: true per_page: type: integer description: 'Must be at least 1. Must not be greater than 100.' example: 1 nullable: true page: type: integer description: 'Must be at least 1.' example: 22 nullable: true /api/v1/auth/web/register: post: summary: Register operationId: register description: 'Create a new user account and establish a session.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: user: id: 1 name: 'John Doe' email: john@example.com message: 'Registered successfully.' properties: user: type: object properties: id: type: integer example: 1 name: type: string example: 'John Doe' email: type: string example: john@example.com message: type: string example: 'Registered successfully.' 422: description: 'Validation error' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: email: - 'This email is already registered.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: email: type: array example: - 'This email is already registered.' items: type: string tags: - 'Web Authentication' requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: "The user's full name." example: 'John Doe' email: type: string description: "The user's email address. Must be unique." example: john@example.com password: type: string description: 'The password. Must be at least 8 characters.' example: secretpassword preferred_language: type: string description: '' example: en enum: - en - zh-CN - ja - th - id nullable: true password_confirmation: type: string description: 'Password confirmation. Must match password.' example: secretpassword required: - name - email - password - password_confirmation security: [] /api/v1/auth/web/login: post: summary: Login operationId: login description: 'Authenticate user with email and password, establish a session.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: user: id: 1 name: 'John Doe' email: john@example.com message: 'Logged in successfully.' properties: user: type: object properties: id: type: integer example: 1 name: type: string example: 'John Doe' email: type: string example: john@example.com message: type: string example: 'Logged in successfully.' 403: description: 'Account inactive' content: application/json: schema: type: object example: message: 'Account is inactive.' properties: message: type: string example: 'Account is inactive.' 422: description: 'Invalid credentials' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: email: - 'The provided credentials are incorrect.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: email: type: array example: - 'The provided credentials are incorrect.' items: type: string tags: - 'Web Authentication' requestBody: required: true content: application/json: schema: type: object properties: email: type: string description: "The user's email address." example: john@example.com password: type: string description: "The user's password." example: secretpassword device_name: type: string description: 'Must not be greater than 255 characters.' example: v required: - email - password security: [] /api/v1/auth/web/otp: post: summary: 'Request OTP' operationId: requestOTP description: "Send a One-Time Password to the user's email for passwordless authentication." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'OTP sent to your email.' properties: message: type: string example: 'OTP sent to your email.' 422: description: 'Validation error' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: email: - 'The email field must be a valid email address.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: email: type: array example: - 'The email field must be a valid email address.' items: type: string tags: - 'Web Authentication' requestBody: required: true content: application/json: schema: type: object properties: email: type: string description: 'The email address to send the OTP to.' example: john@example.com required: - email security: [] /api/v1/auth/web/otp/verify: post: summary: 'Verify OTP' operationId: verifyOTP description: "Verify the One-Time Password and establish a session.\nCreates a new account if the email is not registered." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: user: id: 1 name: john email: john@example.com message: 'Logged in successfully.' properties: user: type: object properties: id: type: integer example: 1 name: type: string example: john email: type: string example: john@example.com message: type: string example: 'Logged in successfully.' 403: description: 'Account inactive' content: application/json: schema: type: object example: message: 'Account is inactive.' properties: message: type: string example: 'Account is inactive.' 422: description: 'Invalid OTP' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: token: - 'Invalid or expired OTP.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: token: type: array example: - 'Invalid or expired OTP.' items: type: string tags: - 'Web Authentication' requestBody: required: true content: application/json: schema: type: object properties: email: type: string description: 'The email address.' example: john@example.com token: type: string description: 'The 6-digit OTP code.' example: '123456' device_name: type: string description: 'Must not be greater than 255 characters.' example: j required: - email - token security: [] /api/v1/auth/web/forgot-password: post: summary: 'Forgot Password' operationId: forgotPassword description: "Send a password reset link to the user's email." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Password reset link sent to your email.' properties: message: type: string example: 'Password reset link sent to your email.' 422: description: 'Email not found' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: email: - 'We could not find an account with that email.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: email: type: array example: - 'We could not find an account with that email.' items: type: string tags: - 'Web Authentication' requestBody: required: true content: application/json: schema: type: object properties: email: type: string description: 'The registered email address.' example: john@example.com required: - email security: [] /api/v1/auth/web/reset-password: post: summary: 'Reset Password' operationId: resetPassword description: "Reset the user's password using the reset token." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Password has been reset successfully.' properties: message: type: string example: 'Password has been reset successfully.' 422: description: 'Invalid token' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: email: - 'This password reset token is invalid.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: email: type: array example: - 'This password reset token is invalid.' items: type: string tags: - 'Web Authentication' requestBody: required: true content: application/json: schema: type: object properties: token: type: string description: 'The password reset token from email.' example: abc123def456... email: type: string description: "The user's email address." example: john@example.com password: type: string description: 'The new password. Must be at least 8 characters.' example: newsecretpassword password_confirmation: type: string description: 'Password confirmation. Must match password.' example: newsecretpassword required: - token - email - password - password_confirmation security: [] /api/v1/auth/web/logout: post: summary: Logout operationId: logout description: 'Destroy the current session.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Logged out successfully.' properties: message: type: string example: 'Logged out successfully.' 401: description: Unauthenticated content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - 'Web Authentication' /api/v1/auth/web/change-password: post: summary: 'Change Password' operationId: changePassword description: "Change the authenticated user's password." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Password changed successfully.' properties: message: type: string example: 'Password changed successfully.' 401: description: Unauthenticated content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 422: description: 'Wrong current password' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: current_password: - 'The current password is incorrect.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: current_password: type: array example: - 'The current password is incorrect.' items: type: string tags: - 'Web Authentication' requestBody: required: true content: application/json: schema: type: object properties: current_password: type: string description: 'The current password.' example: oldsecretpassword password: type: string description: 'The new password. Must be at least 8 characters.' example: newsecretpassword password_confirmation: type: string description: 'New password confirmation. Must match password.' example: newsecretpassword required: - current_password - password - password_confirmation '/api/v1/auth/web/social/{provider}/redirect': post: summary: 'Get OAuth Redirect URL' operationId: getOAuthRedirectURL description: "Get the OAuth redirect URL for the specified provider.\nThe client should open this URL in a browser to start the OAuth flow." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: redirect_url: 'https://accounts.google.com/o/oauth2/v2/auth?...' properties: redirect_url: type: string example: 'https://accounts.google.com/o/oauth2/v2/auth?...' 422: description: 'Invalid provider' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: provider: - 'The selected provider is invalid.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: provider: type: array example: - 'The selected provider is invalid.' items: type: string tags: - 'Web Authentication - Social' security: [] parameters: - in: path name: provider description: 'The OAuth provider name.' example: google required: true schema: type: string '/api/v1/auth/web/social/{provider}/callback': post: summary: 'OAuth Callback' operationId: oAuthCallback description: "Exchange the OAuth code for a session and authenticate the user.\nEstablishes a session cookie for subsequent requests." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: user: id: 1 name: 'John Doe' email: john@example.com message: 'Logged in successfully.' properties: user: type: object properties: id: type: integer example: 1 name: type: string example: 'John Doe' email: type: string example: john@example.com message: type: string example: 'Logged in successfully.' 403: description: 'Account inactive' content: application/json: schema: type: object example: message: 'Account is inactive.' properties: message: type: string example: 'Account is inactive.' 422: description: 'Invalid provider' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: provider: - 'The selected provider is invalid.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: provider: type: array example: - 'The selected provider is invalid.' items: type: string tags: - 'Web Authentication - Social' requestBody: required: true content: application/json: schema: type: object properties: code: type: string description: 'The OAuth authorization code from the provider.' example: 4/0AfJohXn... state: type: string description: 'The state parameter for CSRF protection.' example: xyz123 device_name: type: string description: 'Must not be greater than 255 characters.' example: 'n' required: - code security: [] parameters: - in: path name: provider description: 'The OAuth provider name.' example: google required: true schema: type: string /api/v1/auth/web/social/accounts: get: summary: 'List Linked Accounts' operationId: listLinkedAccounts description: 'Get all social accounts linked to the authenticated user.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: accounts: - id: 1 provider: google provider_email: john@gmail.com name: 'John Doe' avatar: 'https://...' created_at: '2024-01-01T00:00:00.000000Z' properties: accounts: type: array example: - id: 1 provider: google provider_email: john@gmail.com name: 'John Doe' avatar: 'https://...' created_at: '2024-01-01T00:00:00.000000Z' items: type: object properties: id: type: integer example: 1 provider: type: string example: google provider_email: type: string example: john@gmail.com name: type: string example: 'John Doe' avatar: type: string example: 'https://...' created_at: type: string example: '2024-01-01T00:00:00.000000Z' 401: description: Unauthenticated content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - 'Web Authentication - Social' '/api/v1/auth/web/social/{provider}/link': post: summary: 'Link Social Account' operationId: linkSocialAccount description: "Link a new social account to the authenticated user.\nReturns the OAuth redirect URL for the linking flow." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: redirect_url: 'https://accounts.google.com/o/oauth2/v2/auth?...' properties: redirect_url: type: string example: 'https://accounts.google.com/o/oauth2/v2/auth?...' 401: description: Unauthenticated content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 422: description: 'Invalid provider' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: provider: - 'The selected provider is invalid.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: provider: type: array example: - 'The selected provider is invalid.' items: type: string tags: - 'Web Authentication - Social' parameters: - in: path name: provider description: 'The OAuth provider name.' example: google required: true schema: type: string '/api/v1/auth/web/social/{provider}/link/callback': post: summary: 'Complete Link Social Account' operationId: completeLinkSocialAccount description: 'Complete the social account linking after OAuth callback.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: account: id: 1 provider: google provider_email: john@gmail.com name: 'John Doe' message: 'Social account linked successfully.' properties: account: type: object properties: id: type: integer example: 1 provider: type: string example: google provider_email: type: string example: john@gmail.com name: type: string example: 'John Doe' message: type: string example: 'Social account linked successfully.' 401: description: Unauthenticated content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 422: description: '' content: application/json: schema: oneOf: - description: 'Already linked' type: object example: message: 'This social account is already linked to your account.' properties: message: type: string example: 'This social account is already linked to your account.' - description: 'Linked to another user' type: object example: message: 'This social account is already linked to another user.' properties: message: type: string example: 'This social account is already linked to another user.' tags: - 'Web Authentication - Social' requestBody: required: true content: application/json: schema: type: object properties: code: type: string description: 'The OAuth authorization code from the provider.' example: 4/0AfJohXn... state: type: string description: '' example: architecto device_name: type: string description: 'Must not be greater than 255 characters.' example: 'n' required: - code parameters: - in: path name: provider description: 'The OAuth provider name.' example: google required: true schema: type: string '/api/v1/auth/web/social/{provider}/unlink': delete: summary: 'Unlink Social Account' operationId: unlinkSocialAccount description: 'Remove a linked social account from the authenticated user.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Social account unlinked successfully.' properties: message: type: string example: 'Social account unlinked successfully.' 401: description: Unauthenticated content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 404: description: 'Not found' content: application/json: schema: type: object example: message: 'Social account not found.' properties: message: type: string example: 'Social account not found.' 422: description: 'Last auth method' content: application/json: schema: type: object example: message: 'Cannot unlink the last authentication method. Please set a password first.' properties: message: type: string example: 'Cannot unlink the last authentication method. Please set a password first.' tags: - 'Web Authentication - Social' parameters: - in: path name: provider description: 'The OAuth provider name.' example: google required: true schema: type: string