"openapi": "3.0.3"
"info":
  "title": "MUDBASESDK"
  "description": "MUDBASE is a scalable, real-time, and secure Backend-as-a-Service (BaaS) platform\ 

    designed for modern applications. Built with custom logic, it offers fine-grained\ 

    control, extensibility, and enterprise-grade security.


    ## Features

    - 🔐 Multi-provider authentication (30+ OAuth providers)

    - 📊 Real-time database with collections

    - 📁 File storage and management

    - 🔑 API key management with permissions

    - 🔗 Webhook system with retry logic

    - ⚡ Serverless functions

    - 💬 Multi-channel messaging (Push, Email, SMS)

    - 📈 Usage analytics and monitoring

    - 🌐 Real-time WebSocket events

    - 🔍 Full-text search capabilities

    - 💳 Billing: Flutterwave for fiat (platform subscriptions and payment processing with 7% + $0.50 split); crypto payment processor for multi-chain checkout

    - 📡 Block-based multi-chain wallet monitoring (ETH/UTXO scanners, GetBlock, scanner metrics API)\n"
  "version": "1.2.12"
  "contact":
    "name": "MUDBASE Support"
    "url": "https://mudbase.dev/support"
    "email": "support@mudbase.dev"
  "license":
    "name": "MIT"
    "url": "https://opensource.org/licenses/MIT"
"servers":
  - "url": "https://cloud.mudbase.dev"
    "description": "Production server"
"tags":
  - "name": "auth"
    "description": "User authentication and authorization"
  - "name": "users"
    "description": "User profile management"
  - "name": "collections"
    "description": "Database schema and collection management"
  - "name": "data"
    "description": "CRUD operations on collection data"
  - "name": "storage"
    "description": "Buckets and file storage (buckets, files, upload, signed URLs)"
  - "name": "webhooks"
    "description": "Webhook configuration and logs"
  - "name": "functions"
    "description": "Serverless function management"
  - "name": "messaging"
    "description": "Push notifications, email, and SMS"
  - "name": "usage"
    "description": "Project-level usage and analytics. Use /api/usage/projects/{projectId} and /api/usage/trends.\n"
  - "name": "search"
    "description": "Full-text search capabilities"
  - "name": "wallet"
    "description": "Cryptocurrency wallet management. Supports multiple chains (EVM, UTXO, Solana, Tron, TON, Cardano).

      **Production flow (non-custodial):** Register addresses (POST /api/wallet/non-custodial/register-address), get network fee (POST /api/wallet/estimate-network-fee or GET /api/wallet/fees), build and sign tx client-side, broadcast (POST /api/wallet/non-custodial/broadcast). Stuck EVM txs: GET replacement params (POST speed-up or cancel), sign and broadcast again.

      **Custodial endpoints (for testing only):** Create wallet (POST /api/wallet/create), get private key (GET /api/wallet/{walletId}/private-key), register that address in non-custodial, then use estimate-network-fee + broadcast to test the full flow. Custodial withdraw (POST /api/wallet/{walletId}/withdraw) returns a **semi-transaction** (signedTx, chain, fromAddress)—it does not broadcast; you broadcast it via POST /api/wallet/non-custodial/broadcast. Supports all platform chains/currencies. Transactions appear in the same transaction list and can be speed-up/canceled via nonce.

      **Network fee only:** POST /api/wallet/estimate-network-fee and POST /api/wallet/calculate-fee return **network fee only** (from blockchain). No platform or project fee in fee estimation. See docs/FEE_ARCHITECTURE.md.\n"
  - "name": "billing"
    "description": "Billing and subscription management. Fiat via Flutterwave (platform subscriptions and payment processing with 7% + $0.50 split). Crypto checkout via multi-chain payment processor.

      Project checkout and subscription endpoints are documented here.\n"
  - "name": "chat"
    "description": "Real-time chat and messaging"
  - "name": "integrations"
    "description": "Third-party service integrations"
  - "name": "multiRole"
    "description": "Project app roles (starter `customer` role) with per-collection CRUD; add roles via API and match signup paths to each role's `signupEndpoint`"
  - "name": "roleElevation"
    "description": "Configurable role elevation with admin approval support"
  - "name": "compliance"
    "description": "Compliance automation and security event logging (GDPR, SOC 2)"
  - "name": "realtimeAnalytics"
    "description": "Real-time analytics and monitoring endpoints"
  - "name": "health"
    "description": "System health and status"
"paths":
  "/api/auth/local/register":
    "post":
      "tags":
        - "auth"
      "summary": "Register new user"
      "operationId": "auth.register"
      "x-display-name": "Register User"
      "x-sdk-method": "register"
      "description": "When the project has **requireEmailVerification** enabled (default), the response is 201 with **requireVerification: true** and **no token**; the user must verify their email then sign in via login. When email verification is disabled, a token and refreshToken are returned.\n"
      "security": []
      "requestBody":
        "required": true
        "description": "Registration payload (email, password, firstName, lastName, projectId)."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "email"
                - "password"
                - "firstName"
                - "lastName"
                - "projectId"
              "properties":
                "email":
                  "type": "string"
                  "format": "email"
                "password":
                  "type": "string"
                  "minLength": 8
                "firstName":
                  "type": "string"
                "lastName":
                  "type": "string"
                "projectId":
                  "type": "string"
            "example":
              "email": "sarah.chen@example.com"
              "password": "SecurePass123!"
              "firstName": "Sarah"
              "lastName": "Chen"
              "projectId": "685ad30be129932fbb7a1047"
      "responses":
        "201":
          "description": "When project.requireEmailVerification is on (default): no token returned; use requireVerification and message to prompt email verification, then user signs in via login. When off: token and refreshToken returned.\n"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "message":
                    "type": "string"
                  "requireVerification":
                    "type": "boolean"
                    "description": "true when email verification is required; no token in response"
                  "token":
                    "type": "string"
                    "description": "Present only when requireEmailVerification is false"
                  "refreshToken":
                    "type": "string"
                    "description": "Present only when requireEmailVerification is false"
                  "expiresIn":
                    "type": "integer"
                    "description": "Present only when token is returned"
                  "user":
                    "type": "object"
                    "properties":
                      "id":
                        "type": "string"
                      "email":
                        "type": "string"
                      "firstName":
                        "type": "string"
                      "lastName":
                        "type": "string"
                      "emailVerified":
                        "type": "boolean"
                      "customRole":
                        "type": "string"
              "examples":
                "emailVerificationOn":
                  "summary": "Email verification ON (default) — no token until verified"
                  "value":
                    "message": "Check your email to verify your account"
                    "requireVerification": true
                "emailVerificationOff":
                  "summary": "Email verification OFF — token returned immediately"
                  "value":
                    "message": "Registration successful"
                    "requireVerification": false
                    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                    "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                    "expiresIn": 65051
                    "user":
                      "id": "685acbe0e129932fbb7a0fc2"
                      "email": "john.doe@mudbase.dev"
                      "firstName": "John"
                      "lastName": "Doe"
                      "emailVerified": true
                      "customRole": null
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "Project not found (exact backend message)."
          "$ref": "#/components/responses/ProjectNotFound"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
  "/api/auth/local/login":
    "post":
      "tags":
        - "auth"
      "summary": "Login user"
      "operationId": "auth.login"
      "x-display-name": "Login User"
      "x-sdk-method": "login"
      "description": "When the project has **requireEmailVerification** enabled and the user has not verified their email, returns 403 with code **EMAIL_VERIFICATION_REQUIRED** (user must verify email first, then login again).\n"
      "security": []
      "requestBody":
        "required": true
        "description": "Login credentials (email, password) and project ID."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "email"
                - "password"
              "properties":
                "email":
                  "type": "string"
                  "format": "email"
                "password":
                  "type": "string"
                "projectId":
                  "type": "string"
            "example":
              "email": "sarah.chen@example.com"
              "password": "SecurePass123!"
              "projectId": "685ad30be129932fbb7a1047"
      "responses":
        "200":
          "description": "Login successful"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "message":
                    "type": "string"
                  "token":
                    "type": "string"
                    "description": "JWT access token (use in Authorization Bearer header)"
                  "refreshToken":
                    "type": "string"
                    "description": "JWT refresh token (use with POST /api/auth/refresh to get new token pair)"
                  "expiresIn":
                    "type": "integer"
                    "description": "Access token TTL in seconds (e.g. 1800 for 30 minutes)"
                  "user":
                    "type": "object"
                    "properties":
                      "id":
                        "type": "string"
                      "email":
                        "type": "string"
                      "firstName":
                        "type": "string"
                      "lastName":
                        "type": "string"
                      "role":
                        "type": "string"
                      "emailVerified":
                        "type": "boolean"
                      "twoFactorEnabled":
                        "type": "boolean"
              "example":
                "message": "Login successful"
                "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                "expiresIn": 1800
                "user":
                  "id": "685acbe0e129932fbb7a0fc2"
                  "email": "john.doe@mudbase.dev"
                  "firstName": "John"
                  "lastName": "Doe"
                  "role": "developer"
                  "emailVerified": true
                  "twoFactorEnabled": false
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Email verification required (project has requireEmailVerification and user has not verified)"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "error":
                    "type": "string"
                  "code":
                    "type": "string"
                  "message":
                    "type": "string"
              "example":
                "error": "Email verification required"
                "code": "EMAIL_VERIFICATION_REQUIRED"
                "message": "Please verify your email to sign in. Check your inbox for the verification link."
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
  "/api/auth/refresh":
    "post":
      "tags":
        - "auth"
      "summary": "Refresh access token (dashboard and project)"
      "operationId": "auth.refresh"
      "x-display-name": "Refresh Token"
      "x-sdk-method": "refresh"
      "description": "Exchange a valid refresh token for a new JWT access token and refresh token.

        Works for both **dashboard** (builder console) and **app** (end-user) auth; the same endpoint is used.

        The previous refresh token is invalidated (rotation). If the same refresh token is used again, the session is revoked (reuse detection).\n"
      "security": []
      "requestBody":
        "required": true
        "description": "JSON body containing the refresh token to exchange for a new access token and refresh token (token rotation)."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "refreshToken"
              "properties":
                "refreshToken":
                  "type": "string"
                  "description": "The refresh token returned from login/sign-in (dashboard or project)"
            "example":
              "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
      "responses":
        "200":
          "description": "New token pair issued"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "message":
                    "type": "string"
                    "example": "Token refreshed successfully"
                  "token":
                    "type": "string"
                    "description": "New JWT access token"
                  "refreshToken":
                    "type": "string"
                    "description": "New refresh token (store and use for next refresh)"
                  "expiresIn":
                    "type": "integer"
                    "description": "Access token TTL in seconds"
                    "example": 1800
              "example":
                "message": "Token refreshed successfully"
                "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                "expiresIn": 1800
        "400":
          "description": "Missing refresh token"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "error":
                    "type": "string"
              "example":
                "error": "Refresh token is required"
        "401":
          "description": "Invalid or expired refresh token (or reuse detected)"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "error":
                    "type": "string"
              "example":
                "error": "Invalid or expired refresh token"
  "/api/auth/local/logout":
    "post":
      "tags":
        - "auth"
      "summary": "Logout user"
      "operationId": "auth.logout"
      "description": "Logout the current authenticated user session.

        Requires JWT Bearer token (BearerToken). API keys are not supported for this endpoint.\n"
      "security":
        - "BearerToken": []
      "responses":
        "200":
          "description": "Logout successful"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "Logout successful"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Logout user"
      "x-sdk-method": "logout"
  "/api/auth/local/session":
    "get":
      "tags":
        - "auth"
      "summary": "Get current session"
      "operationId": "auth.getSession"
      "x-display-name": "Get Session"
      "x-sdk-method": "getSession"
      "description": "Get the current authenticated user session.

        Requires JWT Bearer token (BearerToken). API keys are not supported for this endpoint.\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "query"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID to get session for."
      "responses":
        "200":
          "description": "Current session"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "user":
                    "type": "object"
                  "authenticated":
                    "type": "boolean"
              "example":
                "user":
                  "id": "685acbe0e129932fbb7a0fc2"
                  "email": "john.doe@mudbase.dev"
                  "firstName": "John"
                  "lastName": "Doe"
                  "project":
                    "id": "685ad30be129932fbb7a1047"
                    "name": "Mudbase Platform"
                    "role": "developer"
                "authenticated": true
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "404":
          "description": "Project not found (exact backend message)."
          "$ref": "#/components/responses/ProjectNotFound"
  "/api/auth/local/password-reset":
    "post":
      "tags":
        - "auth"
      "summary": "Request password reset (OTP)"
      "operationId": "auth.requestPasswordReset"
      "x-display-name": "Request Password Reset"
      "x-sdk-method": "requestPasswordReset"
      "description": "When projectId is provided, sends a 6-digit OTP to the user's email (app reset uses OTP, not link).

        When projectId is omitted, sends a token link (org/platform local account). Rate limited.\n"
      "security": []
      "requestBody":
        "required": true
        "description": "Email and optional projectId for app OTP or org token link."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "email"
              "properties":
                "email":
                  "type": "string"
                  "format": "email"
                  "example": "user@example.com"
                "projectId":
                  "type": "string"
                  "description": "Required for app reset (sends OTP). Omit for org token link."
                  "example": "685ad30be129932fbb7a1047"
            "example":
              "email": "user@example.com"
              "projectId": "685ad30be129932fbb7a1047"
      "responses":
        "200":
          "description": "OTP or reset email sent (generic message to prevent enumeration)"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "If an account exists, a verification code has been sent to your email"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "Project not found (exact backend message)."
          "$ref": "#/components/responses/ProjectNotFound"
        "429":
          "description": "Too many requests (rate limit)"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
  "/api/auth/local/password-reset/confirm":
    "post":
      "tags":
        - "auth"
      "summary": "Confirm password reset with OTP"
      "operationId": "auth.confirmPasswordReset"
      "description": "Set new password using the OTP sent to the user's email. Call after

        POST /api/auth/local/password-reset with projectId. Rate limited (OTP limit).

        If the user's email was not yet verified, it is marked as verified upon successful reset.\n"
      "security": []
      "requestBody":
        "required": true
        "description": "Email, projectId, OTP code, and new password."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "email"
                - "projectId"
                - "otp"
                - "newPassword"
              "properties":
                "email":
                  "type": "string"
                  "format": "email"
                  "example": "user@example.com"
                "projectId":
                  "type": "string"
                  "example": "685ad30be129932fbb7a1047"
                "otp":
                  "type": "string"
                  "minLength": 6
                  "maxLength": 6
                  "pattern": "^[0-9]+$"
                  "example": "123456"
                "newPassword":
                  "type": "string"
                  "minLength": 8
                  "example": "NewSecurePass123!"
            "example":
              "email": "user@example.com"
              "projectId": "685ad30be129932fbb7a1047"
              "otp": "123456"
              "newPassword": "NewSecurePass123!"
      "responses":
        "200":
          "description": "Password reset successful"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "Password reset successful"
        "400":
          "description": "Invalid or expired OTP, or validation error"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "Resource not found (exact backend message)."
          "$ref": "#/components/responses/NotFound"
        "429":
          "description": "Too many attempts (rate limit)"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Confirm password reset with OTP"
      "x-sdk-method": "confirmPasswordReset"
  "/api/auth/local/password-reset/{token}":
    "post":
      "tags":
        - "auth"
      "summary": "Reset password with token (legacy)"
      "operationId": "auth.resetPassword"
      "x-display-name": "Reset Password"
      "x-sdk-method": "resetPassword"
      "description": "Legacy token-based completion. Prefer OTP flow: use POST .../password-reset/confirm

        with the OTP sent to email for app resets.\n"
      "security": []
      "parameters":
        - "name": "token"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Password reset token from email link."
      "requestBody":
        "required": true
        "description": "New password and optional projectId."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "password"
              "properties":
                "password":
                  "type": "string"
                  "minLength": 8
                  "example": "NewSecurePass123!"
                "projectId":
                  "type": "string"
                  "example": "685ad30be129932fbb7a1047"
            "example":
              "password": "NewSecurePass123!"
              "projectId": "685ad30be129932fbb7a1047"
      "responses":
        "200":
          "description": "Password reset successful"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "Password reset successful"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
  "/api/auth/oauth/{provider}/{projectId}":
    "get":
      "tags":
        - "auth"
      "summary": "Initiate OAuth authentication"
      "security": []
      "description": "Initiates OAuth authentication flow for a specified provider and project.

        The OAuth provider must be configured and enabled for the project first.

        After user authentication, redirects to the OAuth provider's consent screen.\n"
      "operationId": "auth.oauthInitiate"
      "x-display-name": "Initiate OAuth"
      "x-sdk-method": "oauthInitiate"
      "parameters":
        - "name": "provider"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "enum":
              - "google"
              - "github"
              - "facebook"
              - "microsoft"
              - "apple"
              - "twitter"
              - "discord"
              - "linkedin"
              - "dropbox"
              - "slack"
              - "reddit"
              - "twitch"
              - "figma"
              - "zoom"
              - "bitbucket"
              - "salesforce"
              - "shopify"
              - "line"
              - "spotify"
              - "strava"
              - "paypal"
              - "asana"
              - "trello"
              - "okta"
              - "gitea"
              - "yandex"
              - "yahoo"
              - "vk"
              - "meetup"
          "description": "OAuth provider identifier (e.g. google, github)."
          "example": "google"
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "685ad30be129932fbb7a1047"
          "description": "Project ID for which OAuth is configured."
        - "name": "redirect_url"
          "in": "query"
          "schema":
            "type": "string"
            "format": "uri"
          "description": "The URL to redirect to after authentication. Must be pre-registered in project settings."
          "example": "https://client.app/auth/callback"
      "responses":
        "200":
          "description": "Success (OAuth flow initiated; in most cases the server responds with 302 redirect)."
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "redirectUrl":
                    "type": "string"
                    "format": "uri"
                    "description": "OAuth provider authorization URL (when not using 302)"
        "302":
          "description": "Redirect to OAuth provider's consent screen"
          "headers":
            "Location":
              "schema":
                "type": "string"
                "format": "uri"
              "description": "OAuth provider authorization URL"
        "400":
          "description": "OAuth provider not configured or not enabled for this project"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "error":
                    "type": "string"
                    "example": "google authentication not enabled for this project"
              "example":
                "error": "google authentication not enabled for this project"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "Project not found (exact backend message)."
          "$ref": "#/components/responses/ProjectNotFound"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
  "/api/auth/oauth/callback/{provider}":
    "get":
      "tags":
        - "auth"
      "summary": "OAuth callback handler"
      "description": "OAuth provider redirects the user here after consent. The server exchanges the code for tokens,

        creates or finds the user, and redirects to the client with token, refreshToken, and expiresIn in query params.\n"
      "operationId": "auth.oauthCallback"
      "x-display-name": "OAuth Callback"
      "x-sdk-method": "oauthCallback"
      "security": []
      "parameters":
        - "name": "provider"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "OAuth provider identifier (e.g. google, github)."
      "responses":
        "200":
          "description": "Success (in most cases the server responds with 302 redirect to client with token)."
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "token":
                    "type": "string"
                  "user":
                    "$ref": "#/components/schemas/User"
        "302":
          "description": "Redirect with token, refreshToken, and expiresIn"
          "headers":
            "Location":
              "schema":
                "type": "string"
              "description": "URL with token, refreshToken, expiresIn query params"
              "example": "https://client.app/callback?token=...&refreshToken=...&expiresIn=1800"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
  "/api/auth/oauth/providers/available":
    "get":
      "tags":
        - "auth"
      "summary": "Get all available OAuth providers"
      "security": []
      "description": "Returns a list of all supported OAuth providers with their configuration details"
      "operationId": "auth.getOAuthProviders"
      "responses":
        "200":
          "description": "List of available OAuth providers"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "providers":
                    "type": "array"
                    "items":
                      "type": "object"
                      "properties":
                        "name":
                          "type": "string"
                          "example": "google"
                        "displayName":
                          "type": "string"
                          "example": "Google"
                        "strategy":
                          "type": "string"
                          "example": "google"
                        "defaultScope":
                          "type": "array"
                          "items":
                            "type": "string"
                          "example":
                            - "profile"
                            - "email"
                        "callbackUrl":
                          "type": "string"
                          "example": "/api/auth/oauth/callback/google"
                        "requiredFields":
                          "type": "array"
                          "items":
                            "type": "string"
                          "example":
                            - "clientId"
                            - "clientSecret"
                  "total":
                    "type": "integer"
                    "example": 29
              "example":
                "providers":
                  - "name": "google"
                    "displayName": "Google"
                    "strategy": "google"
                    "defaultScope":
                      - "profile"
                      - "email"
                    "callbackUrl": "/api/auth/oauth/callback/google"
                    "requiredFields":
                      - "clientId"
                      - "clientSecret"
                  - "name": "github"
                    "displayName": "GitHub"
                    "strategy": "github"
                    "defaultScope":
                      - "user:email"
                    "callbackUrl": "/api/auth/oauth/callback/github"
                    "requiredFields":
                      - "clientId"
                      - "clientSecret"
                "total": 29
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Get all available OAuth providers"
      "x-sdk-method": "getOAuthProviders"
  "/api/auth/magic-link/send":
    "post":
      "tags":
        - "auth"
      "summary": "Send magic link"
      "description": "Sends a one-time magic link to the given email for the project. The user clicks the link

        and is authenticated without a password. Use verify endpoint with the token from the link.

        Public endpoint; rate limited.\n"
      "operationId": "auth.sendMagicLink"
      "security": []
      "requestBody":
        "required": true
        "description": "Email, projectId, and optional redirect URL for the magic link."
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/MagicLinkRequest"
            "example":
              "email": "user@example.com"
              "projectId": "685ad30be129932fbb7a1047"
              "redirectUrl": "https://app.example.com/auth/callback"
      "responses":
        "200":
          "description": "Magic link sent"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "Magic link sent successfully"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Send magic link"
      "x-sdk-method": "sendMagicLink"
  "/api/auth/magic-link/verify":
    "post":
      "tags":
        - "auth"
      "summary": "Verify magic link"
      "description": "Exchanges the magic link token (from the link sent by send) for a session. Returns token and user

        on success. Token is short-lived and single-use.\n"
      "operationId": "auth.verifyMagicLink"
      "security": []
      "requestBody":
        "required": true
        "description": "The token from the magic link URL."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "token"
              "properties":
                "token":
                  "type": "string"
                  "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJwcm9qZWN0SWQiOiI2ODVhZDMwYmUxMjk5MzJmYmI3YTEwNDciLCJpYXQiOjE3NTA3ODA4OTgsImV4cCI6MTc1MDc4NDQ5OH0.example"
            "example":
              "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJwcm9qZWN0SWQiOiI2ODVhZDMwYmUxMjk5MzJmYmI3YTEwNDciLCJpYXQiOjE3NTA3ODA4OTgsImV4cCI6MTc1MDc4NDQ5OH0.example"
      "responses":
        "200":
          "description": "Magic link verified"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/AuthResponse"
              "example":
                "message": "Magic link verified successfully"
                "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                "expiresIn": 1800
                "user":
                  "_id": "685acbe0e129932fbb7a0fc2"
                  "email": "user@example.com"
                  "firstName": "John"
                  "lastName": "Doe"
                  "role": "user"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Verify magic link"
      "x-sdk-method": "verifyMagicLink"
  "/api/auth/otp/send":
    "post":
      "tags":
        - "auth"
      "summary": "Send OTP code"
      "description": "Sends a one-time code via SMS or email for the given project. Use verify endpoint to exchange

        the code for a session. Public endpoint; rate limited.\n"
      "operationId": "auth.sendOtp"
      "security": []
      "requestBody":
        "required": true
        "description": "Project ID, delivery method (sms/email), and phone or email."
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/OTPSendRequest"
            "example":
              "email": "user@example.com"
              "projectId": "685ad30be129932fbb7a1047"
              "method": "email"
      "responses":
        "200":
          "description": "OTP sent"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "OTP code sent successfully"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Send OTP code"
      "x-sdk-method": "sendOtp"
  "/api/auth/otp/verify":
    "post":
      "tags":
        - "auth"
      "summary": "Verify OTP code"
      "description": "Verifies the OTP code and returns a session token and user. Public endpoint.\n"
      "operationId": "auth.verifyOtp"
      "security": []
      "requestBody":
        "required": true
        "description": "Identifier (phone/email), OTP code, and project ID."
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/OTPVerifyRequest"
            "example":
              "identifier": "user@example.com"
              "otp": "123456"
              "projectId": "685ad30be129932fbb7a1047"
      "responses":
        "200":
          "description": "OTP verified"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/AuthResponse"
              "example":
                "message": "OTP verified successfully"
                "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                "expiresIn": 1800
                "user":
                  "_id": "685acbe0e129932fbb7a0fc2"
                  "email": "user@example.com"
                  "firstName": "John"
                  "lastName": "Doe"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Verify OTP code"
      "x-sdk-method": "verifyOtp"
  "/api/auth/anonymous":
    "post":
      "tags":
        - "auth"
      "summary": "Create anonymous session"
      "operationId": "auth.createAnonymous"
      "security": []
      "description": "Create an anonymous user session for guest access. Users can later convert to full accounts."
      "requestBody":
        "required": false
        "description": "Optional projectId and deviceId for the anonymous session."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "properties":
                "projectId":
                  "type": "string"
                  "description": "Project ID for the anonymous session"
                  "example": "685ad30be129932fbb7a1047"
                "deviceId":
                  "type": "string"
                  "description": "Optional device identifier"
                  "example": "device-uuid-123"
            "example":
              "projectId": "685ad30be129932fbb7a1047"
              "deviceId": "device-uuid-123"
      "responses":
        "200":
          "description": "Anonymous session created"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "message":
                    "type": "string"
                    "example": "Anonymous session created"
                  "token":
                    "type": "string"
                    "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                  "refreshToken":
                    "type": "string"
                    "description": "Refresh token for POST /api/auth/refresh"
                  "expiresIn":
                    "type": "integer"
                    "example": 86400
                  "user":
                    "type": "object"
                    "properties":
                      "id":
                        "type": "string"
                      "email":
                        "type": "string"
                      "firstName":
                        "type": "string"
                      "lastName":
                        "type": "string"
                      "role":
                        "type": "string"
                      "isAnonymous":
                        "type": "boolean"
                        "example": true
              "example":
                "message": "Anonymous session created"
                "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                "expiresIn": 86400
                "user":
                  "id": "685acbe0e129932fbb7a0fc2"
                  "email": "anonymous_abc123@anonymous.local"
                  "firstName": "Anonymous"
                  "lastName": "User"
                  "role": "viewer"
                  "isAnonymous": true
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "Project not found (exact backend message)."
          "$ref": "#/components/responses/ProjectNotFound"
      "x-display-name": "Create anonymous session"
      "x-sdk-method": "createAnonymous"
  "/api/auth/anonymous/convert":
    "post":
      "tags":
        - "auth"
      "summary": "Convert anonymous account to full account"
      "operationId": "auth.convertAnonymous"
      "description": "Convert an anonymous user session to a full authenticated account. Preserves user data. Requires JWT Bearer token (BearerToken). API keys are not supported for this endpoint.\n"
      "security":
        - "BearerToken": []
      "requestBody":
        "required": true
        "description": "Email, password, and optional firstName, lastName for the new full account."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "email"
                - "password"
              "properties":
                "email":
                  "type": "string"
                  "format": "email"
                  "example": "user@example.com"
                "password":
                  "type": "string"
                  "format": "password"
                  "example": "SecurePassword123!"
                "firstName":
                  "type": "string"
                  "example": "John"
                "lastName":
                  "type": "string"
                  "example": "Doe"
            "example":
              "email": "user@example.com"
              "password": "SecurePassword123!"
              "firstName": "John"
              "lastName": "Doe"
      "responses":
        "200":
          "description": "Account converted successfully"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "message":
                    "type": "string"
                    "example": "Account created successfully"
                  "token":
                    "type": "string"
                    "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                  "refreshToken":
                    "type": "string"
                  "expiresIn":
                    "type": "integer"
                    "example": 1800
                  "user":
                    "$ref": "#/components/schemas/User"
              "example":
                "message": "Account created successfully"
                "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                "expiresIn": 1800
                "user":
                  "_id": "685acbe0e129932fbb7a0fc2"
                  "email": "user@example.com"
                  "firstName": "John"
                  "lastName": "Doe"
                  "role": "developer"
                  "emailVerified": false
                  "isAnonymous": false
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
      "x-display-name": "Convert anonymous account to full account"
      "x-sdk-method": "convertAnonymous"
  "/api/auth/verify-email":
    "post":
      "tags":
        - "auth"
      "summary": "Verify email address (no auth)"
      "operationId": "auth.verifyEmail"
      "security": []
      "description": |
        Verifies the user's email using the token from the link sent at signup.
        Use for project-scoped or general signup flows (unauthenticated).
        Same behavior as POST /api/users/verify-email.
      "requestBody":
        "required": true
        "description": "Verification token from the email link; optional `projectId` for project-scoped signup."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "token"
              "properties":
                "token":
                  "type": "string"
                  "description": "Verification token from the email link"
                "projectId":
                  "type": "string"
                  "description": "Optional; for project signup context (redirect hint)"
      "responses":
        "200":
          "description": "Email verified"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "Email verified successfully"
        "400":
          "description": "Invalid or missing token"
          "$ref": "#/components/responses/BadRequest"
        "500":
          "description": "Unexpected server error while verifying the email token."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Verify email address (no auth)"
      "x-sdk-method": "verifyEmail"
  "/api/auth/resend-verification":
    "post":
      "tags":
        - "auth"
      "summary": "Resend verification email (no auth)"
      "operationId": "auth.resendVerification"
      "security": []
      "description": |
        Sends a new verification email to the given email (and optional project).
        For unauthenticated users who have not verified yet. Rate limited (e.g. 3 per 15 min per IP).
      "requestBody":
        "required": true
        "description": "Email address to resend to; optional `projectId` for project-scoped verification links."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "email"
              "properties":
                "email":
                  "type": "string"
                  "format": "email"
                "projectId":
                  "type": "string"
                  "description": "Optional; for project-scoped signup (sends link with project context)"
      "responses":
        "200":
          "description": "Verification email sent (or generic message to prevent enumeration)"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "If an account exists and is unverified, a verification email has been sent"
        "400":
          "description": "Email required"
          "$ref": "#/components/responses/BadRequest"
        "429":
          "description": "Too many requests (rate limit)"
          "$ref": "#/components/responses/TooManyRequests"
        "500":
          "description": "Unexpected server error while sending the verification email."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Resend verification email (no auth)"
      "x-sdk-method": "resendVerification"
  "/api/users/me":
    "get":
      "tags":
        - "users"
      "summary": "Get current user profile"
      "operationId": "users.get"
      "description": "Get the current authenticated user's profile.

        Accepts JWT Bearer token (BearerToken).\n"
      "security":
        - "BearerToken": []
      "responses":
        "200":
          "description": "User profile"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "user":
                    "$ref": "#/components/schemas/User"
              "example":
                "user":
                  "_id": "685acbe0e129932fbb7a0fc2"
                  "email": "john.doe@mudbase.dev"
                  "firstName": "John"
                  "lastName": "Doe"
                  "role": "owner"
                  "emailVerified": true
                  "twoFactorEnabled": false
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Get current user profile"
      "x-sdk-method": "get"
  "/api/users/update":
    "patch":
      "tags":
        - "users"
      "summary": "Update user profile"
      "operationId": "users.update"
      "description": "Update the current user's profile. Requires JWT Bearer token (BearerToken). API keys are not supported for this endpoint.\n"
      "security":
        - "BearerToken": []
      "requestBody":
        "required": true
        "description": "Profile fields to update (firstName, lastName, avatar)."
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/UpdateUserRequest"
            "example":
              "firstName": "John"
              "lastName": "Doe"
              "avatar": "https://example.com/avatar.jpg"
      "responses":
        "200":
          "description": "Profile updated"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "message":
                    "type": "string"
                  "user":
                    "$ref": "#/components/schemas/User"
              "example":
                "message": "Profile updated successfully"
                "user":
                  "_id": "685acbe0e129932fbb7a0fc2"
                  "email": "john.doe@mudbase.dev"
                  "firstName": "John"
                  "lastName": "Doe"
                  "avatar": "https://example.com/avatar.jpg"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Update user profile"
      "x-sdk-method": "update"
  "/api/users/password":
    "patch":
      "tags":
        - "users"
      "summary": "Change password"
      "operationId": "users.changePassword"
      "description": "Change the current user's password. Accepts JWT Bearer token (BearerToken). API keys are not supported for this endpoint.\n"
      "security":
        - "BearerToken": []
      "requestBody":
        "required": true
        "description": "Current password and new password."
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/ChangePasswordRequest"
            "example":
              "currentPassword": "OldPassword123!"
              "newPassword": "NewSecurePass123!"
      "responses":
        "200":
          "description": "Password changed"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "Password changed successfully"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Change password"
      "x-sdk-method": "changePassword"
  "/api/users/2fa/setup":
    "post":
      "tags":
        - "users"
      "summary": "Initiate two-factor authentication setup (secret, QR code, backup codes)"
      "operationId": "users.setup2fa"
      "description": "Initiates two-factor authentication setup for the current user. Returns a secret, QR code, and manual entry key

        for the user to add to an authenticator app. Requires JWT Bearer token (BearerToken). API keys are not supported.\n"
      "security":
        - "BearerToken": []
      "responses":
        "200":
          "description": "2FA setup data"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/TwoFASetupResponse"
              "example":
                "secret": "JBSWY3DPEHPK3PXP"
                "qrCode": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
                "backupCodes":
                  - "12345678"
                  - "87654321"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Initiate two-factor authentication setup (secret, QR code, backup codes)"
      "x-sdk-method": "setup2fa"
  "/api/users/2fa/verify":
    "post":
      "tags":
        - "users"
      "summary": "Verify and enable 2FA"
      "operationId": "users.verify2fa"
      "description": "Verify and enable two-factor authentication for the current user. Accepts JWT Bearer token (BearerToken). API keys are not supported for this endpoint.\n"
      "security":
        - "BearerToken": []
      "requestBody":
        "required": true
        "description": "One-time code from the authenticator app."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "token"
              "properties":
                "token":
                  "type": "string"
                  "example": "123456"
            "example":
              "token": "123456"
      "responses":
        "200":
          "description": "2FA enabled"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "2FA enabled successfully"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Verify and enable 2FA"
      "x-sdk-method": "verify2fa"
  "/api/users/2fa/disable":
    "post":
      "tags":
        - "users"
      "summary": "Disable 2FA"
      "operationId": "users.disable2fa"
      "description": "Disable two-factor authentication for the current user. Requires JWT Bearer token (BearerToken). API keys are not supported for this endpoint.\n"
      "security":
        - "BearerToken": []
      "requestBody":
        "required": true
        "description": "Current password and one-time code to confirm disable."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "password"
                - "token"
              "properties":
                "password":
                  "type": "string"
                  "example": "SecurePass123!"
                "token":
                  "type": "string"
                  "example": "123456"
            "example":
              "password": "SecurePass123!"
              "token": "123456"
      "responses":
        "200":
          "description": "2FA disabled"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "2FA disabled successfully"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Disable 2FA"
      "x-sdk-method": "disable2fa"
  "/api/users/verify-email":
    "post":
      "tags":
        - "users"
      "summary": "Verify email address (with optional project context)"
      "operationId": "users.verifyEmail"
      "description": "Verifies the user's email using the token from the link sent at signup.

        Supports general and project-scoped signups; the token comes from the verification link

        (e.g. `verify-email?token=...` or `verify-email?token=...&project=...`).\n"
      "security": []
      "requestBody":
        "required": true
        "description": "Verification token from the email link; optional projectId for project context."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "token"
              "properties":
                "token":
                  "type": "string"
                  "description": "Verification token from the email link"
                "projectId":
                  "type": "string"
                  "description": "Optional; for project signup context (redirect hint)"
            "example":
              "token": "a1b2c3d4..."
      "responses":
        "200":
          "description": "Email verified"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "Email verified successfully"
        "400":
          "description": "Invalid verification token"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Verify email address"
      "x-sdk-method": "verifyEmail"
  "/api/users/resend-verification":
    "post":
      "tags":
        - "users"
      "summary": "Resend verification email"
      "operationId": "users.resendVerification"
      "description": "Sends a new verification email to the authenticated user. Rate limited

        (e.g. 3 requests per 15 minutes per user). For app users the

        link includes project context.\n"
      "security":
        - "BearerToken": []
      "responses":
        "200":
          "description": "Verification email sent"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "Verification email sent successfully"
        "400":
          "description": "Email already verified"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "429":
          "description": "Too many requests (rate limit)"
      "x-display-name": "Resend verification email"
      "x-sdk-method": "resendVerification"
  "/api/users/me/export":
    "get":
      "tags":
        - "users"
      "summary": "Export user data (GDPR Article 15)"
      "operationId": "users.exportData"
      "description": "Export all user data in JSON format for GDPR data portability compliance. Accepts JWT Bearer token (BearerToken). API keys are not supported for this endpoint.\n"
      "security":
        - "BearerToken": []
      "responses":
        "200":
          "description": "User data export"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "exportedAt":
                    "type": "string"
                    "format": "date-time"
                  "user":
                    "$ref": "#/components/schemas/User"
                  "projects":
                    "type": "array"
                    "items":
                      "type": "object"
                      "additionalProperties": true
                  "wallets":
                    "type": "array"
                    "items":
                      "type": "object"
                      "additionalProperties": true
                  "transactions":
                    "type": "array"
                    "items":
                      "type": "object"
                      "additionalProperties": true
                  "files":
                    "type": "array"
                    "items":
                      "type": "object"
                      "additionalProperties": true
                  "integrations":
                    "type": "array"
                    "items":
                      "type": "object"
                      "additionalProperties": true
                  "apiKeys":
                    "type": "array"
                    "items":
                      "type": "object"
                      "additionalProperties": true
              "example":
                "exportedAt": "2024-12-16T10:00:00Z"
                "user":
                  "_id": "685acbe0e129932fbb7a0fc2"
                  "email": "user@example.com"
                  "firstName": "John"
                  "lastName": "Doe"
                "projects": []
                "wallets": []
                "transactions": []
                "files": []
                "integrations": []
                "apiKeys": []
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Export user data (GDPR Article 15)"
      "x-sdk-method": "exportData"
  "/api/users/me/erase":
    "post":
      "tags":
        - "users"
      "summary": "Delete user data (GDPR Article 17)"
      "operationId": "users.eraseData"
      "description": "Request account erasure (right to be forgotten). Anonymizes PII and deactivates account with 7-day grace period. Accepts JWT Bearer token (BearerToken). API keys are not supported for this endpoint.\n"
      "security":
        - "BearerToken": []
      "requestBody":
        "required": true
        "description": "Confirmation string (DELETE_MY_ACCOUNT) and optional reason for erasure."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "confirmation"
              "properties":
                "confirmation":
                  "type": "string"
                  "enum":
                    - "DELETE_MY_ACCOUNT"
                  "example": "DELETE_MY_ACCOUNT"
                "reason":
                  "type": "string"
                  "description": "Optional reason for account deletion"
                  "example": "No longer need the service"
            "example":
              "confirmation": "DELETE_MY_ACCOUNT"
              "reason": "No longer need the service"
      "responses":
        "200":
          "description": "Account erasure initiated"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "message":
                    "type": "string"
                    "example": "Account erasure initiated"
                  "details":
                    "type": "object"
                    "properties":
                      "dataAnonymized":
                        "type": "boolean"
                        "example": true
                      "apiKeysDeactivated":
                        "type": "boolean"
                        "example": true
                      "sessionsDeleted":
                        "type": "boolean"
                        "example": true
                      "accountDisabled":
                        "type": "boolean"
                        "example": true
                      "scheduledForDeletion":
                        "type": "string"
                        "format": "date-time"
                        "example": "2024-12-23T10:00:00Z"
              "example":
                "message": "Account erasure initiated"
                "details":
                  "dataAnonymized": true
                  "apiKeysDeactivated": true
                  "sessionsDeleted": true
                  "accountDisabled": true
                  "scheduledForDeletion": "2024-12-23T10:00:00Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
      "x-display-name": "Delete user data (GDPR Article 17)"
      "x-sdk-method": "eraseData"
  "/api/users/me/oauth-providers":
    "get":
      "tags":
        - "users"
      "summary": "List linked OAuth providers"
      "operationId": "users.listOAuthProviders"
      "description": "Get all OAuth providers linked to the current user's account. Accepts JWT Bearer token (BearerToken). API keys are not supported for this endpoint.\n"
      "security":
        - "BearerToken": []
      "responses":
        "200":
          "description": "List of linked OAuth providers"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "providers":
                    "type": "array"
                    "items":
                      "type": "object"
                      "properties":
                        "provider":
                          "type": "string"
                          "example": "google"
                        "providerId":
                          "type": "string"
                          "example": "google-user-id-123"
                        "email":
                          "type": "string"
                          "example": "user@gmail.com"
                        "linkedAt":
                          "type": "string"
                          "format": "date-time"
              "example":
                "providers":
                  - "provider": "google"
                    "providerId": "google-user-id-123"
                    "email": "user@gmail.com"
                    "linkedAt": "2024-12-01T10:00:00Z"
                  - "provider": "github"
                    "providerId": "github-user-id-456"
                    "username": "johndoe"
                    "linkedAt": "2024-12-15T14:30:00Z"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
      "x-display-name": "List linked OAuth providers"
      "x-sdk-method": "listOAuthProviders"
  "/api/users/me/oauth-providers/link/{provider}":
    "get":
      "tags":
        - "users"
      "summary": "Link OAuth provider to account"
      "operationId": "users.linkOAuthProvider"
      "description": "Initiate OAuth flow to link a new provider to the current account. Accepts JWT Bearer token (BearerToken). API keys are not supported for this endpoint.\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "provider"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "enum":
              - "google"
              - "github"
              - "facebook"
              - "microsoft"
              - "apple"
              - "twitter"
              - "discord"
              - "linkedin"
          "description": "OAuth provider to link (e.g. google, github)."
          "example": "google"
        - "name": "projectId"
          "in": "query"
          "schema":
            "type": "string"
          "description": "Project ID for the OAuth link context."
          "example": "685ad30be129932fbb7a1047"
      "responses":
        "200":
          "description": "Success (OAuth link flow initiated; in most cases the server responds with 302 redirect to provider)."
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "redirectUrl":
                    "type": "string"
                    "format": "uri"
        "302":
          "description": "Redirect to OAuth provider"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
      "x-display-name": "Link OAuth provider to account"
      "x-sdk-method": "linkOAuthProvider"
  "/api/users/me/oauth-providers/{provider}":
    "delete":
      "tags":
        - "users"
      "summary": "Unlink OAuth provider"
      "operationId": "users.unlinkOAuthProvider"
      "description": "Remove an OAuth provider from the current account. Cannot unlink if it's the only authentication method. Requires JWT Bearer token (BearerToken). API keys are not supported for this endpoint.\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "provider"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "enum":
              - "google"
              - "github"
              - "facebook"
              - "microsoft"
              - "apple"
              - "twitter"
              - "discord"
              - "linkedin"
          "description": "OAuth provider to unlink (e.g. google, github)."
          "example": "github"
      "responses":
        "200":
          "description": "Provider unlinked successfully"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "message":
                    "type": "string"
                    "example": "OAuth provider unlinked successfully"
                  "provider":
                    "type": "string"
                    "example": "github"
              "example":
                "message": "OAuth provider unlinked successfully"
                "provider": "github"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
      "x-display-name": "Unlink OAuth provider"
      "x-sdk-method": "unlinkOAuthProvider"
  "/api/projects/{projectId}/role-elevation/request":
    "post":
      "tags":
        - "roleElevation"
      "summary": "Request role elevation"
      "description": "User requests to upgrade to a specific role. May require payment, KYC, or admin approval based on role configuration."
      "operationId": "roleElevation.request"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
      "requestBody":
        "required": true
        "description": "Role slug to request elevation to (e.g. a higher-privilege role you configured)."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "roleSlug"
              "properties":
                "roleSlug":
                  "type": "string"
                  "example": "seller"
            "example":
              "roleSlug": "seller"
      "responses":
        "200":
          "description": "Role elevation request created or auto-approved"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "message":
                    "type": "string"
                  "requestId":
                    "type": "string"
                  "workflow":
                    "type": "string"
                    "enum":
                      - "auto_approved"
                      - "pending_admin_approval"
                      - "pending_requirements"
                      - "manual_approval"
                  "status":
                    "type": "string"
                    "enum":
                      - "approved"
                      - "pending"
                  "nextSteps":
                    "type": "array"
                    "items":
                      "type": "string"
                  "estimatedApprovalTime":
                    "type": "string"
              "example":
                "message": "Request submitted"
                "requestId": "req_abc123"
                "workflow": "pending_admin_approval"
                "status": "pending"
        "400":
          "description": "Invalid request or already has role"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Cannot request role with higher hierarchy"
        "404":
          "description": "Role not found (exact backend message)."
          "$ref": "#/components/responses/RoleNotFound"
      "x-display-name": "Request role elevation"
      "x-sdk-method": "request"
  "/api/projects/{projectId}/role-elevation/status":
    "get":
      "tags":
        - "roleElevation"
      "summary": "Get role elevation status"
      "description": "Get status of pending role elevation requests for current user"
      "operationId": "roleElevation.getStatus"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "roleSlug"
          "in": "query"
          "schema":
            "type": "string"
          "description": "Optional filter by role slug."
      "responses":
        "200":
          "description": "List of role elevation requests"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "requests":
                    "type": "array"
                    "items":
                      "type": "object"
              "example":
                "requests": []
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Get role elevation status"
      "x-sdk-method": "getStatus"
  "/api/projects/{projectId}/role-elevation/documents":
    "post":
      "tags":
        - "roleElevation"
      "summary": "Upload verification documents"
      "description": "Upload KYC/verification documents for role elevation"
      "operationId": "roleElevation.uploadDocuments"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
      "requestBody":
        "required": true
        "description": "Role slug and array of document objects (type, url)."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "roleSlug"
                - "documents"
              "properties":
                "roleSlug":
                  "type": "string"
                "documents":
                  "type": "array"
                  "items":
                    "type": "object"
                    "properties":
                      "type":
                        "type": "string"
                      "url":
                        "type": "string"
            "example":
              "roleSlug": "seller"
              "documents":
                - "type": "id"
                  "url": "https://example.com/id.pdf"
      "responses":
        "200":
          "description": "Documents uploaded successfully"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Upload verification documents"
      "x-sdk-method": "uploadDocuments"

  "/api/projects/{projectId}/permissions-matrix":
    "get":
      "tags":
        - "multiRole"
      "summary": "Get permissions matrix (collections + featurePermissions)"
      "description": "Per-collection role actions and per-role `featurePermissions` for app-role gates."
      "operationId": "multiRole.getPermissionsMatrix"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "description": "Project ID whose multi-role matrix is returned."
          "schema":
            "type": "string"
            "example": "685ad30be129932fbb7a1047"
      "responses":
        "200":
          "description": "Matrix payload"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
              "example":
                "success": true
                "data":
                  "collections": []
                  "roles": []
                  "features":
                    - "slug": "customer"
                      "featurePermissions":
                        "messaging":
                          "email": true
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions to read the matrix."
          "$ref": "#/components/responses/Forbidden"
  "/api/projects/{projectId}/multi-role":
    "get":
      "tags":
        - "multiRole"
      "summary": "Get multi-role feature configuration"
      "description": "Returns project app roles (default one editable `customer` starter until you add more) and settings."
      "operationId": "multiRole.getConfig"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "685ad30be129932fbb7a1047"
          "description": "Project ID."
      "responses":
        "200":
          "description": "Multi-role configuration"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
                    "properties":
                      "isEnabled":
                        "type": "boolean"
                      "defaultRole":
                        "type": "string"
                      "settings":
                        "type": "object"
                      "roles":
                        "type": "array"
                        "items":
                          "type": "object"
              "example":
                "success": true
                "data":
                  "isEnabled": true
                  "defaultRole": "customer"
                  "settings":
                    "allowMultipleRoles": false
                    "requireRoleSelection": false
                    "autoAssignDefault": true
                  "roles":
                    - "slug": "customer"
                      "name": "Customer"
                      "description": "Default app user role. Edit name/slug and assign create/read/update/delete per collection after you add schemas."
                      "isEnabled": true
                      "isCustom": true
                      "signupEndpoint": "customer"
                      "requiresApproval": false
                      "requiresPayment": false
                      "requiresKYC": false
                      "defaultPermissions": []
                      "collectionPermissions": []
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Get multi-role feature configuration"
      "x-sdk-method": "getConfig"
  "/api/projects/{projectId}/multi-role/settings":
    "patch":
      "tags":
        - "multiRole"
      "summary": "Update multi-role feature settings"
      "operationId": "multiRole.updateSettings"
      "description": "Update multi-role feature settings: enable/disable the feature, `defaultRole`, and `settings` (`allowMultipleRoles`, `requireRoleSelection`, `autoAssignDefault`, `dataOwnerField`). Does not edit role definitions — use `POST/PATCH .../multi-role/roles` (same body shape as add role).

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "685ad30be129932fbb7a1047"
          "description": "Project ID."
      "requestBody":
        "required": true
        "description": "Feature flags only — not per-role approval. Use `settings.allowMultipleRoles`, `requireRoleSelection`, `autoAssignDefault`, `dataOwnerField`."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "properties":
                "isEnabled":
                  "type": "boolean"
                  "example": true
                "defaultRole":
                  "type": "string"
                  "example": "customer"
                "settings":
                  "type": "object"
                  "description": "Feature toggles for signup behavior (not per-role approval flags)."
                  "properties":
                    "allowMultipleRoles":
                      "type": "boolean"
                      "description": "Whether an end user may hold multiple app roles."
                    "requireRoleSelection":
                      "type": "boolean"
                      "description": "If true, signup must pick a role; if false and `autoAssignDefault` is true, `defaultRole` is used when omitted."
                    "autoAssignDefault":
                      "type": "boolean"
                      "description": "When true, assigns `defaultRole` when the client does not specify a role at signup."
                    "dataOwnerField":
                      "type": "string"
                      "default": "createdBy"
                      "description": "Default document field for `dataScope: own` (e.g. `createdBy`, `userId`)."
            "example":
              "isEnabled": true
              "defaultRole": "customer"
              "settings":
                "allowMultipleRoles": false
                "requireRoleSelection": false
                "autoAssignDefault": true
                "dataOwnerField": "createdBy"
      "responses":
        "200":
          "description": "Settings updated"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "message":
                    "type": "string"
                  "data":
                    "type": "object"
                    "description": "Same shape as GET `/multi-role` — `isEnabled`, `defaultRole`, `settings`, and `roles` (no raw MultiRoleFeature document)."
              "example":
                "success": true
                "message": "Multi-role settings updated"
                "data":
                  "isEnabled": true
                  "defaultRole": "customer"
                  "settings":
                    "allowMultipleRoles": false
                    "requireRoleSelection": false
                    "autoAssignDefault": true
                    "dataOwnerField": "createdBy"
                  "roles":
                    - "slug": "customer"
                      "name": "Customer"
                      "description": "Default app user role. Edit name/slug and assign create/read/update/delete per collection after you add schemas."
                      "isEnabled": true
                      "isCustom": true
                      "signupEndpoint": "customer"
                      "requiresApproval": false
                      "requiresPayment": false
                      "requiresKYC": false
                      "defaultPermissions": []
                      "collectionPermissions": []
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Update multi-role feature settings"
      "x-sdk-method": "updateSettings"
  "/api/projects/{projectId}/multi-role/simulate-permissions":
    "post":
      "tags":
        - "multiRole"
      "summary": "Simulate app-role feature permission for a path"
      "description": "Given role slug and either `operationId` or HTTP method + pathname, returns whether `featurePermissions` would allow gated routes. Unmapped paths or unknown operation IDs return allowed with `no_feature_gate_for_path` or `no_feature_gate_for_operation_id`."
      "operationId": "multiRole.simulateAppPermissions"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "description": "Project ID used to resolve role configuration."
          "schema":
            "type": "string"
      "requestBody":
        "required": true
        "description": "Role slug plus either OpenAPI `operationId` or HTTP `method` and `pathname` to evaluate."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required": ["role"]
              "properties":
                "role":
                  "type": "string"
                "operationId":
                  "type": "string"
                  "description": "OpenAPI operationId (e.g. sendEmail). Optional if method + pathname are sent."
                "method":
                  "type": "string"
                "pathname":
                  "type": "string"
                  "description": "Full API path, e.g. /api/messaging/projects/{projectId}/messaging/email"
                "path":
                  "type": "string"
                  "description": "Alias for pathname"
              "oneOf":
                - "required": ["operationId"]
                - "required": ["method", "pathname"]
            "examples":
              "byPath":
                "summary": "Method + pathname"
                "value":
                  "role": "customer"
                  "method": "POST"
                  "pathname": "/api/messaging/projects/685ad30be129932fbb7a1047/messaging/email"
              "byOperationId":
                "summary": "OpenAPI operationId"
                "value":
                  "role": "customer"
                  "operationId": "sendEmail"
      "responses":
        "200":
          "description": "Simulation result"
          "content":
            "application/json":
              "schema":
                "type": "object"
              "examples":
                "allowed":
                  "value":
                    "success": true
                    "allowed": true
                    "reason": "allowed"
                    "evaluated":
                      "role": "customer"
                      "resource": "messaging"
                      "action": "send_email"
                "denied":
                  "value":
                    "success": true
                    "allowed": false
                    "reason": "feature_not_allowed"
                    "evaluated":
                      "role": "viewer"
                      "resource": "messaging"
                      "action": "send_email"
        "400":
          "description": "Missing role, invalid body, or invalid method/pathname combination."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions to run the simulation."
          "$ref": "#/components/responses/Forbidden"
  "/api/projects/{projectId}/multi-role/roles/{roleSlug}/apply-preset":
    "post":
      "tags":
        - "multiRole"
      "summary": "Apply Admin / User / Viewer feature permission preset"
      "description": "Sets `featurePermissions` from preset `admin`, `user`, or `viewer`."
      "operationId": "multiRole.applyRoleFeaturePreset"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "description": "Project ID."
          "schema":
            "type": "string"
        - "name": "roleSlug"
          "in": "path"
          "required": true
          "description": "Role slug to apply the preset to (e.g. `customer`)."
          "schema":
            "type": "string"
      "requestBody":
        "required": true
        "description": "JSON body with `preset` set to `admin`, `user`, or `viewer`."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required": ["preset"]
              "properties":
                "preset":
                  "type": "string"
                  "enum": ["admin", "user", "viewer"]
      "responses":
        "200":
          "description": "Preset applied"
        "400":
          "description": "Invalid preset or malformed body."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions to change role presets."
          "$ref": "#/components/responses/Forbidden"
  "/api/projects/{projectId}/multi-role/roles/{roleSlug}/toggle":
    "patch":
      "tags":
        - "multiRole"
      "summary": "Toggle role on/off"
      "description": "Enable or disable a role for the project. When disabled, the role is no longer available for signup or assignment."
      "operationId": "multiRole.toggleRole"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "685ad30be129932fbb7a1047"
          "description": "Project ID."
        - "name": "roleSlug"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "customer"
          "description": "Role slug to toggle (e.g. starter `customer` or a role you added)."
      "requestBody":
        "required": true
        "description": "Whether the role is enabled (true) or disabled (false)."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "isEnabled"
              "properties":
                "isEnabled":
                  "type": "boolean"
                  "example": true
            "example":
              "isEnabled": true
      "responses":
        "200":
          "description": "Role toggled"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "message":
                    "type": "string"
                  "data":
                    "type": "object"
              "example":
                "success": true
                "message": "Role enabled"
                "data":
                  "slug": "customer"
                  "name": "Customer"
                  "description": "Default app user role. Edit name/slug and assign create/read/update/delete per collection after you add schemas."
                  "isEnabled": true
                  "isCustom": true
                  "signupEndpoint": "customer"
                  "requiresApproval": false
                  "requiresPayment": false
                  "requiresKYC": false
                  "defaultPermissions": []
                  "collectionPermissions": []
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Toggle role on/off"
      "x-sdk-method": "toggleRole"
  "/api/projects/{projectId}/multi-role/roles/{roleSlug}":
    "patch":
      "tags":
        - "multiRole"
      "summary": "Update role configuration"
      "description": "Update an app role — same fields as **Add custom role** (partial). `defaultPermissions` / `collectionPermissions` use the same normalization as on create. **featurePermissions:** see schema `AppRoleFeaturePermissions`."
      "operationId": "multiRole.updateRole"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "685ad30be129932fbb7a1047"
          "description": "Project ID."
        - "name": "roleSlug"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "customer"
          "description": "Role slug to update (e.g. starter `customer` or a role you added)."
      "requestBody":
        "required": true
        "description": "Same fields as **Add custom role** — send only fields you want to change. `defaultPermissions` / `collectionPermissions` are normalized the same way as on create."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "properties":
                "name":
                  "type": "string"
                  "example": "App user"
                "description":
                  "type": "string"
                  "example": "End users of the app"
                "signupEndpoint":
                  "type": "string"
                  "example": "customer"
                "requiresApproval":
                  "type": "boolean"
                  "example": false
                "requiresPayment":
                  "type": "boolean"
                  "example": false
                "requiresKYC":
                  "type": "boolean"
                  "example": false
                "defaultPermissions":
                  "type": "array"
                  "items":
                    "type": "object"
                "collectionPermissions":
                  "type": "object"
                  "description": "Per-collection CRUD map (same as POST add role)."
                  "additionalProperties":
                    "$ref": "#/components/schemas/AppRoleCollectionPermissionValue"
                "metadata":
                  "type": "object"
                "featurePermissions":
                  "$ref": "#/components/schemas/AppRoleFeaturePermissions"
            "example":
              "name": "App user"
              "description": "End users of the app"
              "signupEndpoint": "customer"
              "requiresApproval": false
              "requiresPayment": false
              "requiresKYC": false
              "collectionPermissions":
                "posts":
                  - "create"
                  - "read"
                  - "update"
                  - "delete"
              "featurePermissions":
                "messaging":
                  "email": true
                  "sms": false
                "integration":
                  "read": true
                  "execute": true
      "responses":
        "200":
          "description": "Role updated"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "message":
                    "type": "string"
                  "data":
                    "type": "object"
              "example":
                "success": true
                "message": "Role updated"
                "data":
                  "slug": "customer"
                  "name": "App user"
                  "description": "End users of the app"
                  "isEnabled": true
                  "isCustom": true
                  "signupEndpoint": "customer"
                  "requiresApproval": false
                  "requiresPayment": false
                  "requiresKYC": false
                  "defaultPermissions": []
                  "collectionPermissions": []
                  "featurePermissions":
                    "messaging":
                      "email": true
                      "sms": false
                    "integration":
                      "read": true
                      "execute": true
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Update role configuration"
      "x-sdk-method": "updateRole"
  "/api/projects/{projectId}/multi-role/roles":
    "post":
      "tags":
        - "multiRole"
      "summary": "Add custom role"
      "operationId": "multiRole.addRole"
      "description": "Add a custom role to a project with specific permissions and signup endpoint.
        Optional **featurePermissions** must align with app JWT gates — see schema `AppRoleFeaturePermissions`.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "685ad30be129932fbb7a1047"
          "description": "Project ID."
      "requestBody":
        "required": true
        "description": "Custom role definition. Use `collectionPermissions` to apply CRUD per collection slug (e.g. users/products/orders). `defaultPermissions` is optional for global/base permissions."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "slug"
                - "name"
                - "signupEndpoint"
              "properties":
                "slug":
                  "type": "string"
                  "example": "seller"
                "name":
                  "type": "string"
                  "example": "Seller"
                "description":
                  "type": "string"
                  "example": "Seller role with CRUD on seller-owned collections"
                "signupEndpoint":
                  "type": "string"
                  "example": "seller"
                "requiresApproval":
                  "type": "boolean"
                  "example": false
                "requiresPayment":
                  "type": "boolean"
                  "example": false
                "requiresKYC":
                  "type": "boolean"
                  "example": false
                "defaultPermissions":
                  "type": "array"
                  "description": "Optional global/base permissions. For collection-level CRUD use `collectionPermissions`."
                  "items":
                    "type": "object"
                    "properties":
                      "resource":
                        "type": "string"
                      "actions":
                        "type": "array"
                        "items":
                          "type": "string"
                "collectionPermissions":
                  "type": "object"
                  "description": "Per-collection CRUD map. Keys are collection slugs; values are action arrays or objects with `actions` + optional `conditions`."
                  "additionalProperties":
                    "$ref": "#/components/schemas/AppRoleCollectionPermissionValue"
                "metadata":
                  "type": "object"
                "featurePermissions":
                  "$ref": "#/components/schemas/AppRoleFeaturePermissions"
            "examples":
              "fullTesting":
                "summary": "Full payload for testing (all featurePermission buckets)"
                "description": "Use in Swagger / Postman; aligns with `AppRoleFeaturePermissions`."
                "value":
                  "slug": "seller"
                  "name": "Seller"
                  "description": "Seller role with CRUD on seller-owned collections"
                  "signupEndpoint": "seller"
                  "requiresApproval": false
                  "requiresPayment": false
                  "requiresKYC": false
                  "metadata":
                    "notes": "Example role for API integration tests"
                  "defaultPermissions":
                    - "resource": "project"
                      "actions":
                        - "read"
                    - "resource": "data"
                      "actions":
                        - "read"
                        - "create"
                  "collectionPermissions":
                    "listings":
                      - "create"
                      - "read"
                      - "update"
                      - "delete"
                    "orders":
                      "actions":
                        - "create"
                        - "read"
                      "conditions":
                        "status": "active"
                  "featurePermissions":
                    "messaging":
                      "email": true
                      "sms": true
                      "push": true
                      "history": true
                      "stats": true
                    "integration":
                      "read": true
                      "create": true
                      "update": true
                      "delete": false
                      "execute": true
                      "test": true
                      "export": true
                      "read_usage": true
                    "functions":
                      "create": true
                      "read": true
                      "update": true
                      "delete": false
                      "execute": true
                      "simulate": true
                    "data":
                      "create": true
                      "read": true
                      "update": true
                      "delete": false
                    "search":
                      "query": true
                      "suggestions": true
                      "read_analytics": true
                    "usage":
                      "read": true
                    "storage":
                      "read": true
                      "create": true
                      "update": true
                      "delete": false
                      "upload": true
                    "chat":
                      "read": true
                      "create": true
                      "update": true
                      "delete": false
                    "realtime":
                      "read_analytics": true
                      "read_active_users": true
                      "presence": true
                      "read_throughput": true
                      "read_history": true
                    "roleElevation":
                      "request": true
                      "status": true
                      "documents": true
                    "webhooks":
                      "config_read": true
                      "config_update": true
                      "test_transformation": true
      "responses":
        "201":
          "description": "Custom role added"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "message":
                    "type": "string"
                  "data":
                    "type": "object"
              "examples":
                "fullTesting":
                  "summary": "Success body matching fullTesting request (shape may vary after normalization)"
                  "value":
                    "success": true
                    "message": "Custom role added"
                    "data":
                      "slug": "seller"
                      "name": "Seller"
                      "description": "Seller role with CRUD on seller-owned collections"
                      "isEnabled": true
                      "isCustom": true
                      "signupEndpoint": "seller"
                      "requiresApproval": false
                      "requiresPayment": false
                      "requiresKYC": false
                      "defaultPermissions":
                        - "resource": "project"
                          "actions":
                            - "read"
                        - "resource": "data"
                          "actions":
                            - "read"
                            - "create"
                      "collectionPermissions":
                        - "collectionSlug": "listings"
                          "actions":
                            - "create"
                            - "read"
                            - "update"
                            - "delete"
                        - "collectionSlug": "orders"
                          "actions":
                            - "create"
                            - "read"
                          "conditions":
                            "status": "active"
                      "metadata": {}
                      "featurePermissions":
                        "messaging":
                          "email": true
                          "sms": true
                          "push": true
                          "history": true
                          "stats": true
                        "integration":
                          "read": true
                          "create": true
                          "update": true
                          "delete": false
                          "execute": true
                          "test": true
                          "export": true
                          "read_usage": true
                        "functions":
                          "create": true
                          "read": true
                          "update": true
                          "delete": false
                          "execute": true
                          "simulate": true
                        "data":
                          "create": true
                          "read": true
                          "update": true
                          "delete": false
                        "search":
                          "query": true
                          "suggestions": true
                          "read_analytics": true
                        "usage":
                          "read": true
                        "storage":
                          "read": true
                          "create": true
                          "update": true
                          "delete": false
                          "upload": true
                        "chat":
                          "read": true
                          "create": true
                          "update": true
                          "delete": false
                        "realtime":
                          "read_analytics": true
                          "read_active_users": true
                          "presence": true
                          "read_throughput": true
                          "read_history": true
                        "roleElevation":
                          "request": true
                          "status": true
                          "documents": true
                        "webhooks":
                          "config_read": true
                          "config_update": true
                          "test_transformation": true
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Add custom role"
      "x-sdk-method": "addRole"
  "/api/projects/{projectId}/multi-role/roles/{roleSlug}/collections/{collectionId}/permissions":
    "patch":
      "tags":
        - "multiRole"
      "summary": "Update collection permissions for a role"
      "operationId": "multiRole.updateCollectionPermissions"
      "description": "Update collection-specific permissions for a role in a project.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "685ad30be129932fbb7a1047"
          "description": "Project ID."
        - "name": "roleSlug"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "customer"
          "description": "Role slug (e.g. starter `customer` or a role you added)."
        - "name": "collectionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "696ba6e4f4a9422ac4be4f74"
          "description": "Collection ID to set permissions for."
      "requestBody":
        "required": true
        "description": "Allowed actions and optional conditions for the role on this collection."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "properties":
                "actions":
                  "type": "array"
                  "items":
                    "type": "string"
                    "enum":
                      - "create"
                      - "read"
                      - "update"
                      - "delete"
                  "example":
                    - "create"
                    - "read"
                    - "update"
                    - "delete"
                "conditions":
                  "type": "object"
                  "example":
                    "status": "active"
                "dataScope":
                  "type": "string"
                  "enum":
                    - "all"
                    - "own"
                  "description": "`all` = no automatic row-owner filter. `own` = only documents where the owner field (default `createdBy`) matches the authenticated app user."
                "ownerField":
                  "type": "string"
                  "description": "Optional per-assignment override for the document field used when `dataScope` is `own` (project default is `settings.dataOwnerField`, usually `createdBy`)."
            "example":
              "actions":
                - "create"
                - "read"
                - "update"
                - "delete"
              "conditions":
                "status": "active"
      "responses":
        "200":
          "description": "Collection permissions updated"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "message":
                    "type": "string"
                  "data":
                    "type": "object"
              "example":
                "success": true
                "message": "Collection permissions updated"
                "data":
                  "slug": "customer"
                  "name": "Customer"
                  "description": "Default app user role. Edit name/slug and assign create/read/update/delete per collection after you add schemas."
                  "isEnabled": true
                  "isCustom": true
                  "signupEndpoint": "customer"
                  "requiresApproval": false
                  "requiresPayment": false
                  "requiresKYC": false
                  "defaultPermissions": []
                  "collectionPermissions":
                    - "collectionId": "696ba6e4f4a9422ac4be4f74"
                      "collectionSlug": "posts"
                      "actions":
                        - "create"
                        - "read"
                        - "update"
                        - "delete"
                      "conditions":
                        "status": "active"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Update collection permissions for a role"
      "x-sdk-method": "updateCollectionPermissions"
  "/api/projects/{projectId}/multi-role/roles/available":
    "get":
      "tags":
        - "multiRole"
      "summary": "Get available roles for signup"
      "operationId": "multiRole.getAvailableRoles"
      "description": "Get all available roles for user signup in a project.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "685ad30be129932fbb7a1047"
          "description": "Project ID."
      "responses":
        "200":
          "description": "List of available roles"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "array"
                    "items":
                      "type": "object"
                      "properties":
                        "slug":
                          "type": "string"
                        "name":
                          "type": "string"
                        "description":
                          "type": "string"
                        "signupEndpoint":
                          "type": "string"
                        "requiresApproval":
                          "type": "boolean"
                        "requiresPayment":
                          "type": "boolean"
                        "requiresKYC":
                          "type": "boolean"
              "example":
                "success": true
                "data":
                  - "slug": "customer"
                    "name": "Customer"
                    "description": "Default app user role. Edit name/slug and assign create/read/update/delete per collection after you add schemas."
                    "signupEndpoint": "customer"
                    "requiresApproval": false
                    "requiresPayment": false
                    "requiresKYC": false
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Get available roles for signup"
      "x-sdk-method": "getAvailableRoles"
  "/api/auth/local/signup/{role}":
    "post":
      "tags":
        - "multiRole"
      "summary": "Register user with specific role (Local Auth)"
      "description": "Public endpoint for user registration with a specific role. The path segment must match a role's `signupEndpoint` (default starter is `customer`; add more roles via multi-role API).

        No authentication required - this is a public signup endpoint.\n"
      "operationId": "auth.registerWithRole"
      "security": []
      "parameters":
        - "name": "role"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "customer"
          "description": "Must match the role's `signupEndpoint` (default `customer`; other values for roles you add)."
      "requestBody":
        "required": true
        "description": "Registration payload (email, password, firstName, lastName, projectId)."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "email"
                - "password"
                - "firstName"
                - "lastName"
                - "projectId"
              "properties":
                "email":
                  "type": "string"
                  "format": "email"
                "password":
                  "type": "string"
                "firstName":
                  "type": "string"
                "lastName":
                  "type": "string"
                "projectId":
                  "type": "string"
            "example":
              "email": "customer@example.com"
              "password": "SecurePass123!"
              "firstName": "Jane"
              "lastName": "Doe"
              "projectId": "685ad30be129932fbb7a1047"
      "responses":
        "201":
          "description": "Registration successful"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "Role not found or not enabled"
      "x-display-name": "Register user with specific role (Local Auth)"
      "x-sdk-method": "registerWithRole"
  "/api/auth/oauth/signup/{role}/{provider}/{projectId}":
    "get":
      "tags":
        - "multiRole"
      "summary": "OAuth signup with specific role"
      "description": "Public endpoint that initiates OAuth signup flow with a specific role assigned during registration.

        The OAuth provider must be configured and enabled for the project first.

        The role must be available for signup in the project's multi-role configuration.

        After successful OAuth authentication, the user will be created with the specified role.

        No authentication required - this is a public signup endpoint.\n"
      "operationId": "auth.oauthSignupWithRole"
      "security": []
      "parameters":
        - "name": "role"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "customer"
          "description": "Path segment must match the role's `signupEndpoint` (default `customer`; use each role's configured endpoint)."
        - "name": "provider"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "enum":
              - "google"
              - "github"
              - "facebook"
              - "microsoft"
              - "apple"
              - "twitter"
              - "discord"
              - "linkedin"
              - "dropbox"
              - "slack"
              - "reddit"
              - "twitch"
              - "figma"
              - "zoom"
              - "bitbucket"
              - "salesforce"
              - "shopify"
              - "line"
              - "spotify"
              - "strava"
              - "paypal"
              - "asana"
              - "trello"
              - "okta"
              - "gitea"
              - "yandex"
              - "yahoo"
              - "vk"
              - "meetup"
          "example": "google"
          "description": "OAuth provider (e.g. google, github)."
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "685ad30be129932fbb7a1047"
          "description": "Project ID."
        - "name": "redirect_url"
          "in": "query"
          "schema":
            "type": "string"
            "format": "uri"
          "description": "The URL to redirect to after authentication"
          "example": "https://client.app/auth/callback"
      "responses":
        "200":
          "description": "Success (OAuth signup flow initiated; in most cases the server responds with 302 redirect)."
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "redirectUrl":
                    "type": "string"
                    "format": "uri"
        "302":
          "description": "Redirects to OAuth provider's consent screen"
          "headers":
            "Location":
              "schema":
                "type": "string"
                "format": "uri"
              "description": "OAuth provider authorization URL"
        "400":
          "description": "OAuth provider not configured, role not found, or validation error"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "error":
                    "type": "string"
                  "message":
                    "type": "string"
              "examples":
                "providerNotEnabled":
                  "value":
                    "error": "google authentication not enabled for this project"
                    "message": "Please configure google OAuth provider in project settings first"
                "roleNotFound":
                  "value":
                    "error": "Role not found"
                    "message": "Role with endpoint 'seller' is not available for this project"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "Project not found (exact backend message)."
          "$ref": "#/components/responses/ProjectNotFound"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "OAuth signup with specific role"
      "x-sdk-method": "oauthSignupWithRole"
  "/api/schemas/projects/{projectId}/collections":
    "get":
      "tags":
        - "collections"
      "summary": "List collections in project"
      "operationId": "collections.list"
      "description": "List all collections in a project.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
      "responses":
        "200":
          "description": "Collections list"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "collections":
                    "type": "array"
                    "items":
                      "$ref": "#/components/schemas/Collection"
                  "total":
                    "type": "integer"
              "example":
                "collections":
                  - "_id": "685ada8fd9416ac02f171abf"
                    "name": "users"
                    "slug": "users"
                    "project": "685ad30be129932fbb7a1047"
                    "fields":
                      - "name": "email"
                        "type": "email"
                        "required": true
                        "unique": true
                      - "name": "firstName"
                        "type": "string"
                        "required": true
                      - "name": "lastName"
                        "type": "string"
                        "required": true
                    "createdAt": "2024-01-15T10:00:00.000Z"
                  - "_id": "685ada8fd9416ac02f171ac0"
                    "name": "products"
                    "slug": "products"
                    "project": "685ad30be129932fbb7a1047"
                    "fields":
                      - "name": "name"
                        "type": "string"
                        "required": true
                      - "name": "price"
                        "type": "number"
                        "required": true
                    "createdAt": "2024-01-15T11:00:00.000Z"
                "total": 2
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "List collections in project"
      "x-sdk-method": "list"
    "post":
      "tags":
        - "collections"
      "summary": "Create new collection"
      "operationId": "collections.create"
      "description": "Create a new collection in a project.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
      "requestBody":
        "required": true
        "description": "Collection name, optional slug, fields, permissions, and settings."
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/CreateCollectionRequest"
            "example":
              "name": "products"
              "fields":
                - "name": "title"
                  "type": "string"
                  "required": true
                - "name": "price"
                  "type": "number"
                  "required": true
                - "name": "description"
                  "type": "string"
      "responses":
        "201":
          "description": "Collection created"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "message":
                    "type": "string"
                  "collection":
                    "$ref": "#/components/schemas/Collection"
              "example":
                "message": "Collection created successfully"
                "collection":
                  "_id": "685ada8fd9416ac02f171abf"
                  "name": "users"
                  "slug": "users"
                  "project": "685ad30be129932fbb7a1047"
                  "fields":
                    - "name": "email"
                      "type": "email"
                      "required": true
                  "createdAt": "2024-01-15T10:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Create new collection"
      "x-sdk-method": "create"
  "/api/schemas/projects/{projectId}/collections/{collectionId}":
    "get":
      "tags":
        - "collections"
      "summary": "Get single collection"
      "operationId": "collections.get"
      "description": "Get collection details by ID.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "collectionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Collection ID."
      "responses":
        "200":
          "description": "Collection details"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Collection"
              "example":
                "_id": "685ada8fd9416ac02f171abf"
                "name": "users"
                "slug": "users"
                "project": "685ad30be129932fbb7a1047"
                "fields":
                  - "name": "email"
                    "type": "email"
                    "required": true
                  - "name": "firstName"
                    "type": "string"
                    "required": true
                "createdAt": "2024-01-15T10:00:00.000Z"
                "updatedAt": "2024-01-15T10:00:00.000Z"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Get single collection"
      "x-sdk-method": "get"
    "patch":
      "tags":
        - "collections"
      "summary": "Update collection"
      "operationId": "collections.update"
      "description": "Update collection configuration (name, fields, permissions).

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "collectionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Collection ID."
      "requestBody":
        "required": true
        "description": "Fields to update (name, fields, permissions, settings)."
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/UpdateCollectionRequest"
            "example":
              "name": "products_updated"
              "fields":
                - "name": "title"
                  "type": "string"
                  "required": true
                - "name": "price"
                  "type": "number"
                  "required": true
      "responses":
        "200":
          "description": "Collection updated"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "message":
                    "type": "string"
                  "collection":
                    "$ref": "#/components/schemas/Collection"
              "example":
                "message": "Collection updated successfully"
                "collection":
                  "_id": "685ada8fd9416ac02f171abf"
                  "name": "products_updated"
                  "slug": "products-updated"
                  "project": "685ad30be129932fbb7a1047"
                  "fields":
                    - "name": "title"
                      "type": "string"
                      "required": true
                  "updatedAt": "2024-01-15T11:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Update collection"
      "x-sdk-method": "update"
    "delete":
      "tags":
        - "collections"
      "summary": "Delete collection"
      "operationId": "collections.delete"
      "description": "Delete a collection permanently. This is a destructive operation.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "collectionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Collection ID."
      "responses":
        "200":
          "description": "Collection deleted"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "Collection deleted successfully"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Delete collection"
      "x-sdk-method": "delete"
  "/api/data/projects/{projectId}/collections/{collectionId}/data":
    "get":
      "tags":
        - "data"
      "summary": "List data in collection"
      "operationId": "data.list"
      "description": "List all documents in a collection with optional pagination, sort, and filter.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "collectionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Collection ID."
        - "name": "page"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 1
          "description": "Page number (1-based)."
        - "name": "limit"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 20
            "maximum": 100
          "description": "Number of documents per page."
        - "name": "sort"
          "in": "query"
          "schema":
            "type": "string"
            "default": "-createdAt"
          "description": "Sort field and order (e.g. -createdAt, name)."
        - "name": "filter"
          "in": "query"
          "schema":
            "type": "string"
            "description": "JSON filter object"
          "description": "JSON string for filtering documents (e.g. {\"status\":\"active\"})."
      "responses":
        "200":
          "description": "Data list"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/DataListResponse"
              "example":
                "data":
                  - "_id": "696bbe5b99eeb7f929a93e0b"
                    "title": "Laptop"
                    "price": 8500
                    "description": "High-performance laptop for developers"
                    "createdAt": "2026-01-17T16:52:43.541Z"
                    "updatedAt": "2026-01-17T16:52:43.542Z"
                  - "_id": "696bbe5c99eeb7f929a93e0c"
                    "title": "Mouse"
                    "price": 25
                    "description": "Wireless mouse"
                    "createdAt": "2026-01-17T16:53:10.123Z"
                    "updatedAt": "2026-01-17T16:53:10.123Z"
                "pagination":
                  "page": 1
                  "limit": 20
                  "total": 2
                  "totalPages": 1
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "List data in collection"
      "x-sdk-method": "list"
    "post":
      "tags":
        - "data"
      "summary": "Create data in collection"
      "description": "Create a new document in a collection. Request body must match the collection schema.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "operationId": "data.create"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "collectionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Collection ID."
      "requestBody":
        "required": true
        "description": "Document fields matching the collection schema."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "description": "Data object matching collection schema"
            "example":
              "email": "john.doe@example.com"
              "firstName": "John"
              "lastName": "Doe"
              "role": "developer"
              "status": "active"
      "responses":
        "201":
          "description": "Data created"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/DataResponse"
              "example":
                "message": "Data created successfully"
                "data":
                  "_id": "685ae1210136e73fa1dcaf36"
                  "email": "john.doe@mudbase.dev"
                  "firstName": "John"
                  "lastName": "Doe"
                  "role": "developer"
                  "createdAt": "2024-01-15T10:00:00.000Z"
                  "updatedAt": "2024-01-15T10:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Create data in collection"
      "x-sdk-method": "create"
  "/api/data/projects/{projectId}/collections/{collectionId}/data/{documentId}":
    "get":
      "tags":
        - "data"
      "summary": "Get single document"
      "operationId": "data.get"
      "description": "Get a document by ID from a collection.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "collectionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Collection ID."
        - "name": "documentId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Document ID."
      "responses":
        "200":
          "description": "Document data"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/DataResponse"
              "example":
                "_id": "685ae1210136e73fa1dcaf36"
                "email": "user@example.com"
                "firstName": "John"
                "lastName": "Doe"
                "createdAt": "2024-01-15T10:00:00.000Z"
                "updatedAt": "2024-01-15T10:00:00.000Z"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Get single document"
      "x-sdk-method": "get"
    "patch":
      "tags":
        - "data"
      "summary": "Update document"
      "operationId": "data.update"
      "description": "Update a document in a collection.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "collectionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Collection ID."
        - "name": "documentId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Document ID."
      "requestBody":
        "required": true
        "description": "Partial document fields to update."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "description": "Partial data object for update"
            "example":
              "firstName": "Sarah"
              "lastName": "Chen"
              "email": "sarah.chen@example.com"
              "role": "admin"
              "status": "active"
      "responses":
        "200":
          "description": "Data updated"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/DataResponse"
              "example":
                "message": "Data updated successfully"
                "data":
                  "_id": "685ae1210136e73fa1dcaf36"
                  "firstName": "Sarah"
                  "lastName": "Chen"
                  "email": "sarah.chen@example.com"
                  "role": "admin"
                  "status": "active"
                  "updatedAt": "2024-01-15T11:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Update document"
      "x-sdk-method": "update"
    "delete":
      "tags":
        - "data"
      "summary": "Delete document"
      "operationId": "data.delete"
      "description": "Delete a document from a collection.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "collectionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Collection ID."
        - "name": "documentId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Document ID."
      "responses":
        "200":
          "description": "Data deleted"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "Data deleted successfully"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Delete document"
      "x-sdk-method": "delete"
  "/api/bucket/projects/{projectId}/buckets":
    "post":
      "tags":
        - "storage"
      "summary": "Create a new bucket"
      "operationId": "storage.createBucket"
      "description": "Create a new storage bucket in a project.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
      "requestBody":
        "required": true
        "description": "Bucket name, isPublic flag, and optional settings."
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/CreateBucketRequest"
            "example":
              "name": "my-bucket"
              "isPublic": false
              "settings": {}
      "responses":
        "201":
          "description": "Bucket created successfully"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/BucketResponse"
              "example":
                "success": true
                "message": "Bucket created successfully"
                "bucket":
                  "_id": "65a1b2c3d4e5f6789012345a"
                  "name": "my-bucket"
                  "project": "685ad30be129932fbb7a1047"
                  "isPublic": false
                  "settings": {}
                  "createdAt": "2024-01-15T10:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "409":
          "description": "Conflict (e.g. resource already exists or state conflict)."
          "$ref": "#/components/responses/Conflict"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Create a new bucket"
      "x-sdk-method": "createBucket"
    "get":
      "tags":
        - "storage"
      "summary": "List buckets in a project"
      "operationId": "storage.listBuckets"
      "description": "List all storage buckets in a project with pagination and search.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "page"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 1
          "description": "Page number (1-based)."
        - "name": "limit"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 20
          "description": "Number of buckets per page."
        - "name": "search"
          "in": "query"
          "schema":
            "type": "string"
          "description": "Search by bucket name."
      "responses":
        "200":
          "description": "List of buckets"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/BucketListResponse"
              "example":
                "success": true
                "buckets":
                  - "_id": "65a1b2c3d4e5f6789012345a"
                    "name": "my-bucket"
                    "project": "685ad30be129932fbb7a1047"
                    "isPublic": false
                    "createdAt": "2024-01-15T10:00:00.000Z"
                "pagination":
                  "page": 1
                  "limit": 20
                  "total": 1
                  "totalPages": 1
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "409":
          "description": "Conflict (e.g. resource already exists or state conflict)."
          "$ref": "#/components/responses/Conflict"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "List buckets in a project"
      "x-sdk-method": "listBuckets"
  "/api/bucket/projects/{projectId}/buckets/{bucketId}":
    "get":
      "tags":
        - "storage"
      "summary": "Get bucket details"
      "description": "Retrieve metadata and configuration for a single storage bucket, including name, project, public/private status, and settings.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "operationId": "storage.getBucket"
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "bucketId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Bucket ID."
      "responses":
        "200":
          "description": "Bucket details"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/BucketResponse"
              "example":
                "success": true
                "message": "Bucket retrieved successfully"
                "bucket":
                  "_id": "65a1b2c3d4e5f6789012345a"
                  "name": "my-bucket"
                  "project": "685ad30be129932fbb7a1047"
                  "isPublic": false
                  "settings": {}
                  "createdAt": "2024-01-15T10:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "409":
          "description": "Conflict (e.g. resource already exists or state conflict)."
          "$ref": "#/components/responses/Conflict"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Get bucket details"
      "x-sdk-method": "getBucket"
    "patch":
      "tags":
        - "storage"
      "summary": "Update bucket"
      "operationId": "storage.updateBucket"
      "description": "Update bucket configuration (name, public/private status, settings).

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "bucketId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Bucket ID."
      "requestBody":
        "required": true
        "description": "Fields to update (name, isPublic, settings)."
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/UpdateBucketRequest"
            "example":
              "name": "my-bucket-updated"
              "isPublic": true
              "settings": {}
      "responses":
        "200":
          "description": "Bucket updated successfully"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/BucketResponse"
              "example":
                "success": true
                "message": "Bucket updated successfully"
                "bucket":
                  "_id": "65a1b2c3d4e5f6789012345a"
                  "name": "my-bucket-updated"
                  "project": "685ad30be129932fbb7a1047"
                  "isPublic": true
                  "settings": {}
                  "updatedAt": "2024-01-15T11:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "409":
          "description": "Conflict (e.g. resource already exists or state conflict)."
          "$ref": "#/components/responses/Conflict"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Update bucket"
      "x-sdk-method": "updateBucket"
    "delete":
      "tags":
        - "storage"
      "summary": "Delete bucket"
      "operationId": "storage.deleteBucket"
      "description": "Delete a storage bucket permanently. This is a destructive operation that will also delete all files in the bucket.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "bucketId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Bucket ID."
      "responses":
        "200":
          "description": "Bucket deleted successfully"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "Bucket deleted successfully"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "409":
          "description": "Conflict (e.g. resource already exists or state conflict)."
          "$ref": "#/components/responses/Conflict"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Delete bucket"
      "x-sdk-method": "deleteBucket"
  "/api/bucket/projects/{projectId}/buckets/{bucketId}/files":
    "post":
      "tags":
        - "storage"
      "summary": "Upload files to bucket"
      "operationId": "storage.uploadFiles"
      "description": "Upload one or more files to a storage bucket using multipart/form-data.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "bucketId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Bucket ID."
      "requestBody":
        "required": true
        "description": "Use multipart/form-data for file upload (files required; optional folder, tags). application/json uses the same schema for metadata-only or tooling that prefers JSON."
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/UploadFilesToBucketRequest"
          "multipart/form-data":
            "schema":
              "$ref": "#/components/schemas/UploadFilesToBucketRequest"
            "encoding":
              "files":
                "contentType": "application/octet-stream"
      "responses":
        "201":
          "description": "Files uploaded successfully"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/FileUploadResponse"
              "example":
                "message": "Files uploaded successfully"
                "file":
                  "_id": "685af8b85d73a104065b6a77"
                  "name": "example.pdf"
                  "size": 1024000
                  "mimeType": "application/pdf"
                  "bucket": "65a1b2c3d4e5f6789012345a"
                  "url": "https://storage.example.com/files/685af8b85d73a104065b6a77"
                  "createdAt": "2024-01-15T10:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "409":
          "description": "Conflict (e.g. resource already exists or state conflict)."
          "$ref": "#/components/responses/Conflict"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Upload files to bucket"
      "x-sdk-method": "uploadFiles"
    "get":
      "tags":
        - "storage"
      "summary": "List files in bucket"
      "operationId": "storage.listFiles"
      "description": "List files in a bucket with pagination, search, and optional type filter.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "bucketId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Bucket ID."
        - "name": "page"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 1
          "description": "Page number (1-based)."
        - "name": "limit"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 20
          "description": "Number of files per page."
        - "name": "search"
          "in": "query"
          "schema":
            "type": "string"
          "description": "Search by filename."
        - "name": "type"
          "in": "query"
          "schema":
            "type": "string"
          "description": "Filter by MIME type or file type."
      "responses":
        "200":
          "description": "List of files"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/FileListResponse"
              "example":
                "files":
                  - "_id": "685af8b85d73a104065b6a77"
                    "name": "example.pdf"
                    "size": 1024000
                    "mimeType": "application/pdf"
                    "bucket": "65a1b2c3d4e5f6789012345a"
                    "url": "https://storage.example.com/files/685af8b85d73a104065b6a77"
                    "createdAt": "2024-01-15T10:00:00.000Z"
                "total": 1
                "page": 1
                "limit": 20
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "409":
          "description": "Conflict (e.g. resource already exists or state conflict)."
          "$ref": "#/components/responses/Conflict"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "List files in bucket"
      "x-sdk-method": "listFiles"
  "/api/bucket/projects/{projectId}/buckets/{bucketId}/files/{fileId}":
    "get":
      "tags":
        - "storage"
      "summary": "Get file metadata"
      "operationId": "storage.getFile"
      "description": "Get metadata for a specific file in a bucket.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "bucketId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Bucket ID."
        - "name": "fileId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "File ID."
      "responses":
        "200":
          "description": "File metadata"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/FileResponse"
              "example":
                "file":
                  "_id": "685af8b85d73a104065b6a77"
                  "name": "example.pdf"
                  "size": 1024000
                  "mimeType": "application/pdf"
                  "bucket": "65a1b2c3d4e5f6789012345a"
                  "url": "https://storage.example.com/files/685af8b85d73a104065b6a77"
                  "createdAt": "2024-01-15T10:00:00.000Z"
                  "updatedAt": "2024-01-15T10:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "File not found (exact backend message)."
          "$ref": "#/components/responses/FileNotFound"
        "409":
          "description": "Conflict (e.g. resource already exists or state conflict)."
          "$ref": "#/components/responses/Conflict"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Get file metadata"
      "x-sdk-method": "getFile"
    "delete":
      "tags":
        - "storage"
      "summary": "Delete file"
      "operationId": "storage.deleteFile"
      "description": "Delete a file from a bucket permanently.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "bucketId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Bucket ID."
        - "name": "fileId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "File ID."
      "responses":
        "200":
          "description": "File deleted successfully"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "File deleted successfully"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "File not found (exact backend message)."
          "$ref": "#/components/responses/FileNotFound"
        "409":
          "description": "Conflict (e.g. resource already exists or state conflict)."
          "$ref": "#/components/responses/Conflict"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Delete file"
      "x-sdk-method": "deleteFile"
  "/api/files/{fileId}/download":
    "get":
      "tags":
        - "storage"
      "summary": "Generate a presigned URL for downloading a file"
      "description": "Returns a time-limited provider-signed URL (S3) for direct download. Server enforces RBAC before issuing the URL."
      "operationId": "storage.downloadFile"
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "fileId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "File ID."
        - "name": "token"
          "in": "query"
          "schema":
            "type": "string"
          "description": "Optional one-time download token (if provided by upload flow)."
      "responses":
        "200":
          "description": "Signed URL generated"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/SignedUrlResponse"
              "example":
                "success": true
                "url": "https://my-bucket.s3.us-east-1.amazonaws.com/projects/123/default/abcd-file.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=..."
                "expiresIn": 3600
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "File not found (exact backend message)."
          "$ref": "#/components/responses/FileNotFound"
        "409":
          "description": "Conflict (e.g. resource already exists or state conflict)."
          "$ref": "#/components/responses/Conflict"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Generate a presigned URL for downloading a file"
      "x-sdk-method": "downloadFile"
  "/api/files/upload/presigned":
    "post":
      "tags":
        - "storage"
      "summary": "Generate presigned POST data for direct browser upload"
      "operationId": "storage.getPresignedUpload"
      "description": "Issue a presigned POST (fields + url) for clients to upload directly to S3. The server stores the issued key with expiry and RBAC is enforced."
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "requestBody":
        "required": true
        "description": "projectId, originalName, optional bucket, contentType, isPublic."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "projectId"
                - "originalName"
              "properties":
                "projectId":
                  "type": "string"
                "bucket":
                  "type": "string"
                  "default": "default"
                "originalName":
                  "type": "string"
                "contentType":
                  "type": "string"
                "isPublic":
                  "type": "boolean"
                  "default": false
            "example":
              "projectId": "65a1b2c3d4e5f6789012345a"
              "bucket": "default"
              "originalName": "invoice.pdf"
              "contentType": "application/pdf"
              "isPublic": false
      "responses":
        "200":
          "description": "Presigned POST data"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/PresignedPostResponse"
              "example":
                "key": "65a1b2c3d4e5f6789012345a/default/abcd-1234-invoice.pdf"
                "url": "https://my-bucket.s3.amazonaws.com/"
                "fields":
                  "key": "65a1b2c3d4e5f6789012345a/default/abcd-1234-invoice.pdf"
                  "Policy": "BASE64_POLICY"
                  "X-Amz-Signature": "signature"
                "expiresIn": 3600
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Generate presigned POST data for direct browser upload"
      "x-sdk-method": "getPresignedUpload"
  "/api/files/upload/confirm":
    "post":
      "tags":
        - "storage"
      "summary": "Confirm direct upload (scan + finalize metadata)"
      "operationId": "storage.confirmUpload"
      "description": "After a client uploads directly to S3 using the presigned POST, call this endpoint to have the server scan the object, create the File record, and optionally quarantine if infected."
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "requestBody":
        "required": true
        "description": "S3 key from presigned response, projectId, and optional originalName, contentType, size, bucket, isPublic."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "key"
                - "projectId"
              "properties":
                "key":
                  "type": "string"
                  "description": "The S3 object key returned when the presigned POST was issued"
                "projectId":
                  "type": "string"
                "originalName":
                  "type": "string"
                "contentType":
                  "type": "string"
                "size":
                  "type": "integer"
                "bucket":
                  "type": "string"
                "isPublic":
                  "type": "boolean"
            "example":
              "key": "65a1b2c3d4e5f6789012345a/default/abcd-1234-invoice.pdf"
              "projectId": "65a1b2c3d4e5f6789012345a"
              "originalName": "invoice.pdf"
              "contentType": "application/pdf"
              "size": 52312
              "isPublic": false
      "responses":
        "201":
          "description": "File confirmed and metadata stored"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/ConfirmUploadResponse"
              "example":
                "fileId": "abcd1234ef567890"
                "status": "ok"
                "scan":
                  "status": "clean"
                  "provider": "virustotal"
                  "detections": 0
        "400":
          "description": "Bad request or file quarantined"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "message":
                    "type": "string"
                  "details":
                    "type": "object"
              "example":
                "message": "File quarantined"
                "details":
                  "fileId": "abcd1234ef567890"
                  "status": "quarantined"
                  "threat": "EICAR-Test-Signature"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Confirm direct upload (scan + finalize metadata)"
      "x-sdk-method": "confirmUpload"
  "/api/bucket/projects/{projectId}/buckets/{bucketId}/files/{fileId}/signed-url":
    "post":
      "tags":
        - "storage"
      "summary": "Generate signed URL for file"
      "operationId": "storage.getSignedUrl"
      "description": "Generate a time-limited signed URL for downloading a private file.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "bucketId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Bucket ID."
        - "name": "fileId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "File ID."
      "requestBody":
        "description": "Optional expiresIn (seconds) for the signed URL."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "properties":
                "expiresIn":
                  "type": "integer"
                  "default": 3600
                  "example": 3600
            "example":
              "expiresIn": 3600
      "responses":
        "200":
          "description": "Signed URL generated"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/SignedUrlResponse"
              "example":
                "success": true
                "url": "https://storage.example.com/files/685af8b85d73a104065b6a77?token=abc123xyz789&expires=1705312800"
                "expiresAt": "2024-01-15T11:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "409":
          "description": "Conflict (e.g. resource already exists or state conflict)."
          "$ref": "#/components/responses/Conflict"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Generate signed URL for file"
      "x-sdk-method": "getSignedUrl"
  "/api/bucket/files/{fileId}/download":
    "get":
      "tags":
        - "storage"
      "summary": "Download file from bucket"
      "operationId": "storage.downloadBucketFile"
      "description": "Download a file from a bucket. For public files, no authentication is required.

        For private files, a download token (obtained via signed URL endpoint) is required in the query parameter.

        Accepts: Token-based authentication via query parameter (for private files), or no authentication (for public files).\n"
      "security": []
      "parameters":
        - "name": "fileId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "685af8b85d73a104065b6a77"
          "description": "File ID to download."
        - "name": "token"
          "in": "query"
          "schema":
            "type": "string"
          "description": "Download token for private files (from signed URL endpoint)."
      "responses":
        "200":
          "description": "File download"
          "content":
            "application/octet-stream":
              "schema":
                "type": "string"
                "format": "binary"
          "headers":
            "Content-Type":
              "schema":
                "type": "string"
            "Content-Length":
              "schema":
                "type": "integer"
            "Content-Disposition":
              "schema":
                "type": "string"
        "403":
          "description": "Access denied or invalid token"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "error":
                    "type": "string"
                    "example": "Invalid or expired download token"
              "example":
                "error": "Invalid or expired download token"
        "404":
          "description": "File not found"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "error":
                    "type": "string"
                    "example": "File not found"
              "example":
                "error": "File not found"
      "x-display-name": "Download file from bucket"
      "x-sdk-method": "downloadBucketFile"
  "/api/webhooks/stats":
    "get":
      "tags":
        - "webhooks"
      "summary": "Get webhook statistics"
      "operationId": "webhooks.getStats"
      "description": "Get webhook delivery statistics including success rate, total deliveries, and breakdown by status.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "query"
          "schema":
            "type": "string"
          "description": "Project ID to filter stats (optional)."
        - "name": "days"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 7
          "description": "Number of days to include in the stats window."
      "responses":
        "200":
          "description": "Webhook statistics"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/WebhookStatsResponse"
              "example":
                "total": 100
                "success": 85
                "failed": 10
                "pending": 5
                "successRate": 0.85
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Get webhook statistics"
      "x-sdk-method": "getStats"
  "/api/functions/webhook/{projectId}":
    "post":
      "tags":
        - "functions"
      "summary": "Trigger webhook functions"
      "operationId": "functions.triggerWebhook"
      "description": "Public endpoint for external services to trigger functions with `trigger.type: webhook`.

        No authentication required. Optionally verify using `X-Webhook-Secret` header (configure per project or via FUNCTION_WEBHOOK_SECRET).

        Rate limited to 30 requests per 15 minutes per IP.\n"
      "security": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "format": "objectid"
          "description": "Project ID."
        - "name": "X-Webhook-Secret"
          "in": "header"
          "required": false
          "schema":
            "type": "string"
          "description": "Optional webhook secret for verification"
      "requestBody":
        "description": "Payload sent to the triggered function(s)."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "description": "Payload sent to triggered functions"
          "application/x-www-form-urlencoded":
            "schema":
              "type": "object"
          "text/plain":
            "schema":
              "type": "string"
      "responses":
        "200":
          "description": "Functions triggered successfully"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "triggered":
                    "type": "integer"
                    "description": "Number of functions triggered"
                  "results":
                    "type": "array"
                    "items":
                      "type": "object"
              "examples":
                "success":
                  "summary": "Successful trigger"
                  "value":
                    "success": true
                    "triggered": 2
                    "results":
                      - "functionId": "685af8b85d73a104065b6a77"
                        "success": true
                        "result":
                          "processed": true
                        "executionTime": 45
                      - "functionId": "685af8b85d73a104065b6a78"
                        "success": true
                        "result":
                          "processed": true
                        "executionTime": 32
                "noFunctions":
                  "summary": "No matching functions"
                  "value":
                    "success": true
                    "triggered": 0
                    "results": []
        "400":
          "description": "Invalid project ID"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                    "example": false
                  "error":
                    "type": "string"
        "401":
          "description": "Invalid webhook secret"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                    "example": false
                  "error":
                    "type": "string"
                    "example": "Invalid webhook secret"
        "404":
          "description": "Project not found (exact backend message)."
          "$ref": "#/components/responses/ProjectNotFound"
        "429":
          "description": "Rate limit exceeded"
      "x-display-name": "Trigger webhook functions"
      "x-sdk-method": "triggerWebhook"
  "/api/functions/projects/{projectId}/functions":
    "get":
      "tags":
        - "functions"
      "summary": "List functions"
      "operationId": "functions.list"
      "description": "List serverless functions in a project with optional search and filters.

        Supports trigger types: http, event, document, file, webhook, wallet, cron, messaging.\n"
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "page"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 1
          "description": "Page number (1-based)."
        - "name": "limit"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 20
          "description": "Number of functions per page."
        - "name": "search"
          "in": "query"
          "schema":
            "type": "string"
          "description": "Search by name or description"
        - "name": "triggerType"
          "in": "query"
          "schema":
            "type": "string"
            "enum":
              - "http"
              - "event"
              - "document"
              - "file"
              - "webhook"
              - "wallet"
              - "cron"
              - "messaging"
          "description": "Filter by trigger type"
        - "name": "isActive"
          "in": "query"
          "schema":
            "type": "boolean"
          "description": "Filter by active status (true/false)"
      "responses":
        "200":
          "description": "Functions list"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/FunctionListResponse"
              "examples":
                "withFilters":
                  "summary": "List with search and filters"
                  "value":
                    "success": true
                    "data":
                      "functions":
                        - "_id": "685af8b85d73a104065b6a77"
                          "name": "ProcessUserData"
                          "description": "Process user data on create"
                          "trigger":
                            "type": "document"
                            "event": "create"
                            "collectionId": "685ada8fd9416ac02f171abf"
                          "isActive": true
                          "stats":
                            "totalExecutions": 42
                            "successful": 40
                            "failed": 2
                            "successRate": 95.24
                            "avgExecutionTime": 125
                            "lastRun": "2024-01-15T10:30:00.000Z"
                      "pagination":
                        "page": 1
                        "limit": 20
                        "total": 1
                        "pages": 1
                "webhookFunctions":
                  "summary": "Webhook-triggered functions"
                  "value":
                    "success": true
                    "data":
                      "functions":
                        - "_id": "685af8b85d73a104065b6a79"
                          "name": "HandleStripeWebhook"
                          "trigger":
                            "type": "webhook"
                            "event": "received"
                          "isActive": true
                      "pagination":
                        "page": 1
                        "limit": 20
                        "total": 1
                        "pages": 1
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "List functions"
      "x-sdk-method": "list"
    "post":
      "tags":
        - "functions"
      "summary": "Create function"
      "operationId": "functions.create"
      "description": "Create a new serverless function. Trigger types: http, document, file, webhook, wallet, cron, messaging.

        Sandbox utilities available: db, files, messaging, wallet, utils, env, console.\n"
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
      "requestBody":
        "required": true
        "description": "Function name, description, code, trigger config, and optional environment."
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/CreateFunctionRequest"
            "examples":
              "documentTrigger":
                "summary": "Document create trigger"
                "value":
                  "name": "OnUserCreate"
                  "description": "Process new users"
                  "code": "const count = await db.find('users', payload.document?.data ? { email: payload.document.data.email } : {});

                    return { found: count.length };\n"
                  "trigger":
                    "type": "document"
                    "event": "create"
                    "collectionId": "685ada8fd9416ac02f171abf"
                  "environment":
                    "DEBUG": "true"
              "webhookTrigger":
                "summary": "Webhook trigger"
                "value":
                  "name": "HandleWebhook"
                  "code": "return { received: payload.webhook?.body || payload };\n"
                  "trigger":
                    "type": "webhook"
                    "event": "received"
              "cronTrigger":
                "summary": "Scheduled (cron) trigger"
                "value":
                  "name": "DailyReport"
                  "code": "return { ran: new Date().toISOString() };\n"
                  "trigger":
                    "type": "cron"
                    "schedule": "daily"
              "httpTrigger":
                "summary": "HTTP trigger"
                "value":
                  "name": "HttpWebhook"
                  "code": "// payload.webhook contains headers/body for incoming HTTP

                    return { headers: payload.webhook?.headers || {}, body: payload.webhook?.body || {} };\n"
                  "trigger":
                    "type": "http"
                    "path": "/projects/{projectId}/webhooks/custom"
                    "method": "POST"
              "fileTrigger":
                "summary": "File trigger"
                "value":
                  "name": "ProcessFileUpload"
                  "code": "const meta = payload.file || {};

                    // Example: fetch metadata and return id

                    const md = await files.getMetadata(meta.fileId).catch(()=>null);

                    return { fileId: meta.fileId, metadata: md };\n"
                  "trigger":
                    "type": "file"
                    "event": "uploaded"
              "walletTrigger":
                "summary": "Wallet transaction trigger"
                "value":
                  "name": "OnWalletTx"
                  "code": "const w = payload.wallet || {};

                    const tx = w.transaction || {};

                    // Example: log tx hash and amount

                    return { txHash: tx.txHash || w.txHash, amount: tx.amount || null };\n"
                  "trigger":
                    "type": "wallet"
                    "event": "tx"
              "messagingTrigger":
                "summary": "Messaging trigger"
                "value":
                  "name": "OnMessageSent"
                  "code": "const msg = payload.message || {};

                    // Example: forward message summary to ops via email

                    await messaging.sendEmail({ to: 'ops@mudbase.dev', subject: 'New message', html: `<pre>${JSON.stringify(msg, null, 2)}</pre>` }).catch(()=>null);

                    return { notified: true, messageId: msg.messageId };\n"
                  "trigger":
                    "type": "messaging"
                    "event": "sent"
              "customCronTrigger":
                "summary": "Custom cron expression"
                "value":
                  "name": "HourlyCleanup"
                  "code": "// runs hourly

                    return { cleaned: true, at: new Date().toISOString() };\n"
                  "trigger":
                    "type": "cron"
                    "schedule": "0 * * * *"
      "responses":
        "201":
          "description": "Function created"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/FunctionResponse"
              "examples":
                "created":
                  "summary": "Function created"
                  "value":
                    "success": true
                    "data":
                      "_id": "685af8b85d73a104065b6a77"
                      "name": "OnUserCreate"
                      "trigger":
                        "type": "document"
                        "event": "create"
                        "collectionId": "685ada8fd9416ac02f171abf"
                      "project": "685ad30be129932fbb7a1047"
                      "isActive": true
                      "versions":
                        - "version": 1
                          "comment": "Initial version"
                      "createdAt": "2024-01-15T10:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Create function"
      "x-sdk-method": "create"
  "/api/functions/projects/{projectId}/functions/{functionId}":
    "get":
      "tags":
        - "functions"
      "summary": "Get function"
      "operationId": "functions.get"
      "description": "Get function details by ID including createdBy/updatedBy."
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "functionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Function ID."
      "responses":
        "200":
          "description": "Function details"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/FunctionResponse"
              "example":
                "success": true
                "data":
                  "_id": "685af8b85d73a104065b6a77"
                  "name": "OnUserCreate"
                  "description": "Process new users"
                  "trigger":
                    "type": "document"
                    "event": "create"
                    "collectionId": "685ada8fd9416ac02f171abf"
                  "project": "685ad30be129932fbb7a1047"
                  "isActive": true
                  "limits":
                    "timeout": 30000
                    "maxPayloadSize": 1048576
                    "maxExecutionsPerMinute": 60
                    "maxExecutionsPerHour": 1000
                  "stats":
                    "totalExecutions": 42
                    "successful": 40
                    "failed": 2
                    "successRate": 95.24
                    "avgExecutionTime": 125
                    "lastRun": "2024-01-15T10:30:00.000Z"
                  "createdBy":
                    "_id": "685acbe0e129932fbb7a0fc2"
                    "name": "John Doe"
                    "email": "john@example.com"
                  "createdAt": "2024-01-15T10:00:00.000Z"
                  "updatedAt": "2024-01-15T10:00:00.000Z"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "Function not found (exact backend message)."
          "$ref": "#/components/responses/FunctionNotFound"
      "x-display-name": "Get function"
      "x-sdk-method": "get"
    "put":
      "tags":
        - "functions"
      "summary": "Update function"
      "operationId": "functions.update"
      "description": "Update function configuration. Code changes are versioned automatically."
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "functionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Function ID."
      "requestBody":
        "description": "Fields to update (name, description, code, trigger, environment, isActive, limits, retryPolicy)."
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/UpdateFunctionRequest"
            "examples":
              "nameAndCode":
                "summary": "Update name and code"
                "value":
                  "name": "OnUserCreate v2"
                  "code": "return { version: 2 };\n"
                  "versionComment": "Add version tracking"
              "limits":
                "summary": "Update execution limits"
                "value":
                  "limits":
                    "timeout": 60000
                    "maxPayloadSize": 2097152
                    "maxExecutionsPerMinute": 120
      "responses":
        "200":
          "description": "Function updated"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/FunctionResponse"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "Function not found (exact backend message)."
          "$ref": "#/components/responses/FunctionNotFound"
      "x-display-name": "Update function"
      "x-sdk-method": "update"
    "delete":
      "tags":
        - "functions"
      "summary": "Delete function"
      "operationId": "functions.delete"
      "description": "Delete a function permanently. This is a destructive operation."
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "functionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Function ID to delete."
      "responses":
        "200":
          "description": "Function deleted"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "message":
                    "type": "string"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Delete function"
      "x-sdk-method": "delete"
  "/api/functions/projects/{projectId}/functions/{functionId}/activate":
    "post":
      "tags":
        - "functions"
      "summary": "Activate function"
      "operationId": "functions.activate"
      "description": "Activate a deactivated function. Active functions can be triggered."
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) that owns the function."
        - "name": "functionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Function ID (MongoDB ObjectId) to activate."
      "responses":
        "200":
          "description": "Function activated"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/FunctionResponse"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Activate function"
      "x-sdk-method": "activate"
  "/api/functions/projects/{projectId}/functions/{functionId}/deactivate":
    "post":
      "tags":
        - "functions"
      "summary": "Deactivate function"
      "operationId": "functions.deactivate"
      "description": "Deactivate a function. Deactivated functions will not be triggered."
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) that owns the function."
        - "name": "functionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Function ID (MongoDB ObjectId) to deactivate."
      "responses":
        "200":
          "description": "Function deactivated"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/FunctionResponse"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Deactivate function"
      "x-sdk-method": "deactivate"
  "/api/functions/projects/{projectId}/functions/{functionId}/execute":
    "post":
      "tags":
        - "functions"
      "summary": "Execute function"
      "operationId": "functions.execute"
      "description": "Manually execute a function with custom payload. Payload is merged with auto-injected trigger context.

        Rate limited (data mutation rate limiter). Enforces maxExecutionsPerMinute/maxExecutionsPerHour.\n"
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) that owns the function."
        - "name": "functionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Function ID (MongoDB ObjectId) to execute."
      "requestBody":
        "description": "Optional JSON payload merged with trigger context (e.g. document, file, webhook body). Omit for no custom input."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "properties":
                "payload":
                  "type": "object"
                  "description": "Custom input merged with trigger context"
            "examples":
              "simplePayload":
                "summary": "Simple payload"
                "value":
                  "payload":
                    "userId": "685acbe0e129932fbb7a0fc2"
                    "action": "process"
              "documentContext":
                "summary": "Simulate document trigger payload"
                "value":
                  "payload":
                    "document":
                      "_id": "685ae1210136e73fa1dcaf36"
                      "collectionId": "685ada8fd9416ac02f171abf"
                      "data":
                        "name": "John"
                        "email": "john@example.com"
              "webhookPayload":
                "summary": "Webhook-style payload"
                "value":
                  "payload":
                    "webhook":
                      "headers":
                        "content-type": "application/json"
                      "body":
                        "event": "invoice.paid"
                        "invoiceId": "inv_123"
                        "amount": 49.99
              "fileUploadPayload":
                "summary": "File upload event payload"
                "value":
                  "payload":
                    "file":
                      "fileId": "file_abc123"
                      "bucket": "default"
                      "url": "https://cdn.example.com/project/default/file_abc123.jpg"
                      "originalName": "photo.jpg"
                      "mimeType": "image/jpeg"
                      "size": 345678
              "walletTxPayload":
                "summary": "Wallet transaction payload"
                "value":
                  "payload":
                    "wallet":
                      "walletId": "w_123"
                      "address": "0xabc..."
                      "chain": "ethereum"
                      "txHash": "0xdeadbeef..."
                      "transaction":
                        "amount": 0.5
                        "currency": "ETH"
              "cronPayload":
                "summary": "Cron/scheduled payload"
                "value":
                  "payload":
                    "cron":
                      "schedule": "daily"
                      "at": "2024-01-15T00:00:00.000Z"
              "messagingPayload":
                "summary": "Messaging payload"
                "value":
                  "payload":
                    "message":
                      "messageId": "msg_123"
                      "senderId": "user_123"
                      "chatId": "chat_456"
                      "content":
                        "text": "Hello world"
      "responses":
        "200":
          "description": "Function executed successfully"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/FunctionExecutionResponse"
              "examples":
                "success":
                  "summary": "Successful execution"
                  "value":
                    "success": true
                    "data":
                      "success": true
                      "result":
                        "processed": 1
                        "count": 5
                      "executionTime": 125
                "failure":
                  "summary": "Execution failed"
                  "value":
                    "success": false
                    "error": "ReferenceError: x is not defined"
                    "data":
                      "success": false
                      "error": "ReferenceError: x is not defined"
                      "executionTime": 15
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "429":
          "description": "Rate limit exceeded"
      "x-display-name": "Execute function"
      "x-sdk-method": "execute"
  "/api/functions/projects/{projectId}/functions/{functionId}/logs":
    "get":
      "tags":
        - "functions"
      "summary": "Get function execution logs"
      "operationId": "functions.getLogs"
      "description": "Get execution logs with pagination. Includes stats (totalExecutions, successful, failed, successRate, avgExecutionTime, lastRun)."
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) that owns the function."
        - "name": "functionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Function ID (MongoDB ObjectId) to get logs for."
        - "name": "limit"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 50
          "description": "Maximum number of log entries to return."
        - "name": "offset"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 0
          "description": "Number of log entries to skip for pagination."
      "responses":
        "200":
          "description": "Function logs and stats"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/FunctionLogsResponse"
              "examples":
                "withStats":
                  "summary": "Logs with stats"
                  "value":
                    "success": true
                    "data":
                      "executions":
                        - "executedAt": "2024-01-15T10:30:00.000Z"
                          "executionTime": 125
                          "success": true
                          "result":
                            "processed": 1
                          "triggerType": "document"
                          "triggerEvent": "create"
                          "invokedBy": "trigger"
                        - "executedAt": "2024-01-15T10:29:00.000Z"
                          "executionTime": 0
                          "success": false
                          "error": "Timeout"
                          "invokedBy": "manual"
                      "stats":
                        "totalExecutions": 42
                        "successful": 40
                        "failed": 2
                        "successRate": 95.24
                        "avgExecutionTime": 125
                        "lastRun": "2024-01-15T10:30:00.000Z"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Get function execution logs"
      "x-sdk-method": "getLogs"
  "/api/functions/projects/{projectId}/functions/{functionId}/retry/{executionIndex}":
    "post":
      "tags":
        - "functions"
      "summary": "Retry failed execution"
      "operationId": "functions.retry"
      "description": "Retry a failed execution by its index (0-based) in the logs. Cannot retry successful executions."
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) that owns the function."
        - "name": "functionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Function ID (MongoDB ObjectId) to retry execution for."
        - "name": "executionIndex"
          "in": "path"
          "required": true
          "schema":
            "type": "integer"
          "description": "0-based index of the execution in logs"
      "responses":
        "200":
          "description": "Retry result"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/FunctionExecutionResponse"
        "400":
          "description": "Cannot retry successful execution"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "Function or execution not found (exact backend message)."
          "$ref": "#/components/responses/FunctionNotFound"
      "x-display-name": "Retry failed execution"
      "x-sdk-method": "retry"
  "/api/functions/projects/{projectId}/functions/{functionId}/rollback":
    "post":
      "tags":
        - "functions"
      "summary": "Rollback to previous version"
      "operationId": "functions.rollback"
      "description": "Rollback function code to a previous version. Version number is required."
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) that owns the function."
        - "name": "functionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Function ID (MongoDB ObjectId) to rollback."
      "requestBody":
        "required": true
        "description": "Version number (integer) to rollback to; use GET .../versions to list available versions."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "version"
              "properties":
                "version":
                  "type": "integer"
                  "description": "Version number to rollback to"
            "example":
              "version": 2
      "responses":
        "200":
          "description": "Function rolled back"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/FunctionResponse"
        "400":
          "description": "Version number is required"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "Function or version not found (exact backend message)."
          "$ref": "#/components/responses/FunctionNotFound"
      "x-display-name": "Rollback to previous version"
      "x-sdk-method": "rollback"
  "/api/functions/projects/{projectId}/functions/{functionId}/versions":
    "get":
      "tags":
        - "functions"
      "summary": "Get function versions"
      "operationId": "functions.getVersions"
      "description": "List all code versions for a function. Used for rollback."
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) that owns the function."
        - "name": "functionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Function ID (MongoDB ObjectId) to list versions for."
      "responses":
        "200":
          "description": "Function versions"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
                    "properties":
                      "versions":
                        "type": "array"
                        "items":
                          "type": "object"
                          "properties":
                            "_id":
                              "type": "string"
                            "code":
                              "type": "string"
                            "version":
                              "type": "integer"
                            "createdAt":
                              "type": "string"
                              "format": "date-time"
                            "createdBy":
                              "type": "string"
                            "comment":
                              "type": "string"
              "example":
                "success": true
                "data":
                  "versions":
                    - "_id": "65a1b2c3d4e5f6789012345c"
                      "version": 3
                      "comment": "Add validation"
                      "createdAt": "2024-01-15T12:00:00.000Z"
                    - "_id": "65a1b2c3d4e5f6789012345b"
                      "version": 2
                      "comment": "Fix bug"
                      "createdAt": "2024-01-15T11:00:00.000Z"
                    - "_id": "65a1b2c3d4e5f6789012345a"
                      "version": 1
                      "comment": "Initial version"
                      "createdAt": "2024-01-15T10:00:00.000Z"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "Function not found (exact backend message)."
          "$ref": "#/components/responses/FunctionNotFound"
      "x-display-name": "Get function versions"
      "x-sdk-method": "getVersions"
  "/api/functions/projects/{projectId}/functions/{functionId}/simulate":
    "post":
      "tags":
        - "functions"
      "summary": "Simulate trigger"
      "operationId": "functions.simulate"
      "description": "Test a function with simulated trigger context. Use to verify document, file, webhook, wallet, or cron payloads.

        Executes the function with the provided eventContext merged into the payload.\n"
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) that owns the function."
        - "name": "functionId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Function ID (MongoDB ObjectId) to simulate."
      "requestBody":
        "description": "Simulated trigger (type, event) and eventContext (document, file, webhook, wallet, message, or cron). Merged into the function payload for testing."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "properties":
                "trigger":
                  "type": "object"
                  "description": "Simulated trigger (type, event)"
                "eventContext":
                  "type": "object"
                  "description": "Simulated event context (document, file, webhook, wallet, message)"
                "payload":
                  "type": "object"
                  "description": "Additional payload"
            "examples":
              "documentCreate":
                "summary": "Simulate document create"
                "value":
                  "trigger":
                    "type": "document"
                    "event": "create"
                  "eventContext":
                    "document":
                      "_id": "685ae1210136e73fa1dcaf36"
                      "collectionId": "685ada8fd9416ac02f171abf"
                      "data":
                        "name": "John"
                        "email": "john@example.com"
              "webhookPayload":
                "summary": "Simulate webhook"
                "value":
                  "trigger":
                    "type": "webhook"
                    "event": "received"
                  "eventContext":
                    "webhook":
                      "headers":
                        "content-type": "application/json"
                      "body":
                        "event": "payment.completed"
                        "amount": 99.99
              "fileUploaded":
                "summary": "Simulate file uploaded event"
                "value":
                  "trigger":
                    "type": "file"
                    "event": "uploaded"
                  "eventContext":
                    "file":
                      "fileId": "file_abc123"
                      "bucket": "default"
                      "url": "https://cdn.example.com/project/default/file_abc123.jpg"
                      "originalName": "photo.jpg"
                      "mimeType": "image/jpeg"
                      "size": 345678
              "walletTransaction":
                "summary": "Simulate wallet transaction event"
                "value":
                  "trigger":
                    "type": "wallet"
                    "event": "tx"
                  "eventContext":
                    "wallet":
                      "walletId": "w_123"
                      "address": "0xabc..."
                      "chain": "ethereum"
                      "txHash": "0xdeadbeef..."
                      "transaction":
                        "amount": 0.75
                        "currency": "ETH"
              "cronRun":
                "summary": "Simulate cron schedule"
                "value":
                  "trigger":
                    "type": "cron"
                    "schedule": "daily"
                  "eventContext":
                    "cron":
                      "schedule": "daily"
                      "at": "2024-01-15T00:00:00.000Z"
              "messagingSent":
                "summary": "Simulate messaging event"
                "value":
                  "trigger":
                    "type": "messaging"
                    "event": "sent"
                  "eventContext":
                    "message":
                      "messageId": "msg_123"
                      "senderId": "user_123"
                      "chatId": "chat_456"
                      "content":
                        "text": "Hello"
      "responses":
        "200":
          "description": "Simulation result"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/FunctionExecutionResponse"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Simulate trigger"
      "x-sdk-method": "simulate"
  "/api/messaging/projects/{projectId}/messaging/push":
    "post":
      "tags":
        - "messaging"
      "summary": "Send push notification"
      "operationId": "messaging.sendPush"
      "description": "Send a push notification to one or more devices.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) for the messaging project."
      "requestBody":
        "required": true
        "description": "Device tokens, notification title/body, optional data payload and image URL."
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/PushNotificationRequest"
            "example":
              "tokens":
                - "device_token_123"
                - "device_token_456"
              "title": "New Notification"
              "body": "You have a new message"
              "data": {}
              "imageUrl": "https://example.com/image.jpg"
      "responses":
        "201":
          "description": "Push notification sent"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageSentResponse"
              "example":
                "success": true
                "data":
                  "_id": "65a1b2c3d4e5f6789012345c"
                  "type": "push"
                  "status": "sent"
                  "recipients": 2
                  "sentAt": "2024-01-15T10:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Send push notification"
      "x-sdk-method": "sendPush"
  "/api/messaging/projects/{projectId}/messaging/email":
    "post":
      "tags":
        - "messaging"
      "summary": "Send transactional email"
      "operationId": "messaging.sendEmail"
      "description": "Send a transactional email to one or more recipients. Supports HTML and plain text.

        Use for verification emails, password resets, notifications, and marketing. Attachments and templates can be configured per project.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) for the messaging project."
      "requestBody":
        "required": true
        "description": "Recipient(s), subject, HTML and/or plain text body; optional reply-to and attachments."
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/EmailRequest"
            "example":
              "to": "user@example.com"
              "subject": "Welcome to Mudbase"
              "html": "<h1>Welcome!</h1><p>Thank you for joining.</p>"
              "text": "Welcome! Thank you for joining."
      "responses":
        "201":
          "description": "Email sent"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageSentResponse"
              "example":
                "success": true
                "data":
                  "_id": "65a1b2c3d4e5f6789012345d"
                  "type": "email"
                  "status": "sent"
                  "to": "user@example.com"
                  "sentAt": "2024-01-15T10:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Send transactional email"
      "x-sdk-method": "sendEmail"
  "/api/messaging/projects/{projectId}/messaging/sms":
    "post":
      "tags":
        - "messaging"
      "summary": "Send SMS to one or more recipients (E.164 format)"
      "operationId": "messaging.sendSms"
      "description": "Send an SMS message to one or more phone numbers in E.164 format.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) for the messaging project."
      "requestBody":
        "required": true
        "description": "Recipient phone number(s), message body, and optional sender ID."
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/SMSRequest"
            "example":
              "to": "+1234567890"
              "message": "Your verification code is 123456"
              "from": "Mudbase"
      "responses":
        "201":
          "description": "SMS sent"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageSentResponse"
              "example":
                "success": true
                "data":
                  "_id": "65a1b2c3d4e5f6789012345f"
                  "type": "sms"
                  "to": "+1234567890"
                  "status": "sent"
                  "createdAt": "2024-01-15T10:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Send SMS to one or more recipients (E.164 format)"
      "x-sdk-method": "sendSms"
  "/api/messaging/projects/{projectId}/messaging/history":
    "get":
      "tags":
        - "messaging"
      "summary": "Get message history"
      "operationId": "messaging.getHistory"
      "description": "Get message history (push, email, SMS) with filtering and pagination.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) for the messaging project."
        - "name": "type"
          "in": "query"
          "schema":
            "type": "string"
            "enum":
              - "push"
              - "email"
              - "sms"
          "description": "Filter by message type (push, email, or sms)."
        - "name": "page"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 1
          "description": "Page number for pagination (1-based)."
        - "name": "limit"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 20
          "description": "Maximum number of messages per page."
        - "name": "status"
          "in": "query"
          "schema":
            "type": "string"
            "enum":
              - "sent"
              - "failed"
              - "pending"
          "description": "Filter by delivery status."
      "responses":
        "200":
          "description": "Message history"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageHistoryResponse"
              "example":
                "messages":
                  - "_id": "65a1b2c3d4e5f6789012345f"
                    "type": "email"
                    "to": "user@example.com"
                    "subject": "Welcome"
                    "status": "sent"
                    "createdAt": "2024-01-15T10:00:00.000Z"
                "total": 1
                "page": 1
                "limit": 20
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Get message history"
      "x-sdk-method": "getHistory"
  "/api/messaging/projects/{projectId}/messaging/stats":
    "get":
      "tags":
        - "messaging"
      "summary": "Get message statistics"
      "operationId": "messaging.getStats"
      "description": "Get messaging statistics including total messages, success rates, and breakdown by type (push, email, SMS).

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) for the messaging project."
        - "name": "startDate"
          "in": "query"
          "schema":
            "type": "string"
            "format": "date-time"
          "description": "Start of the date range for statistics (ISO 8601)."
        - "name": "endDate"
          "in": "query"
          "schema":
            "type": "string"
            "format": "date-time"
          "description": "End of the date range for statistics (ISO 8601)."
      "responses":
        "200":
          "description": "Message statistics"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageStatsResponse"
              "example":
                "stats":
                  "total": 1000
                  "sent": 950
                  "failed": 50
                  "byType":
                    "email": 600
                    "sms": 300
                    "push": 100
                "period": "month"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Get message statistics"
      "x-sdk-method": "getStats"
  "/api/usage/projects/{projectId}":
    "get":
      "tags":
        - "usage"
      "summary": "Get project usage"
      "operationId": "usage.getProject"
      "description": "Get usage statistics for a project (API calls, storage, bandwidth, database operations).

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) to get usage for."
        - "name": "period"
          "in": "query"
          "schema":
            "type": "string"
            "enum":
              - "day"
              - "week"
              - "month"
            "default": "month"
          "description": "Aggregation period for usage (day, week, or month)."
      "responses":
        "200":
          "description": "Project usage statistics"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/ProjectUsageStatsResponse"
              "example":
                "usage":
                  "apiCalls": 15000
                  "storage": 52428800
                  "bandwidth": 1073741824
                  "databaseReads": 5000
                  "databaseWrites": 2000
                "period": "month"
                "projectId": "685ad30be129932fbb7a1047"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Get project usage"
      "x-sdk-method": "getProject"
  "/api/usage/trends":
    "get":
      "tags":
        - "usage"
      "summary": "Get usage trends"
      "operationId": "usage.getTrends"
      "description": "Get usage trends over time for the authenticated organization or project.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "days"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 30
          "description": "Number of days of trend data to return (default 30)."
      "responses":
        "200":
          "description": "Usage trends"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/UsageTrendsResponse"
              "example":
                "trends":
                  - "date": "2024-01-01"
                    "apiCalls": 1000
                    "storage": 104857600
                  - "date": "2024-01-02"
                    "apiCalls": 1200
                    "storage": 104857600
                "days": 30
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Get usage trends"
      "x-sdk-method": "getTrends"
  "/api/search/projects/{projectId}/search":
    "get":
      "tags":
        - "search"
      "summary": "Full-text search"
      "operationId": "search.search"
      "description": "Perform full-text search across collections in a project.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) to search within."
        - "name": "q"
          "in": "query"
          "required": true
          "schema":
            "type": "string"
          "description": "Full-text search query string."
        - "name": "collections"
          "in": "query"
          "schema":
            "type": "string"
          "description": "Comma-separated collection slugs or IDs to limit search scope."
        - "name": "fields"
          "in": "query"
          "schema":
            "type": "string"
          "description": "Comma-separated field names to search or return in highlights."
        - "name": "limit"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 20
          "description": "Maximum number of results to return per page."
        - "name": "page"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 1
          "description": "Page number for pagination (1-based)."
      "responses":
        "200":
          "description": "Search results"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/SearchResponse"
              "example":
                "success": true
                "data":
                  "results":
                    - "collection": "users"
                      "item":
                        "_id": "685ae1210136e73fa1dcaf36"
                        "email": "john.doe@mudbase.dev"
                        "firstName": "John"
                        "lastName": "Doe"
                        "role": "developer"
                        "score": 0.95
                      "highlight":
                        "firstName": "<em>John</em>"
                        "lastName": "Doe"
                    - "collection": "users"
                      "item":
                        "_id": "685ae1210136e73fa1dcaf37"
                        "email": "jane.smith@mudbase.dev"
                        "firstName": "Jane"
                        "lastName": "Smith"
                        "role": "admin"
                        "score": 0.82
                      "highlight":
                        "firstName": "Jane"
                        "lastName": "Smith"
                  "pagination":
                    "page": 1
                    "limit": 20
                    "total": 2
                    "totalPages": 1
                  "query": "john"
                  "searchTime": 45
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Full-text search"
      "x-sdk-method": "search"
  "/api/search/projects/{projectId}/search/suggestions":
    "get":
      "tags":
        - "search"
      "summary": "Get search suggestions"
      "operationId": "search.getSuggestions"
      "description": "Get search query suggestions based on partial input.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "685ad30be129932fbb7a1047"
          "description": "Project ID (MongoDB ObjectId) to get suggestions for."
        - "name": "q"
          "in": "query"
          "required": true
          "schema":
            "type": "string"
            "minLength": 2
            "maxLength": 50
          "description": "Partial search query (min 2 characters, max 50); suggestions are based on past queries and indexed content."
        - "name": "limit"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 10
            "minimum": 1
            "maximum": 20
          "description": "Maximum number of suggestions to return (1–20)."
      "responses":
        "200":
          "description": "Search suggestions"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "suggestions":
                    "type": "array"
                    "items":
                      "type": "string"
              "example":
                "suggestions":
                  - "john doe"
                  - "john smith"
                  - "johnny"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Get search suggestions"
      "x-sdk-method": "getSuggestions"
  "/api/search/projects/{projectId}/search/analytics":
    "get":
      "tags":
        - "search"
      "summary": "Get search analytics"
      "operationId": "search.getAnalytics"
      "description": "Get search analytics including top queries, search volume, and performance metrics.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "685ad30be129932fbb7a1047"
          "description": "Project ID (MongoDB ObjectId) to get analytics for."
        - "name": "timeframe"
          "in": "query"
          "schema":
            "type": "string"
            "enum":
              - "1d"
              - "7d"
              - "30d"
            "default": "7d"
          "description": "Timeframe for analytics (1d, 7d, or 30d)."
      "responses":
        "200":
          "description": "Search analytics"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "totalSearches":
                    "type": "integer"
                  "topQueries":
                    "type": "array"
                    "items":
                      "type": "object"
                      "properties":
                        "query":
                          "type": "string"
                        "count":
                          "type": "integer"
                  "searchesByCollection":
                    "type": "object"
                  "averageResponseTime":
                    "type": "number"
              "example":
                "totalSearches": 1250
                "topQueries":
                  - "query": "john"
                    "count": 45
                  - "query": "user"
                    "count": 32
                "searchesByCollection":
                  "users": 800
                  "products": 450
                "averageResponseTime": 45.2
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Get search analytics"
      "x-sdk-method": "getAnalytics"
  "/api/wallet/non-custodial/register-address":
    "post":
      "tags":
        - "wallet"
      "summary": "Register a non-custodial wallet address"
      "operationId": "wallet.registerAddress"
      "description": "Register a public wallet address for balance monitoring, transaction indexing, and webhook notifications.

        Keys are never sent to the server; generation and signing happen client-side only. Supports EVM, UTXO, Solana, Tron, TON, Cardano, and other chains. Optionally provide derivation path and label for multi-address tracking.\n"
      "security":
        - "BearerToken": []
      "requestBody":
        "required": true
        "description": "Public address, chain identifier, and optional derivation path and label. projectId scopes the registration to a project."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "address"
                - "chain"
              "properties":
                "address":
                  "type": "string"
                  "description": "Public wallet address"
                  "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                "chain":
                  "type": "string"
                  "enum":
                    - "ethereum"
                    - "binance"
                    - "bsc"
                    - "polygon"
                    - "arbitrum"
                    - "optimism"
                    - "base"
                    - "avalanche"
                    - "celo"
                    - "bitcoin"
                    - "litecoin"
                    - "dogecoin"
                    - "solana"
                    - "tron"
                    - "ripple"
                    - "cardano"
                    - "ton"
                  "description": "Blockchain network (EVM, UTXO, or chain-specific). Use bsc or binance for BNB Smart Chain; avalanche for Avalanche C-Chain."
                "derivationPath":
                  "type": "string"
                  "description": "HD wallet derivation path (metadata only)"
                  "example": "m/44'/60'/0'/0/5"
                "label":
                  "type": "string"
                  "description": "Optional label for the address"
                  "example": "User Wallet 5"
                "projectId":
                  "type": "string"
                  "description": "Optional project ID"
            "examples":
              "ethereum":
                "summary": "Ethereum address registration"
                "value":
                  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                  "chain": "ethereum"
                  "derivationPath": "m/44'/60'/0'/0/5"
                  "label": "Main Ethereum Wallet"
              "bitcoin":
                "summary": "Bitcoin address registration"
                "value":
                  "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
                  "chain": "bitcoin"
                  "derivationPath": "m/44'/0'/0'/0/0"
                  "label": "Bitcoin Wallet"
              "binance":
                "summary": "Binance Smart Chain (BNB) address registration"
                "value":
                  "address": "0x8ba1f109551bD432803012645Hac136c22C929"
                  "chain": "binance"
                  "derivationPath": "m/44'/60'/0'/0/0"
                  "label": "BNB Wallet"
              "polygon":
                "summary": "Polygon network address registration"
                "value":
                  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                  "chain": "polygon"
                  "derivationPath": "m/44'/60'/0'/0/0"
                  "label": "Polygon Wallet"
              "celo":
                "summary": "Celo network address registration"
                "value":
                  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                  "chain": "celo"
                  "derivationPath": "m/44'/52752'/0'/0/0"
                  "label": "Celo Wallet"
              "arbitrum":
                "summary": "Arbitrum One address registration"
                "value":
                  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                  "chain": "arbitrum"
                  "derivationPath": "m/44'/60'/0'/0/0"
                  "label": "Arbitrum Wallet"
              "optimism":
                "summary": "Optimism mainnet address registration"
                "value":
                  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                  "chain": "optimism"
                  "derivationPath": "m/44'/60'/0'/0/0"
                  "label": "Optimism Wallet"
              "base":
                "summary": "Base mainnet address registration"
                "value":
                  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                  "chain": "base"
                  "derivationPath": "m/44'/60'/0'/0/0"
                  "label": "Base Wallet"
              "bsc":
                "summary": "BNB Smart Chain (bsc) address registration"
                "value":
                  "address": "0x8ba1f109551bD432803012645Hac136c22C929"
                  "chain": "bsc"
                  "derivationPath": "m/44'/60'/0'/0/0"
                  "label": "BSC Wallet"
              "avalanche":
                "summary": "Avalanche C-Chain address registration"
                "value":
                  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                  "chain": "avalanche"
                  "derivationPath": "m/44'/60'/0'/0/0"
                  "label": "Avalanche Wallet"
              "solana":
                "summary": "Solana address registration"
                "value":
                  "address": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"
                  "chain": "solana"
                  "derivationPath": "m/44'/501'/0'/0'"
                  "label": "Solana Wallet"
              "tron":
                "summary": "Tron (TRX) address registration"
                "value":
                  "address": "TQn9Y2khEsLMWTg2LFLu8e3XyqB8K8FJ7z"
                  "chain": "tron"
                  "derivationPath": "m/44'/195'/0'/0/0"
                  "label": "Tron Wallet"
              "litecoin":
                "summary": "Litecoin address registration"
                "value":
                  "address": "ltc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
                  "chain": "litecoin"
                  "derivationPath": "m/44'/2'/0'/0/0"
                  "label": "Litecoin Wallet"
              "ripple":
                "summary": "Ripple (XRP) address registration"
                "value":
                  "address": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH"
                  "chain": "ripple"
                  "derivationPath": "m/44'/144'/0'/0/0"
                  "label": "XRP Wallet"
              "cardano":
                "summary": "Cardano (ADA) address registration"
                "value":
                  "address": "addr1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
                  "chain": "cardano"
                  "derivationPath": "m/1852'/1815'/0'/0/0"
                  "label": "Cardano Wallet"
              "dogecoin":
                "summary": "Dogecoin address registration"
                "value":
                  "address": "D7Y55LdSqtcsAUxDkw6fzRHn7n7otQDd6Fc"
                  "chain": "dogecoin"
                  "derivationPath": "m/44'/3'/0'/0/0"
                  "label": "Dogecoin Wallet"
              "ton":
                "summary": "TON (The Open Network) address registration"
                "value":
                  "address": "EQD0vdSA_NcR8c6z0x1gWhgWhgWhgWhgWhgWhgWhgWhgW"
                  "chain": "ton"
                  "derivationPath": "m/44'/607'/0'/0'/0'"
                  "label": "TON Wallet"
      "responses":
        "201":
          "description": "Address registered successfully"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/NonCustodialAddressResponse"
              "example":
                "success": true
                "message": "Address registered successfully"
                "data":
                  "_id": "65a1b2c3d4e5f6789012345a"
                  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                  "chain": "ethereum"
                  "org": "685acbe0e129932fbb7a0fc3"
                  "project": "685ad30be129932fbb7a1047"
                  "derivationPath": "m/44'/60'/0'/0/5"
                  "label": "User Wallet 5"
                  "isActive": true
                  "registeredAt": "2026-01-22T10:00:00.000Z"
                  "lastSyncedAt": null
                  "createdAt": "2026-01-22T10:00:00.000Z"
                  "updatedAt": "2026-01-22T10:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
      "x-display-name": "Register a non-custodial wallet address"
      "x-sdk-method": "registerAddress"
  "/api/wallet/non-custodial/addresses":
    "get":
      "tags":
        - "wallet"
      "summary": "List registered non-custodial addresses"
      "description": "Returns all non-custodial addresses registered for the current project/organization. Optional filters by chain and projectId.

        Addresses must be registered via POST /api/wallet/non-custodial/register-address before use.\n"
      "operationId": "wallet.listAddresses"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "chain"
          "in": "query"
          "schema":
            "type": "string"
            "enum":
              - "ethereum"
              - "binance"
              - "bsc"
              - "polygon"
              - "arbitrum"
              - "optimism"
              - "base"
              - "avalanche"
              - "celo"
              - "bitcoin"
              - "litecoin"
              - "dogecoin"
              - "solana"
              - "tron"
              - "ripple"
              - "cardano"
              - "ton"
          "description": "Filter by chain (optional)"
        - "name": "projectId"
          "in": "query"
          "schema":
            "type": "string"
          "description": "Filter by project ID (optional)."
      "responses":
        "200":
          "description": "List of registered addresses"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "array"
                    "items":
                      "$ref": "#/components/schemas/NonCustodialAddress"
                  "count":
                    "type": "integer"
              "example":
                "success": true
                "data":
                  - "_id": "65a1b2c3d4e5f6789012345a"
                    "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                    "chain": "ethereum"
                    "label": "User Wallet 5"
                    "isActive": true
                    "registeredAt": "2026-01-22T10:00:00.000Z"
                "count": 1
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
      "x-display-name": "List registered non-custodial addresses"
      "x-sdk-method": "listAddresses"
  "/api/wallet/non-custodial/addresses/{addressId}":
    "get":
      "tags":
        - "wallet"
      "summary": "Get non-custodial address by ID"
      "description": "Returns metadata and status for a single registered non-custodial address (ID, address, chain, label, org, project, derivationPath, isActive, timestamps).\n"
      "operationId": "wallet.getAddress"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "addressId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Registered address ID (MongoDB ObjectId)."
      "responses":
        "200":
          "description": "Address details"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/NonCustodialAddressResponse"
              "example":
                "success": true
                "message": "Address retrieved successfully"
                "data":
                  "_id": "65a1b2c3d4e5f6789012345a"
                  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                  "chain": "ethereum"
                  "org": "685acbe0e129932fbb7a0fc3"
                  "project": "685ad30be129932fbb7a1047"
                  "derivationPath": "m/44'/60'/0'/0/5"
                  "label": "User Wallet 5"
                  "isActive": true
                  "registeredAt": "2026-01-22T10:00:00.000Z"
                  "lastSyncedAt": "2026-01-22T10:05:00.000Z"
                  "createdAt": "2026-01-22T10:00:00.000Z"
                  "updatedAt": "2026-01-22T10:00:00.000Z"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "404":
          "description": "Address not found (exact backend message)."
          "$ref": "#/components/responses/NotFound"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
      "x-display-name": "Get non-custodial address by ID"
      "x-sdk-method": "getAddress"
    "delete":
      "tags":
        - "wallet"
      "summary": "Delete (soft-delete) a non-custodial address"
      "description": "Soft-deletes a registered non-custodial address. The address is marked inactive and no longer used for broadcasts or balance/transaction queries.\n"
      "operationId": "wallet.deleteAddress"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "addressId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Registered address ID to delete."
      "responses":
        "200":
          "description": "Address deleted successfully"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "message":
                    "type": "string"
              "example":
                "success": true
                "message": "Address deleted successfully"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "404":
          "description": "Address not found (exact backend message)."
          "$ref": "#/components/responses/NotFound"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
      "x-display-name": "Delete (soft-delete) a non-custodial address"
      "x-sdk-method": "deleteAddress"
  "/api/wallet/non-custodial/addresses/{addressId}/balance":
    "get":
      "tags":
        - "wallet"
      "summary": "Get balance for a non-custodial address"
      "description": "Returns native token balance (confirmed, unconfirmed, total, currency) for a registered non-custodial address. Updated periodically from the chain.\n"
      "operationId": "wallet.getBalance"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "addressId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Registered address ID."
      "responses":
        "200":
          "description": "Balance information"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "$ref": "#/components/schemas/WalletBalance"
              "example":
                "success": true
                "data":
                  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                  "chain": "ethereum"
                  "confirmed": "1.5"
                  "unconfirmed": "0.0"
                  "total": "1.5"
                  "currency": "ETH"
                  "lastUpdated": "2026-01-22T10:05:00.000Z"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "404":
          "description": "Address not found (exact backend message)."
          "$ref": "#/components/responses/NotFound"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
      "x-display-name": "Get balance for a non-custodial address"
      "x-sdk-method": "getBalance"
  "/api/wallet/non-custodial/addresses/{addressId}/transactions":
    "get":
      "tags":
        - "wallet"
      "summary": "Get transaction history for a non-custodial address"
      "description": "Returns paginated transaction history for a registered non-custodial address (incoming/outgoing, status, confirmations, amounts).\n"
      "operationId": "wallet.getTransactions"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "addressId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Registered address ID."
        - "name": "limit"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 50
          "description": "Number of transactions per page."
        - "name": "page"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 1
          "description": "Page number (1-based)."
      "responses":
        "200":
          "description": "Transaction history"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "array"
                    "items":
                      "$ref": "#/components/schemas/WalletTransaction"
                  "pagination":
                    "type": "object"
                    "properties":
                      "page":
                        "type": "integer"
                      "limit":
                        "type": "integer"
                      "count":
                        "type": "integer"
                      "total":
                        "type": "integer"
                      "totalPages":
                        "type": "integer"
                      "hasNextPage":
                        "type": "boolean"
                      "hasPreviousPage":
                        "type": "boolean"
              "example":
                "success": true
                "data":
                  - "_id": "65a1b2c3d4e5f6789012345b"
                    "txHash": "0xabc123def4567890123456789012345678901234567890123456789012345678"
                    "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                    "chain": "ethereum"
                    "from": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                    "to": "0xdef4567890123456789012345678901234567890"
                    "amount": "0.1"
                    "currency": "ETH"
                    "status": "completed"
                    "mainTxStatus": "confirmed"
                    "confirmations": 12
                    "blockNumber": 12345678
                    "networkFee": "0.00021"
                    "mainTxConfirmedAt": "2026-01-22T10:00:00.000Z"
                    "tokenTransfers":
                      - "tokenAddress": "0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e"
                        "from": "0x1194d844f5c5a9adc488835e1f506dafbb579341"
                        "to": "0x000000000000000000000000000000000ce106a5"
                        "value": "80"
                        "formattedAmount": "0.000076"
                        "tokenSymbol": "USD₮"
                        "tokenDecimals": 6
                        "isIncoming": true
                    "createdAt": "2026-01-22T10:00:00.000Z"
                "pagination":
                  "page": 1
                  "limit": 50
                  "count": 1
                  "total": 100
                  "totalPages": 2
                  "hasNextPage": true
                  "hasPreviousPage": false
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "404":
          "description": "Address not found (exact backend message)."
          "$ref": "#/components/responses/NotFound"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
      "x-display-name": "Get transaction history for a non-custodial address"
      "x-sdk-method": "getTransactions"
  "/api/wallet/non-custodial/transactions/{txHash}":
    "get":
      "tags":
        - "wallet"
      "summary": "Get transaction by hash"
      "operationId": "wallet.getTransactionByHash"
      "description": "Returns a transaction by its hash. The **chain** query parameter is required

        because the same hash format can exist on different chains (e.g. 0x-style on EVM chains).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "txHash"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Transaction hash (e.g. 0x... for EVM, or block explorer format for UTXO)"
        - "name": "chain"
          "in": "query"
          "required": true
          "schema":
            "type": "string"
            "enum":
              - "ethereum"
              - "binance"
              - "polygon"
              - "celo"
              - "bitcoin"
              - "litecoin"
              - "solana"
              - "tron"
              - "ripple"
              - "cardano"
              - "dogecoin"
              - "ton"
          "description": "Chain the transaction belongs to (required for lookup)"
      "responses":
        "200":
          "description": "Transaction details"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "$ref": "#/components/schemas/WalletTransaction"
              "example":
                "success": true
                "data":
                  "_id": "65a1b2c3d4e5f6789012345b"
                  "txHash": "0xabc123def4567890123456789012345678901234567890123456789012345678"
                  "mainTxHash": "0xabc123def4567890123456789012345678901234567890123456789012345678"
                  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                  "chain": "ethereum"
                  "from": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                  "to": "0xdef4567890123456789012345678901234567890"
                  "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                  "toAddress": "0xdef4567890123456789012345678901234567890"
                  "amount": "0.1"
                  "currency": "ETH"
                  "type": "transfer"
                  "status": "completed"
                  "mainTxStatus": "confirmed"
                  "confirmations": 12
                  "blockNumber": 12345678
                  "blockHash": "0xdef7890123456789012345678901234567890123456789012345678901234567"
                  "networkFee": "0.00021"
                  "mainTxConfirmedAt": "2026-01-22T10:00:00.000Z"
                  "tokenTransfers":
                    - "tokenAddress": "0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e"
                      "from": "0x1194d844f5c5a9adc488835e1f506dafbb579341"
                      "to": "0x000000000000000000000000000000000ce106a5"
                      "value": "80"
                      "formattedAmount": "0.000076"
                      "tokenSymbol": "USD₮"
                      "tokenDecimals": 6
                      "isIncoming": true
                  "createdAt": "2026-01-22T10:00:00.000Z"
                  "updatedAt": "2026-01-22T10:00:00.000Z"
        "400":
          "description": "Bad Request - missing or invalid chain (add ?chain=ethereum)"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "error":
                    "type": "string"
              "example":
                "success": false
                "error": "Chain parameter is required. Add ?chain=ethereum (or binance, polygon, celo, bitcoin) to your request."
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "404":
          "description": "Transaction not found (exact backend message)."
          "$ref": "#/components/responses/NotFound"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
      "x-display-name": "Get transaction by hash"
      "x-sdk-method": "getTransactionByHash"
  "/api/wallet/non-custodial/broadcast":
    "post":
      "tags":
        - "wallet"
      "summary": "Broadcast a client-signed transaction"
      "operationId": "wallet.broadcastTransaction"
      "description": "Broadcast a transaction that has been signed client-side.

        The transaction must be fully signed before sending.

        The fromAddress must be registered and belong to your organization (POST /api/wallet/non-custodial/register-address).

        **Supported chains:** EVM (ethereum, polygon, arbitrum, optimism, base, bsc, binance, avalanche, celo), UTXO (bitcoin, litecoin, dogecoin), and chain-specific (tron, solana, ton, cardano). Use `binance` or `bsc` for BNB Smart Chain.

        **Testing with custodial:** You can create a wallet via POST /api/wallet/create, get its private key via GET /api/wallet/{walletId}/private-key, register that address with POST /api/wallet/non-custodial/register-address, then build a signed tx (using POST /api/wallet/estimate-network-fee or estimate-gas for fees) and broadcast it here to test the non-custodial flow end-to-end.\n"
      "security":
        - "BearerToken": []
      "requestBody":
        "required": true
        "description": "Chain, signed transaction (hex), and fromAddress (must be registered)."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "chain"
                - "signedTx"
                - "fromAddress"
              "properties":
                "chain":
                  "type": "string"
                  "enum":
                    - "ethereum"
                    - "polygon"
                    - "arbitrum"
                    - "optimism"
                    - "base"
                    - "bsc"
                    - "binance"
                    - "avalanche"
                    - "celo"
                    - "bitcoin"
                    - "litecoin"
                    - "dogecoin"
                    - "tron"
                    - "solana"
                    - "ton"
                    - "cardano"
                  "description": "Blockchain for broadcast (EVM, UTXO, or chain-specific)"
                "signedTx":
                  "type": "string"
                  "description": "Fully signed transaction (hex string)"
                  "example": "0x02f8..."
                "fromAddress":
                  "type": "string"
                  "description": "Address that signed the transaction (must be registered)"
                  "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
            "examples":
              "ethereum":
                "summary": "Ethereum (ETH)"
                "value":
                  "chain": "ethereum"
                  "signedTx": "0x02f87082012a80843b9aca0082520894def456789012345678901234567890123456789094742d35cc6634c0532925a3b844bc9e7595f0beb880de0b6b3a764000080c001a0..."
                  "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
              "polygon":
                "summary": "Polygon (MATIC)"
                "value":
                  "chain": "polygon"
                  "signedTx": "0x02f870818c80843b9aca0082520894def456789012345678901234567890123456789094742d35cc6634c0532925a3b844bc9e7595f0beb880de0b6b3a764000080c001a0..."
                  "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
              "arbitrum":
                "summary": "Arbitrum One (ETH)"
                "value":
                  "chain": "arbitrum"
                  "signedTx": "0x02f872820a6380843b9aca0082520894def456789012345678901234567890123456789094742d35cc6634c0532925a3b844bc9e7595f0beb880de0b6b3a764000080c001a0..."
                  "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
              "optimism":
                "summary": "Optimism (ETH)"
                "value":
                  "chain": "optimism"
                  "signedTx": "0x02f872820a0a80843b9aca0082520894def456789012345678901234567890123456789094742d35cc6634c0532925a3b844bc9e7595f0beb880de0b6b3a764000080c001a0..."
                  "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
              "base":
                "summary": "Base (ETH)"
                "value":
                  "chain": "base"
                  "signedTx": "0x02f87282021180843b9aca0082520894def456789012345678901234567890123456789094742d35cc6634c0532925a3b844bc9e7595f0beb880de0b6b3a764000080c001a0..."
                  "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
              "bsc":
                "summary": "BNB Smart Chain (BNB)"
                "value":
                  "chain": "bsc"
                  "signedTx": "0x02f87082013880843b9aca0082520894def456789012345678901234567890123456789094742d35cc6634c0532925a3b844bc9e7595f0beb880de0b6b3a764000080c001a0..."
                  "fromAddress": "0x8ba1f109551bD432803012645Hac136c22C929"
              "binance":
                "summary": "Binance Smart Chain (BNB) — alias for bsc"
                "value":
                  "chain": "binance"
                  "signedTx": "0x02f87082013880843b9aca0082520894def456789012345678901234567890123456789094742d35cc6634c0532925a3b844bc9e7595f0beb880de0b6b3a764000080c001a0..."
                  "fromAddress": "0x8ba1f109551bD432803012645Hac136c22C929"
              "avalanche":
                "summary": "Avalanche C-Chain (AVAX)"
                "value":
                  "chain": "avalanche"
                  "signedTx": "0x02f872820a8680843b9aca0082520894def456789012345678901234567890123456789094742d35cc6634c0532925a3b844bc9e7595f0beb880de0b6b3a764000080c001a0..."
                  "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
              "celo":
                "summary": "Celo (CELO)"
                "value":
                  "chain": "celo"
                  "signedTx": "0x02f870820a6c80843b9aca0082520894def456789012345678901234567890123456789094742d35cc6634c0532925a3b844bc9e7595f0beb880de0b6b3a764000080c001a0..."
                  "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
              "bitcoin":
                "summary": "Bitcoin (BTC)"
                "value":
                  "chain": "bitcoin"
                  "signedTx": "0200000001a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef12000000006a47304402207f..."
                  "fromAddress": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
              "litecoin":
                "summary": "Litecoin (LTC)"
                "value":
                  "chain": "litecoin"
                  "signedTx": "0200000001a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef12000000006a47304402207f..."
                  "fromAddress": "ltc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
              "dogecoin":
                "summary": "Dogecoin (DOGE)"
                "value":
                  "chain": "dogecoin"
                  "signedTx": "0200000001a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef12000000006a47304402207f..."
                  "fromAddress": "D7Y55LdSqtcsAUxDkw6fzRHn7n7otQDd6Fc"
              "tron":
                "summary": "Tron (TRX)"
                "value":
                  "chain": "tron"
                  "signedTx": "0a0208012208..."
                  "fromAddress": "TQn9Y2khEsLMWTg2LFLu8e3XyqB8K8FJ7z"
              "solana":
                "summary": "Solana (SOL)"
                "value":
                  "chain": "solana"
                  "signedTx": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAAn2tR3f..."
                  "fromAddress": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"
              "ton":
                "summary": "TON (TON)"
                "value":
                  "chain": "ton"
                  "signedTx": "te6cckEBAQEAKgABAU..."
                  "fromAddress": "EQD0vdSA_NcR8c6z0x1gWhgWhgWhgWhgWhgWhgWhgWhgW"
              "cardano":
                "summary": "Cardano (ADA)"
                "value":
                  "chain": "cardano"
                  "signedTx": "84a40081825820..."
                  "fromAddress": "addr1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
      "responses":
        "200":
          "description": "Transaction broadcast successfully"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "message":
                    "type": "string"
                  "data":
                    "type": "object"
                    "properties":
                      "txHash":
                        "type": "string"
                      "chain":
                        "type": "string"
                      "fromAddress":
                        "type": "string"
                      "currency":
                        "type": "string"
                        "description": "Native currency for the chain (ETH, BNB, MATIC, etc.)"
              "examples":
                "ethereum":
                  "summary": "Ethereum (ETH)"
                  "value":
                    "success": true
                    "message": "Transaction broadcast successfully"
                    "data":
                      "txHash": "0xabc123def4567890123456789012345678901234567890123456789012345678"
                      "chain": "ethereum"
                      "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                      "currency": "ETH"
                "polygon":
                  "summary": "Polygon (MATIC)"
                  "value":
                    "success": true
                    "message": "Transaction broadcast successfully"
                    "data":
                      "txHash": "0xdef4567890123456789012345678901234567890123456789012345678901234"
                      "chain": "polygon"
                      "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                      "currency": "MATIC"
                "arbitrum":
                  "summary": "Arbitrum One (ETH)"
                  "value":
                    "success": true
                    "message": "Transaction broadcast successfully"
                    "data":
                      "txHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef12"
                      "chain": "arbitrum"
                      "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                      "currency": "ETH"
                "optimism":
                  "summary": "Optimism (ETH)"
                  "value":
                    "success": true
                    "message": "Transaction broadcast successfully"
                    "data":
                      "txHash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
                      "chain": "optimism"
                      "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                      "currency": "ETH"
                "base":
                  "summary": "Base (ETH)"
                  "value":
                    "success": true
                    "message": "Transaction broadcast successfully"
                    "data":
                      "txHash": "0xfedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321"
                      "chain": "base"
                      "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                      "currency": "ETH"
                "bsc":
                  "summary": "BNB Smart Chain (BNB)"
                  "value":
                    "success": true
                    "message": "Transaction broadcast successfully"
                    "data":
                      "txHash": "0x9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba"
                      "chain": "bsc"
                      "fromAddress": "0x8ba1f109551bD432803012645Hac136c22C929"
                      "currency": "BNB"
                "avalanche":
                  "summary": "Avalanche C-Chain (AVAX)"
                  "value":
                    "success": true
                    "message": "Transaction broadcast successfully"
                    "data":
                      "txHash": "0xabcd1234ef567890abcd1234ef567890abcd1234ef567890abcd1234ef567890"
                      "chain": "avalanche"
                      "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                      "currency": "AVAX"
                "celo":
                  "summary": "Celo (CELO)"
                  "value":
                    "success": true
                    "message": "Transaction broadcast successfully"
                    "data":
                      "txHash": "0x567890abcd1234567890abcd1234567890abcd1234567890abcd1234567890ab"
                      "chain": "celo"
                      "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                      "currency": "CELO"
                "bitcoin":
                  "summary": "Bitcoin (BTC)"
                  "value":
                    "success": true
                    "message": "Transaction broadcast successfully"
                    "data":
                      "txHash": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef12"
                      "chain": "bitcoin"
                      "fromAddress": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
                      "currency": "BTC"
                "litecoin":
                  "summary": "Litecoin (LTC)"
                  "value":
                    "success": true
                    "message": "Transaction broadcast successfully"
                    "data":
                      "txHash": "b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456"
                      "chain": "litecoin"
                      "fromAddress": "ltc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
                      "currency": "LTC"
                "dogecoin":
                  "summary": "Dogecoin (DOGE)"
                  "value":
                    "success": true
                    "message": "Transaction broadcast successfully"
                    "data":
                      "txHash": "c3d4e5f6789012345678901234567890abcdef1234567890abcdef12345678"
                      "chain": "dogecoin"
                      "fromAddress": "D7Y55LdSqtcsAUxDkw6fzRHn7n7otQDd6Fc"
                      "currency": "DOGE"
                "tron":
                  "summary": "Tron (TRX)"
                  "value":
                    "success": true
                    "message": "Transaction broadcast successfully"
                    "data":
                      "txHash": "d4e5f6789012345678901234567890abcdef1234567890abcdef1234567890"
                      "chain": "tron"
                      "fromAddress": "TQn9Y2khEsLMWTg2LFLu8e3XyqB8K8FJ7z"
                      "currency": "TRX"
                "solana":
                  "summary": "Solana (SOL)"
                  "value":
                    "success": true
                    "message": "Transaction broadcast successfully"
                    "data":
                      "txHash": "5VERv8NMvzbJMEkV8xnrLkEaWRtSy9LN7ezS4qc3ws3DyPDKyd2Rdk4SxHpR2qDn2f2f2f2f2f2f2f2f2f2f2f"
                      "chain": "solana"
                      "fromAddress": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"
                      "currency": "SOL"
                "ton":
                  "summary": "TON (TON)"
                  "value":
                    "success": true
                    "message": "Transaction broadcast successfully"
                    "data":
                      "txHash": "e5f6789012345678901234567890abcdef1234567890abcdef1234567890abcd"
                      "chain": "ton"
                      "fromAddress": "EQD0vdSA_NcR8c6z0x1gWhgWhgWhgWhgWhgWhgWhgWhgW"
                      "currency": "TON"
                "cardano":
                  "summary": "Cardano (ADA)"
                  "value":
                    "success": true
                    "message": "Transaction broadcast successfully"
                    "data":
                      "txHash": "f6789012345678901234567890abcdef1234567890abcdef1234567890abcdef"
                      "chain": "cardano"
                      "fromAddress": "addr1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
                      "currency": "ADA"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
      "x-display-name": "Broadcast a client-signed transaction"
      "x-sdk-method": "broadcastTransaction"
  "/api/wallet/non-custodial/speed-up":
    "post":
      "tags":
        - "wallet"
      "summary": "Get replacement tx params for speed-up (stuck EVM tx)"
      "operationId": "wallet.getSpeedUpParams"
      "description": "Returns **replacement transaction params** for a stuck EVM transaction (same nonce, same to/value/data, higher gas). Client signs the replacement and broadcasts via POST /api/wallet/non-custodial/broadcast. Address must be registered for your organization. Use when a tx has been pending >5 min (stuck). EVM chains only.\n"
      "security":
        - "BearerToken": []
      "requestBody":
        "required": true
        "description": "Stuck transaction identifier (txId or txHash) and EVM chain."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "chain"
              "properties":
                "txId":
                  "type": "string"
                  "description": "WalletTransaction _id (MongoDB ObjectId)"
                "txHash":
                  "type": "string"
                  "description": "mainTxHash or txHash of the stuck transaction"
                "chain":
                  "type": "string"
                  "enum":
                    - "ethereum"
                    - "polygon"
                    - "arbitrum"
                    - "optimism"
                    - "base"
                    - "bsc"
                    - "binance"
                    - "avalanche"
                    - "celo"
                  "description": "EVM chain (speed-up is EVM only)"
            "example":
              "txHash": "0xabc123..."
              "chain": "ethereum"
      "responses":
        "200":
          "description": "Replacement tx params (client signs and broadcasts via /broadcast)"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
                    "properties":
                      "chainId":
                        "type": "integer"
                      "from":
                        "type": "string"
                      "nonce":
                        "type": "integer"
                      "to":
                        "type": "string"
                      "value":
                        "type": "string"
                      "data":
                        "type": "string"
                      "gasLimit":
                        "type": "string"
                      "maxFeePerGas":
                        "type": "string"
                      "maxPriorityFeePerGas":
                        "type": "string"
                      "gasPrice":
                        "type": "string"
                        "description": "Legacy; use when EIP-1559 not used"
              "example":
                "success": true
                "data":
                  "chainId": 1
                  "from": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                  "nonce": 7
                  "to": "0xdef4567890123456789012345678901234567890"
                  "value": "1000000000000000000"
                  "data": "0x"
                  "gasLimit": "21000"
                  "maxFeePerGas": "36000000000"
                  "maxPriorityFeePerGas": "2000000000"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "Transaction or address not found (exact backend message)."
          "$ref": "#/components/responses/NotFound"
      "x-display-name": "Get replacement tx params for speed-up (stuck EVM tx)"
      "x-sdk-method": "getSpeedUpParams"
  "/api/wallet/non-custodial/cancel":
    "post":
      "tags":
        - "wallet"
      "summary": "Get replacement tx params for cancel (stuck EVM tx)"
      "operationId": "wallet.getCancelParams"
      "description": "Returns **replacement transaction params** to cancel a stuck EVM transaction (same nonce, to=self, value=0, data=0x, higher gas). Client signs and broadcasts via POST /api/wallet/non-custodial/broadcast. Address must be registered for your organization. EVM chains only.\n"
      "security":
        - "BearerToken": []
      "requestBody":
        "required": true
        "description": "Stuck transaction identifier (txId or txHash) and EVM chain for cancel."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "chain"
              "properties":
                "txId":
                  "type": "string"
                  "description": "WalletTransaction _id"
                "txHash":
                  "type": "string"
                  "description": "mainTxHash or txHash of the stuck transaction"
                "chain":
                  "type": "string"
                  "enum":
                    - "ethereum"
                    - "polygon"
                    - "arbitrum"
                    - "optimism"
                    - "base"
                    - "bsc"
                    - "binance"
                    - "avalanche"
                    - "celo"
            "example":
              "txHash": "0xabc123..."
              "chain": "ethereum"
      "responses":
        "200":
          "description": "Cancel tx params (client signs and broadcasts via /broadcast)"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
                    "properties":
                      "chainId":
                        "type": "integer"
                      "from":
                        "type": "string"
                      "nonce":
                        "type": "integer"
                      "to":
                        "type": "string"
                        "description": "Same as from (self)"
                      "value":
                        "type": "string"
                        "description": "0"
                      "data":
                        "type": "string"
                        "description": "0x"
                      "gasLimit":
                        "type": "string"
                      "maxFeePerGas":
                        "type": "string"
                      "maxPriorityFeePerGas":
                        "type": "string"
                      "gasPrice":
                        "type": "string"
              "example":
                "success": true
                "data":
                  "chainId": 1
                  "from": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                  "nonce": 7
                  "to": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                  "value": "0"
                  "data": "0x"
                  "gasLimit": "21000"
                  "maxFeePerGas": "36000000000"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "Transaction or address not found (exact backend message)."
          "$ref": "#/components/responses/NotFound"
      "x-display-name": "Get replacement tx params for cancel (stuck EVM tx)"
      "x-sdk-method": "getCancelParams"
  "/api/wallet/non-custodial/estimate-gas":
    "post":
      "tags":
        - "wallet"
      "summary": "Estimate network fee from blockchain (all supported chains; not controlled by Mudbase)"
      "operationId": "wallet.estimateGas"
      "description": "**Network fee (from blockchain only).** Returns network fee **estimated directly from the blockchain** via RPC or fee APIs. **Not controlled by Mudbase.** Both POST /api/wallet/estimate-network-fee (or calculate-fee) and this endpoint return network fee only; use either for gas/fee display. This endpoint is chain-oriented and supports full transaction shape for EVM.

        **EVM chains:** ethereum, polygon, arbitrum, optimism, base, bsc, binance, avalanche, celo — require `transaction` (from, and to/value or tokenAddress/amount). Response includes gasLimit, gasPrice, networkFee, estimatedTime, currency.

        **Non-EVM chains:** bitcoin, litecoin, dogecoin, solana, tron, ton, cardano — only `chain` is required; `transaction` is optional/ignored. Returns networkFee, estimatedTime, currency (and e.g. satPerVb for UTXO). See docs/FEE_ARCHITECTURE.md. Results cached 15s.\n"
      "security":
        - "BearerToken": []
      "requestBody":
        "required": true
        "description": "Chain and optional transaction shape (required for EVM). Returns network fee from blockchain."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "chain"
              "properties":
                "chain":
                  "type": "string"
                  "enum":
                    - "ethereum"
                    - "binance"
                    - "bsc"
                    - "polygon"
                    - "arbitrum"
                    - "optimism"
                    - "base"
                    - "avalanche"
                    - "celo"
                    - "bitcoin"
                    - "litecoin"
                    - "dogecoin"
                    - "solana"
                    - "tron"
                    - "ton"
                    - "cardano"
                  "description": "Chain id. For EVM, transaction is required. For non-EVM (UTXO, Solana, Tron, TON, Cardano) only chain is needed."
                "transaction":
                  "type": "object"
                  "description": "Required for EVM chains. Optional for non-EVM (ignored). Supports 1) Token transfer { from, tokenAddress, to, amount }, 2) Native transfer { from, to, value }, 3) Raw { from, to, value, data }.\n"
                  "required":
                    - "from"
                  "properties":
                    "from":
                      "type": "string"
                      "description": "Sender address"
                      "example": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
                    "to":
                      "type": "string"
                      "description": "For native transfers: recipient address.

                        For token transfers: recipient address (tokenAddress must be provided separately).

                        For raw format: contract or recipient address.\n"
                      "example": "0x53d284357ec70cE289D6D64134DfAc8E511c8a3D"
                    "value":
                      "type": "string"
                      "description": "Amount in native currency (ETH/BNB/MATIC).

                        Can be provided as decimal string (e.g., \"1.0\") or wei string.

                        Required for native transfers.\n"
                      "example": "1.0"
                    "data":
                      "type": "string"
                      "description": "Raw transaction data (hex string starting with 0x).

                        Used for raw format or contract calls.

                        For token transfers, this is auto-generated from tokenAddress, to, and amount.\n"
                      "example": "0xa9059cbb000000000000000000000000..."
                    "tokenAddress":
                      "type": "string"
                      "description": "Token contract address (for token transfers).

                        When provided with 'amount', automatically encodes the transfer.\n"
                      "example": "0xdAC17F958D2ee523a2206206994597C13D831ec7"
                    "amount":
                      "type": "string"
                      "description": "Token amount in human-readable format (e.g., \"1.0\" for 1 token).

                        Used with tokenAddress for user-friendly token transfers.

                        Automatically converted to token units based on token decimals.\n"
                      "example": "1.0"
            "examples":
              "ethereum":
                "summary": "Ethereum (ETH) — native transfer"
                "value":
                  "chain": "ethereum"
                  "transaction":
                    "from": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
                    "to": "0x53d284357ec70cE289D6D64134DfAc8E511c8a3D"
                    "value": "1.0"
              "polygon":
                "summary": "Polygon (MATIC) — native transfer"
                "value":
                  "chain": "polygon"
                  "transaction":
                    "from": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
                    "to": "0x53d284357ec70cE289D6D64134DfAc8E511c8a3D"
                    "value": "1.0"
              "arbitrum":
                "summary": "Arbitrum One (ETH) — native transfer"
                "value":
                  "chain": "arbitrum"
                  "transaction":
                    "from": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
                    "to": "0x53d284357ec70cE289D6D64134DfAc8E511c8a3D"
                    "value": "0.1"
              "optimism":
                "summary": "Optimism (ETH) — native transfer"
                "value":
                  "chain": "optimism"
                  "transaction":
                    "from": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
                    "to": "0x53d284357ec70cE289D6D64134DfAc8E511c8a3D"
                    "value": "0.1"
              "base":
                "summary": "Base (ETH) — native transfer"
                "value":
                  "chain": "base"
                  "transaction":
                    "from": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
                    "to": "0x53d284357ec70cE289D6D64134DfAc8E511c8a3D"
                    "value": "0.1"
              "bsc":
                "summary": "BNB Smart Chain (BNB) — native transfer"
                "value":
                  "chain": "bsc"
                  "transaction":
                    "from": "0x8ba1f109551bD432803012645Hac136c22C929"
                    "to": "0x53d284357ec70cE289D6D64134DfAc8E511c8a3D"
                    "value": "0.5"
              "binance":
                "summary": "Binance Smart Chain (BNB) — alias for bsc"
                "value":
                  "chain": "binance"
                  "transaction":
                    "from": "0x8ba1f109551bD432803012645Hac136c22C929"
                    "to": "0x53d284357ec70cE289D6D64134DfAc8E511c8a3D"
                    "value": "0.5"
              "avalanche":
                "summary": "Avalanche C-Chain (AVAX) — native transfer"
                "value":
                  "chain": "avalanche"
                  "transaction":
                    "from": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
                    "to": "0x53d284357ec70cE289D6D64134DfAc8E511c8a3D"
                    "value": "1.0"
              "celo":
                "summary": "Celo (CELO) — native transfer"
                "value":
                  "chain": "celo"
                  "transaction":
                    "from": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
                    "to": "0x53d284357ec70cE289D6D64134DfAc8E511c8a3D"
                    "value": "1.0"
              "ethereumToken":
                "summary": "Ethereum (ETH) — ERC-20 token transfer"
                "value":
                  "chain": "ethereum"
                  "transaction":
                    "from": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
                    "tokenAddress": "0xdAC17F958D2ee523a2206206994597C13D831ec7"
                    "to": "0x53d284357ec70cE289D6D64134DfAc8E511c8a3D"
                    "amount": "1.0"
              "rawFormat":
                "summary": "Ethereum (ETH) — raw hex data"
                "value":
                  "chain": "ethereum"
                  "transaction":
                    "from": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
                    "to": "0xdAC17F958D2ee523a2206206994597C13D831ec7"
                    "value": "0"
                    "data": "0xa9059cbb00000000000000000000000053d284357ec70ce289d6d64134dfac8e511c8a3d00000000000000000000000000000000000000000000000000000000000f4240"
              "bitcoin":
                "summary": "Bitcoin (BTC) — chain only, no transaction"
                "value":
                  "chain": "bitcoin"
              "litecoin":
                "summary": "Litecoin (LTC) — chain only"
                "value":
                  "chain": "litecoin"
              "dogecoin":
                "summary": "Dogecoin (DOGE) — chain only"
                "value":
                  "chain": "dogecoin"
              "solana":
                "summary": "Solana (SOL) — chain only"
                "value":
                  "chain": "solana"
              "tron":
                "summary": "Tron (TRX) — chain only"
                "value":
                  "chain": "tron"
              "ton":
                "summary": "TON — chain only"
                "value":
                  "chain": "ton"
              "cardano":
                "summary": "Cardano (ADA) — chain only"
                "value":
                  "chain": "cardano"
      "responses":
        "200":
          "description": "Network fee from blockchain RPC (not from Mudbase logic)"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                    "example": true
                  "data":
                    "type": "object"
                    "properties":
                      "chain":
                        "type": "string"
                        "description": "Chain id (e.g. bsc, ethereum, bitcoin)"
                      "gasLimit":
                        "type": "string"
                        "description": "(EVM only) Estimated gas limit from RPC eth_estimateGas"
                        "example": "21000"
                      "gasPrice":
                        "type": "string"
                        "description": "(EVM only) Gas price in wei"
                        "example": "3000000000"
                      "gasPriceGwei":
                        "type": "number"
                        "description": "(EVM only) Gas price in Gwei"
                        "example": 3
                      "estimatedCost":
                        "type": "string"
                        "description": "(EVM only) Total cost in wei (gasLimit * gasPrice)"
                        "example": "63000000000000"
                      "networkFee":
                        "type": "string"
                        "description": "Human-readable network fee from blockchain (e.g. \"0.00063 ETH\", \"0.00001 BTC\")"
                        "example": "0.00063 ETH"
                      "estimatedTime":
                        "type": "string"
                        "description": "Estimated confirmation time when available"
                        "example": "15 seconds"
                      "currency":
                        "type": "string"
                        "description": "Native currency for the chain (ETH, BNB, MATIC, BTC, SOL, TRX, etc.)"
                      "satPerVb":
                        "type": "integer"
                        "description": "(UTXO only) Satoshis per virtual byte"
                      "feeSat":
                        "type": "integer"
                        "description": "(UTXO only) Estimated fee in satoshis"
                      "lamports":
                        "type": "integer"
                        "description": "(Solana only) Fee in lamports"
              "examples":
                "ethereum":
                  "summary": "Ethereum (ETH) — from RPC"
                  "value":
                    "success": true
                    "data":
                      "chain": "ethereum"
                      "gasLimit": "21000"
                      "gasPrice": "30000000000"
                      "gasPriceGwei": 30
                      "estimatedCost": "630000000000000"
                      "networkFee": "0.00063 ETH"
                      "estimatedTime": "15 seconds"
                      "currency": "ETH"
                "polygon":
                  "summary": "Polygon (MATIC)"
                  "value":
                    "success": true
                    "data":
                      "chain": "polygon"
                      "gasLimit": "21000"
                      "gasPrice": "50000000000"
                      "gasPriceGwei": 50
                      "estimatedCost": "1050000000000000"
                      "networkFee": "0.00105 MATIC"
                      "estimatedTime": "15 seconds"
                      "currency": "MATIC"
                "arbitrum":
                  "summary": "Arbitrum One (ETH)"
                  "value":
                    "success": true
                    "data":
                      "chain": "arbitrum"
                      "gasLimit": "21000"
                      "gasPrice": "100000000"
                      "gasPriceGwei": 0.1
                      "estimatedCost": "2100000000000"
                      "networkFee": "0.0000021 ETH"
                      "estimatedTime": "15 seconds"
                      "currency": "ETH"
                "optimism":
                  "summary": "Optimism (ETH)"
                  "value":
                    "success": true
                    "data":
                      "chain": "optimism"
                      "gasLimit": "21000"
                      "gasPrice": "1000000"
                      "gasPriceGwei": 0.001
                      "estimatedCost": "21000000000"
                      "networkFee": "0.000000021 ETH"
                      "estimatedTime": "15 seconds"
                      "currency": "ETH"
                "base":
                  "summary": "Base (ETH)"
                  "value":
                    "success": true
                    "data":
                      "chain": "base"
                      "gasLimit": "21000"
                      "gasPrice": "1000000000"
                      "gasPriceGwei": 0.001
                      "estimatedCost": "21000000000000"
                      "networkFee": "0.000021 ETH"
                      "estimatedTime": "15 seconds"
                      "currency": "ETH"
                "bsc":
                  "summary": "BNB Smart Chain (BNB)"
                  "value":
                    "success": true
                    "data":
                      "chain": "bsc"
                      "gasLimit": "21000"
                      "gasPrice": "5000000000"
                      "gasPriceGwei": 5
                      "estimatedCost": "105000000000000"
                      "networkFee": "0.000105 BNB"
                      "estimatedTime": "15 seconds"
                      "currency": "BNB"
                "avalanche":
                  "summary": "Avalanche C-Chain (AVAX)"
                  "value":
                    "success": true
                    "data":
                      "chain": "avalanche"
                      "gasLimit": "21000"
                      "gasPrice": "25000000000"
                      "gasPriceGwei": 25
                      "estimatedCost": "525000000000000"
                      "networkFee": "0.000525 AVAX"
                      "estimatedTime": "15 seconds"
                      "currency": "AVAX"
                "celo":
                  "summary": "Celo (CELO)"
                  "value":
                    "success": true
                    "data":
                      "chain": "celo"
                      "gasLimit": "21000"
                      "gasPrice": "1000000000"
                      "gasPriceGwei": 1
                      "estimatedCost": "21000000000000"
                      "networkFee": "0.000021 CELO"
                      "estimatedTime": "15 seconds"
                      "currency": "CELO"
                "bitcoin":
                  "summary": "Bitcoin (BTC) — non-EVM"
                  "value":
                    "success": true
                    "data":
                      "chain": "bitcoin"
                      "networkFee": "0.00002500 BTC"
                      "estimatedTime": "10–30 minutes"
                      "satPerVb": 15
                      "feeSat": 3750
                "solana":
                  "summary": "Solana (SOL) — non-EVM"
                  "value":
                    "success": true
                    "data":
                      "chain": "solana"
                      "networkFee": "0.000005 SOL"
                      "lamports": 5000
                      "estimatedTime": "15 seconds"
                      "currency": "SOL"
                "tron":
                  "summary": "Tron (TRX) — non-EVM"
                  "value":
                    "success": true
                    "data":
                      "chain": "tron"
                      "networkFee": "1 TRX"
                      "estimatedTime": "3 seconds"
                      "currency": "TRX"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
      "x-display-name": "Estimate network fee from blockchain (all supported chains; not controlled by Mudbase)"
      "x-sdk-method": "estimateGas"
  "/api/wallet/non-custodial/webhooks":
    "post":
      "tags":
        - "wallet"
      "summary": "Create a wallet webhook"
      "description": "Register a webhook URL to receive wallet events (balance updates, transaction confirmed/failed/detected/broadcast, token balance, address created/deactivated). Optional filters by addresses and chains.\n"
      "operationId": "wallet.createWebhook"
      "security":
        - "BearerToken": []
      "requestBody":
        "required": true
        "description": "Webhook URL, events array, optional secret and filters (addresses, chains, projectId)."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "url"
                - "events"
              "properties":
                "url":
                  "type": "string"
                  "format": "uri"
                  "example": "https://your-app.com/webhooks/wallet"
                "events":
                  "type": "array"
                  "items":
                    "type": "string"
                    "enum":
                      - "wallet.balance.updated"
                      - "wallet.transaction.confirmed"
                      - "wallet.transaction.failed"
                      - "wallet.transaction.detected"
                      - "wallet.transaction.broadcast"
                      - "wallet.token.balance.updated"
                      - "wallet.address.created"
                      - "wallet.address.deactivated"
                  "example":
                    - "wallet.balance.updated"
                    - "wallet.transaction.confirmed"
                "secret":
                  "type": "string"
                  "description": "Optional webhook secret for HMAC signing"
                  "example": "whsec_abc123xyz789"
                "filters":
                  "type": "object"
                  "properties":
                    "addresses":
                      "type": "array"
                      "items":
                        "type": "string"
                      "description": "Filter by address IDs (optional)"
                      "example":
                        - "65a1b2c3d4e5f6789012345a"
                    "chains":
                      "type": "array"
                      "items":
                        "type": "string"
                        "enum":
                          - "ethereum"
                          - "binance"
                          - "bsc"
                          - "polygon"
                          - "arbitrum"
                          - "optimism"
                          - "base"
                          - "avalanche"
                          - "celo"
                          - "bitcoin"
                          - "litecoin"
                          - "dogecoin"
                          - "solana"
                          - "tron"
                          - "ripple"
                          - "cardano"
                          - "ton"
                      "description": "Filter by chains (optional)"
                      "example":
                        - "ethereum"
                        - "bitcoin"
                "projectId":
                  "type": "string"
                  "description": "Optional project ID"
                  "example": "685ad30be129932fbb7a1047"
            "examples":
              "allEvents":
                "summary": "Webhook for all wallet events"
                "value":
                  "url": "https://your-app.com/webhooks/wallet"
                  "events":
                    - "wallet.balance.updated"
                    - "wallet.transaction.confirmed"
                    - "wallet.transaction.failed"
                  "secret": "whsec_abc123xyz789"
              "filtered":
                "summary": "Filtered webhook for specific addresses"
                "value":
                  "url": "https://your-app.com/webhooks/wallet-filtered"
                  "events":
                    - "wallet.balance.updated"
                  "filters":
                    "addresses":
                      - "65a1b2c3d4e5f6789012345a"
                    "chains":
                      - "ethereum"
      "responses":
        "201":
          "description": "Webhook created successfully"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "message":
                    "type": "string"
                  "data":
                    "$ref": "#/components/schemas/WalletWebhook"
              "example":
                "success": true
                "message": "Webhook created successfully"
                "data":
                  "_id": "65a1b2c3d4e5f6789012345c"
                  "url": "https://your-app.com/webhooks/wallet"
                  "events":
                    - "wallet.balance.updated"
                    - "wallet.transaction.confirmed"
                  "filters":
                    "addresses": []
                    "chains": []
                  "isActive": true
                  "stats":
                    "totalDeliveries": 0
                    "successfulDeliveries": 0
                    "failedDeliveries": 0
                    "lastDeliveryAt": null
                  "createdAt": "2026-01-22T10:00:00.000Z"
                  "updatedAt": "2026-01-22T10:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
      "x-display-name": "Create a wallet webhook"
      "x-sdk-method": "createWebhook"
    "get":
      "tags":
        - "wallet"
      "summary": "List wallet webhooks"
      "description": "Returns all wallet webhooks for the current context, optionally filtered by projectId. Includes delivery stats and active status.\n"
      "operationId": "wallet.listWebhooks"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "query"
          "schema":
            "type": "string"
          "description": "Filter by project ID (optional)."
      "responses":
        "200":
          "description": "List of webhooks"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "array"
                    "items":
                      "$ref": "#/components/schemas/WalletWebhook"
                  "count":
                    "type": "integer"
              "example":
                "success": true
                "data":
                  - "_id": "65a1b2c3d4e5f6789012345c"
                    "url": "https://your-app.com/webhooks/wallet"
                    "events":
                      - "wallet.balance.updated"
                      - "wallet.transaction.confirmed"
                    "isActive": true
                    "stats":
                      "totalDeliveries": 150
                      "successfulDeliveries": 148
                      "failedDeliveries": 2
                      "lastDeliveryAt": "2026-01-22T10:05:00.000Z"
                    "createdAt": "2026-01-22T10:00:00.000Z"
                "count": 1
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
      "x-display-name": "List wallet webhooks"
      "x-sdk-method": "listWebhooks"
  "/api/wallet/non-custodial/webhooks/{webhookId}":
    "delete":
      "tags":
        - "wallet"
      "summary": "Delete a wallet webhook"
      "operationId": "wallet.deleteWebhook"
      "description": "Permanently delete a wallet webhook. Delivery will stop immediately."
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "webhookId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Webhook ID (MongoDB ObjectId) to delete."
      "responses":
        "200":
          "description": "Webhook deleted successfully"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "message":
                    "type": "string"
              "example":
                "success": true
                "message": "Webhook deleted successfully"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "404":
          "description": "Webhook not found (exact backend message)."
          "$ref": "#/components/responses/WebhookNotFound"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
      "x-display-name": "Delete a wallet webhook"
      "x-sdk-method": "deleteWebhook"
    "put":
      "tags":
        - "wallet"
      "summary": "Update a wallet webhook"
      "operationId": "wallet.updateWebhook"
      "description": "Update webhook URL, events, secret, or filters. Partially applied; only provided fields are updated."
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "webhookId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Webhook ID (MongoDB ObjectId) to update."
      "requestBody":
        "required": true
        "description": "Fields to update (url, events, secret, filters). Omitted fields are left unchanged."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "properties":
                "url":
                  "type": "string"
                "events":
                  "type": "array"
                  "items":
                    "type": "string"
                "secret":
                  "type": "string"
                "filters":
                  "type": "object"
            "examples":
              "updateExample":
                "summary": "Update webhook to new URL and events"
                "value":
                  "url": "https://your-app.com/webhooks/updated"
                  "events":
                    - "wallet.transaction.confirmed"
                    - "wallet.transaction.detected"
                  "secret": "whsec_newsecret123"
                  "filters":
                    "addresses":
                      - "65a1b2c3d4e5f6789012345a"
                    "chains":
                      - "celo"
                      - "ethereum"
      "responses":
        "200":
          "description": "Webhook updated successfully"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "$ref": "#/components/schemas/WalletWebhook"
              "example":
                "success": true
                "data":
                  "_id": "65a1b2c3d4e5f6789012345c"
                  "url": "https://your-app.com/webhooks/wallet"
                  "events":
                    - "wallet.balance.updated"
                    - "wallet.transaction.confirmed"
                  "isActive": true
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "404":
          "description": "Webhook not found (exact backend message)."
          "$ref": "#/components/responses/WebhookNotFound"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
      "x-display-name": "Update a wallet webhook"
      "x-sdk-method": "updateWebhook"
  "/api/wallet/non-custodial/webhooks/{webhookId}/logs":
    "get":
      "tags":
        - "wallet"
      "summary": "Get webhook delivery logs"
      "operationId": "wallet.getWebhookLogs"
      "description": "List delivery attempts for a wallet webhook (success/failure, payload, response, duration). Paginated by limit."
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "parameters":
        - "name": "webhookId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Webhook ID (MongoDB ObjectId) to get logs for."
        - "name": "limit"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 50
          "description": "Maximum number of log entries to return."
      "responses":
        "200":
          "description": "Webhook delivery logs"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "array"
                    "items":
                      "$ref": "#/components/schemas/WebhookLog"
              "example":
                "success": true
                "data":
                  - "_id": "605b9f1a2e9b8c0012345678"
                    "url": "https://your-app.com/webhooks/wallet"
                    "method": "POST"
                    "event": "wallet.transaction.confirmed"
                    "status": "success"
                    "statusCode": 200
                    "payload":
                      "event": "wallet.transaction.confirmed"
                      "data":
                        "addressId": "65a1b2c3d4e5f6789012345a"
                        "txHash": "0xa2939a..."
                    "response":
                      "status": 200
                      "body":
                        "result": "ok"
                    "duration": 210
                    "attempts": 1
                    "error": null
                    "nextRetry": null
                    "createdAt": "2026-02-01T21:05:18.123Z"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "404":
          "description": "Webhook not found (exact backend message)."
          "$ref": "#/components/responses/WebhookNotFound"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
      "x-display-name": "Get webhook delivery logs"
      "x-sdk-method": "getWebhookLogs"
  "/api/wallet/non-custodial/webhooks/test":
    "post":
      "tags":
        - "wallet"
      "summary": "Test a webhook delivery (sends a single test payload)"
      "operationId": "wallet.testWebhook"
      "description": "Sends a test payload to the given URL to verify webhook connectivity and signature. Uses the same signing as real deliveries."
      "security":
        - "BearerToken": []
        - "ApiKeyAuth": []
      "requestBody":
        "required": true
        "description": "URL to send the test POST to; optional secret and projectId for scoping; optional event type to simulate."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "url"
              "properties":
                "url":
                  "type": "string"
                "secret":
                  "type": "string"
                "projectId":
                  "type": "string"
                "event":
                  "type": "string"
            "examples":
              "testWebhookExample":
                "summary": "Test webhook delivery for detected event"
                "value":
                  "url": "https://your-app.com/webhooks/test"
                  "secret": "whsec_test_abc123"
                  "projectId": "685ad30be129932fbb7a1047"
                  "event": "wallet.transaction.detected"
      "responses":
        "200":
          "description": "Test result"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
              "example":
                "success": true
                "data":
                  "success": true
                  "status": 200
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "429":
          "description": "Rate limit exceeded."
          "$ref": "#/components/responses/TooManyRequests"
      "x-display-name": "Test a webhook delivery (sends a single test payload)"
      "x-sdk-method": "testWebhook"
  "/api/billing/public/projects/{projectId}/plans":
    "get":
      "tags":
        - "billing"
      "summary": "Get public plans (no auth required)"
      "operationId": "billing.getPublicPlans"
      "description": "Returns subscription plans available for the project. Public; no authentication required. Use for pricing pages and checkout flow."
      "security": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) to list plans for."
      "responses":
        "200":
          "description": "Public plans list"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "plans":
                    "type": "array"
                    "items":
                      "$ref": "#/components/schemas/Plan"
              "example":
                "plans":
                  - "_id": "65a1b2c3d4e5f6789012345d"
                    "name": "Pro Plan"
                    "price": 29.99
                    "currency": "USD"
                    "interval": "month"
                    "features":
                      - "Unlimited API calls"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Get public plans (no auth required)"
      "x-sdk-method": "getPublicPlans"
  "/api/billing/public/projects/{projectId}/checkout":
    "post":
      "tags":
        - "billing"
      "summary": "Create checkout session (Flutterwave or crypto)"
      "description": "Creates a checkout session for subscription billing. When Flutterwave is configured (platform),

        returns authorizationUrl and accessCode for redirect. When using crypto payment processor,

        returns checkoutUrl, paymentOptions (multi-chain USDC/USDT/BTC Lightning), and reference.\n"
      "operationId": "billing.createCheckoutSession"
      "security": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) for the billing project."
      "requestBody":
        "required": true
        "description": "Plan to subscribe to, billing cycle, customer email/name, and optional success/cancel redirect URLs."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "planId"
                - "billingCycle"
                - "customerInfo"
              "properties":
                "planId":
                  "type": "string"
                  "description": "Plan ID to subscribe to"
                "billingCycle":
                  "type": "string"
                  "enum":
                    - "monthly"
                    - "yearly"
                  "description": "Billing interval"
                "customerInfo":
                  "type": "object"
                  "required":
                    - "email"
                  "properties":
                    "email":
                      "type": "string"
                      "format": "email"
                    "name":
                      "type": "string"
                "successUrl":
                  "type": "string"
                  "format": "uri"
                  "description": "Redirect URL after successful payment"
                "cancelUrl":
                  "type": "string"
                  "format": "uri"
                  "description": "Redirect URL if user cancels"
            "example":
              "planId": "65a1b2c3d4e5f6789012345d"
              "billingCycle": "monthly"
              "customerInfo":
                "email": "customer@example.com"
                "name": "John Doe"
              "successUrl": "https://app.example.com/success"
              "cancelUrl": "https://app.example.com/cancel"
      "responses":
        "200":
          "description": "Checkout session created"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
                    "properties":
                      "checkoutUrl":
                        "type": "string"
                        "description": "Checkout/page URL (crypto) or null when Flutterwave"
                      "authorizationUrl":
                        "type": "string"
                        "description": "Flutterwave redirect URL (when Flutterwave is used)"
                      "accessCode":
                        "type": "string"
                        "description": "Flutterwave access code"
                      "reference":
                        "type": "string"
                        "description": "Payment reference (e.g. mudbase_xxx or pmt_xxx)"
                      "paymentId":
                        "type": "string"
                        "description": "Payment intent ID (crypto)"
                      "paymentOptions":
                        "type": "array"
                        "description": "Multi-chain payment options (crypto)"
                        "items":
                          "type": "object"
                          "properties":
                            "chain":
                              "type": "string"
                              "enum":
                                - "polygon"
                                - "arbitrum"
                                - "tron"
                                - "solana"
                                - "lightning"
                                - "ton"
                            "asset":
                              "type": "string"
                              "enum":
                                - "USDC"
                                - "USDT"
                                - "BTC"
                            "address":
                              "type": "string"
                            "invoice":
                              "type": "string"
                            "networkFee":
                              "type": "string"
                            "totalDue":
                              "type": "string"
                      "paymentAddress":
                        "type": "string"
                      "network":
                        "type": "string"
                      "asset":
                        "type": "string"
                      "amount":
                        "type": "number"
                      "currency":
                        "type": "string"
              "examples":
                "flutterwave":
                  "summary": "Flutterwave response"
                  "value":
                    "success": true
                    "data":
                      "authorizationUrl": "https://checkout.flutterwave.com/v3/xxx"
                      "accessCode": "FLW_ACCESS_xxx"
                      "reference": "mudbase_abc123xyz"
                      "amount": 29.99
                      "currency": "USD"
                "crypto":
                  "summary": "Crypto payment response"
                  "value":
                    "success": true
                    "data":
                      "checkoutUrl": "https://mudbase-pay.com/checkout/pmt_abc123"
                      "reference": "pmt_abc123"
                      "paymentId": "pmt_abc123"
                      "paymentOptions":
                        - "chain": "polygon"
                          "asset": "USDC"
                          "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                          "networkFee": "0.01"
                          "totalDue": "29.99"
                      "amount": 29.99
                      "currency": "USD"
        "400":
          "description": "Missing planId, billingCycle, or customerInfo.email"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "error":
                    "type": "string"
              "example":
                "error": "planId, billingCycle, and customerInfo.email are required"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Create checkout session (Flutterwave or crypto)"
      "x-sdk-method": "createCheckoutSession"
  "/api/billing/public/projects/{projectId}/checkout/{paymentId}":
    "get":
      "tags":
        - "billing"
      "summary": "Get checkout payment details"
      "description": "Returns payment intent/checkout status (for refresh or deep link). No auth required."
      "operationId": "billing.getCheckoutPayment"
      "security": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) for the billing project."
        - "name": "paymentId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Payment ID or reference from checkout session"
      "responses":
        "200":
          "description": "Payment details"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
                    "properties":
                      "paymentId":
                        "type": "string"
                      "paymentAddress":
                        "type": "string"
                        "nullable": true
                      "network":
                        "type": "string"
                        "nullable": true
                      "asset":
                        "type": "string"
                        "nullable": true
                      "amount":
                        "type": "number"
                      "currency":
                        "type": "string"
                      "totalDue":
                        "type": "string"
                        "nullable": true
                      "status":
                        "type": "string"
                      "expiresAt":
                        "type": "string"
                        "format": "date-time"
                        "nullable": true
              "example":
                "success": true
                "data":
                  "paymentId": "pmt_abc123"
                  "paymentAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
                  "network": "polygon"
                  "asset": "USDC"
                  "amount": 29.99
                  "currency": "USD"
                  "totalDue": "30.00"
                  "status": "pending"
                  "expiresAt": "2026-03-02T03:00:00.000Z"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "Payment not found (exact backend message)."
          "$ref": "#/components/responses/PaymentNotFound"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Get checkout payment details"
      "x-sdk-method": "getCheckoutPayment"
  "/api/billing/public/projects/{projectId}/verify-payment":
    "post":
      "tags":
        - "billing"
      "summary": "Verify payment and create subscription"
      "description": "Verifies payment by reference (Flutterwave mudbase_xxx or crypto pmt_xxx) and creates or updates the subscription.

        Call after redirect from payment provider; pass reference as query (e.g. ?reference=mudbase_abc123). Idempotent for same reference.\n"
      "operationId": "billing.verifyPayment"
      "security": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) for the billing project."
        - "name": "reference"
          "in": "query"
          "required": true
          "schema":
            "type": "string"
          "description": "Payment reference (e.g. mudbase_abc123 or pmt_abc123)"
      "responses":
        "200":
          "description": "Payment verified and subscription created"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "message":
                    "type": "string"
                  "data":
                    "type": "object"
                    "properties":
                      "subscription":
                        "type": "object"
                        "properties":
                          "_id":
                            "type": "string"
                          "status":
                            "type": "string"
                            "enum":
                              - "active"
                              - "cancelled"
                              - "past_due"
                          "plan":
                            "type": "string"
                          "currentPeriodEnd":
                            "type": "string"
                            "format": "date-time"
              "example":
                "success": true
                "message": "Payment verified and subscription created"
                "data":
                  "subscription":
                    "_id": "65a1b2c3d4e5f6789012345e"
                    "status": "active"
                    "plan": "65a1b2c3d4e5f6789012345d"
                    "currentPeriodEnd": "2026-04-02T00:00:00.000Z"
        "400":
          "description": "reference is required or organization context missing"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "error":
                    "type": "string"
              "example":
                "error": "reference is required"
        "403":
          "description": "Payment does not belong to your organization"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "error":
                    "type": "string"
              "example":
                "error": "Payment does not belong to your organization"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Verify payment and create subscription"
      "x-sdk-method": "verifyPayment"
  "/api/billing/public/projects/{projectId}/subscription":
    "get":
      "tags":
        - "billing"
      "summary": "Check subscription status (public)"
      "operationId": "billing.checkSubscription"
      "description": "Check whether a customer (by email) has an active subscription for the project. Public; no auth required."
      "security": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) for the billing project."
        - "name": "email"
          "in": "query"
          "required": true
          "schema":
            "type": "string"
            "format": "email"
          "description": "Customer email to check subscription for"
      "responses":
        "200":
          "description": "Subscription status"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "hasSubscription":
                    "type": "boolean"
                  "subscription":
                    "type": "object"
                    "properties":
                      "status":
                        "type": "string"
                      "plan":
                        "type": "string"
              "example":
                "hasSubscription": true
                "subscription":
                  "status": "active"
                  "plan": "65a1b2c3d4e5f6789012345d"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Check subscription status (public)"
      "x-sdk-method": "checkSubscription"
  "/api/billing/public/projects/{projectId}/feature-access":
    "get":
      "tags":
        - "billing"
      "summary": "Check feature access (public)"
      "operationId": "billing.checkFeatureAccess"
      "description": "Check whether a customer has access to a feature (by plan or entitlement). Public; no auth required."
      "security": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) for the billing project."
        - "name": "email"
          "in": "query"
          "required": true
          "schema":
            "type": "string"
            "format": "email"
          "description": "Customer email"
        - "name": "feature"
          "in": "query"
          "required": true
          "schema":
            "type": "string"
          "description": "Feature slug to check access for"
      "responses":
        "200":
          "description": "Feature access status"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "hasAccess":
                    "type": "boolean"
                  "reason":
                    "type": "string"
              "example":
                "hasAccess": true
                "reason": "Active subscription"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Check feature access (public)"
      "x-sdk-method": "checkFeatureAccess"
  "/api/billing/public/projects/{projectId}/usage":
    "post":
      "tags":
        - "billing"
      "summary": "Record usage (public)"
      "operationId": "billing.recordUsage"
      "description": "Record metered usage for a customer (e.g. api_calls, storage_mb). Used for usage-based billing. Public endpoint; optionally secured by webhook or API key in production."
      "security": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID (MongoDB ObjectId) for the billing project."
      "requestBody":
        "required": true
        "description": "Customer email, metric name (e.g. api_calls, storage_mb), and quantity to record."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "email"
                - "metric"
                - "quantity"
              "properties":
                "email":
                  "type": "string"
                  "format": "email"
                  "description": "Customer email"
                "metric":
                  "type": "string"
                  "description": "Usage metric name (e.g. api_calls, storage_mb)"
                "quantity":
                  "type": "number"
                  "description": "Quantity to record"
            "example":
              "email": "customer@example.com"
              "metric": "api_calls"
              "quantity": 150
      "responses":
        "200":
          "description": "Usage recorded"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "Usage recorded successfully"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Record usage (public)"
      "x-sdk-method": "recordUsage"
  "/api/billing/webhooks/crypto":
    "post":
      "tags":
        - "billing"
      "summary": "Crypto payment processor webhook"
      "description": "Receives crypto payment events (payment.completed, etc.) for platform billing. No auth; verified by provider signature."
      "operationId": "billing.handleCryptoWebhook"
      "security": []
      "requestBody":
        "required": true
        "description": "Crypto payment webhook payload (event type and data with paymentId, reference, amount, currency, network, status, metadata)."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "event"
                - "data"
              "properties":
                "event":
                  "type": "string"
                  "enum":
                    - "payment.created"
                    - "payment.detected"
                    - "payment.confirmed"
                    - "payment.finalized"
                    - "payment.completed"
                    - "payment.failed"
                "data":
                  "type": "object"
                  "properties":
                    "paymentId":
                      "type": "string"
                    "reference":
                      "type": "string"
                    "amount":
                      "type": "number"
                    "currency":
                      "type": "string"
                    "network":
                      "type": "string"
                    "status":
                      "type": "string"
                    "metadata":
                      "type": "object"
            "example":
              "event": "payment.completed"
              "data":
                "paymentId": "pmt_abc123xyz789"
                "reference": "pmt_abc123xyz789"
                "amount": 29.99
                "currency": "USD"
                "network": "polygon"
                "status": "completed"
                "metadata":
                  "isPlatformBilling": true
                  "planId": "65a1b2c3d4e5f6789012345d"
                  "billingCycle": "monthly"
                  "customerEmail": "customer@example.com"
      "responses":
        "200":
          "description": "Webhook processed"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "received":
                    "type": "boolean"
              "example":
                "received": true
        "400":
          "description": "Event type is required or invalid payload"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "error":
                    "type": "string"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Crypto payment processor webhook"
      "x-sdk-method": "handleCryptoWebhook"
  "/api/billing/webhooks/flutterwave":
    "post":
      "tags":
        - "billing"
      "summary": "Flutterwave webhook"
      "description": "Receives Flutterwave webhook events (charge.completed, payment.successful). No auth; verified by verif-hash header.

        - Subscription billing: meta without isPaymentProcessing triggers verifyPaymentAndCreateSubscription (mudbase_xxx refs).

        - Payment processing: meta.isPaymentProcessing === true triggers fiat payment record (mudbase_fiat_xxx refs); org share goes to org subaccount, platform fee to main or configured subaccounts.\n"
      "operationId": "billing.handleFlutterwaveWebhook"
      "security": []
      "requestBody":
        "required": true
        "description": "Flutterwave webhook payload (event and data with id, tx_ref, amount, currency, status, customer, meta for subscription or payment-processing)."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "properties":
                "event":
                  "type": "string"
                  "description": "Event type (e.g. charge.completed, payment.successful)"
                "data":
                  "type": "object"
                  "properties":
                    "id":
                      "type": "number"
                    "tx_ref":
                      "type": "string"
                    "flw_ref":
                      "type": "string"
                    "amount":
                      "type": "number"
                    "currency":
                      "type": "string"
                    "status":
                      "type": "string"
                    "customer":
                      "type": "object"
                      "properties":
                        "email":
                          "type": "string"
                        "name":
                          "type": "string"
                    "meta":
                      "type": "object"
                      "description": "orgId, projectId, planId, billingCycle; or isPaymentProcessing true for fiat payment-processing"
            "example":
              "event": "charge.completed"
              "data":
                "id": 123456789
                "tx_ref": "mudbase_fiat_org123_project456_1234567890_abc"
                "amount": 100
                "currency": "USD"
                "status": "successful"
                "customer":
                  "email": "customer@example.com"
                  "name": "John Doe"
                "meta":
                  "orgId": "65a1b2c3d4e5f6789012345a"
                  "projectId": "65a1b2c3d4e5f6789012345b"
                  "isPaymentProcessing": true
      "responses":
        "200":
          "description": "Webhook received"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "received":
                    "type": "boolean"
              "example":
                "received": true
        "400":
          "description": "Invalid or missing event"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "error":
                    "type": "string"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Flutterwave webhook"
      "x-sdk-method": "handleFlutterwaveWebhook"
  "/api/projects/{projectId}/payment-processing/initialize-payment":
    "post":
      "tags":
        - "billing"
      "summary": "Initialize fiat payment (app-scoped)"
      "description": "Same as org-level initialize-payment; projectId from path is used for scope and tx_ref. Resolves project to org and uses org's Flutterwave subaccount."
      "operationId": "billing.initializePayment"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID for payment scope and tx_ref."
      "requestBody":
        "required": true
        "description": "Payment amount, currency, customer (email, name), and optional metadata."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "amount"
                - "customer"
              "properties":
                "amount":
                  "type": "number"
                  "minimum": 0.01
                "currency":
                  "type": "string"
                  "default": "USD"
                "customer":
                  "type": "object"
                  "required":
                    - "email"
                  "properties":
                    "email":
                      "type": "string"
                    "name":
                      "type": "string"
                "metadata":
                  "type": "object"
      "responses":
        "200":
          "description": "Payment link and fee breakdown (same shape as org-level)"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "500":
          "description": "Internal server error."
          "$ref": "#/components/responses/InternalServerError"
      "x-display-name": "Initialize fiat payment (app-scoped)"
      "x-sdk-method": "initializePayment"
  "/api/chat/projects/{projectId}/chats":
    "post":
      "tags":
        - "chat"
      "summary": "Create new chat"
      "description": "Create a new chat (direct, group, channel, or broadcast) with name, type, participants, and optional settings."
      "operationId": "chat.create"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
      "requestBody":
        "required": true
        "description": "Chat name, type (direct/group/channel/broadcast), participants array, optional description and settings."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "name"
                - "type"
                - "participants"
              "properties":
                "name":
                  "type": "string"
                "description":
                  "type": "string"
                "type":
                  "type": "string"
                  "enum":
                    - "direct"
                    - "group"
                    - "channel"
                    - "broadcast"
                "participants":
                  "type": "array"
                  "items":
                    "type": "string"
                "settings":
                  "type": "object"
            "example":
              "name": "Team Chat"
              "description": "Main team communication"
              "type": "group"
              "participants":
                - "685acbe0e129932fbb7a0fc2"
                - "685acbe0e129932fbb7a0fc3"
              "settings": {}
      "responses":
        "201":
          "description": "Chat created"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
                    "properties":
                      "_id":
                        "type": "string"
                      "name":
                        "type": "string"
                      "type":
                        "type": "string"
                      "participants":
                        "type": "array"
                        "items":
                          "type": "string"
                      "createdAt":
                        "type": "string"
                        "format": "date-time"
              "example":
                "success": true
                "data":
                  "_id": "65a1b2c3d4e5f6789012345f"
                  "name": "Team Chat"
                  "type": "group"
                  "participants":
                    - "user": "65a1b2c3d4e5f6789012345"
                      "role": "admin"
                  "createdAt": "2024-01-15T10:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
      "x-display-name": "Create new chat"
      "x-sdk-method": "create"
    "get":
      "tags":
        - "chat"
      "summary": "Get user chats"
      "description": "Returns paginated list of chats for the current user in the project, with last message and unread count."
      "operationId": "chat.list"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "page"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 1
          "description": "Page number (1-based)."
        - "name": "limit"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 20
          "description": "Number of chats per page."
      "responses":
        "200":
          "description": "User chats list"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
                    "properties":
                      "chats":
                        "type": "array"
                        "items":
                          "type": "object"
                          "properties":
                            "_id":
                              "type": "string"
                            "name":
                              "type": "string"
                            "type":
                              "type": "string"
                            "lastMessage":
                              "type": "object"
                              "properties":
                                "content":
                                  "type": "string"
                            "unreadCount":
                              "type": "integer"
                      "total":
                        "type": "integer"
              "example":
                "success": true
                "data":
                  "chats":
                    - "_id": "65a1b2c3d4e5f6789012345f"
                      "name": "Team Chat"
                      "type": "group"
                      "lastMessage":
                        "content": "Hello everyone"
                      "unreadCount": 2
                  "total": 1
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
      "x-display-name": "Get user chats"
      "x-sdk-method": "list"
  "/api/chat/projects/{projectId}/chats/{chatId}":
    "get":
      "tags":
        - "chat"
      "summary": "Get chat details"
      "description": "Returns full chat metadata including participants and roles for a single chat."
      "operationId": "chat.get"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "chatId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Chat ID."
      "responses":
        "200":
          "description": "Chat details"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
                    "properties":
                      "_id":
                        "type": "string"
                      "name":
                        "type": "string"
                      "participants":
                        "type": "array"
                        "items":
                          "type": "object"
                          "properties":
                            "userId":
                              "type": "string"
                            "role":
                              "type": "string"
              "example":
                "success": true
                "data":
                  "_id": "65a1b2c3d4e5f6789012345f"
                  "name": "Team Chat"
                  "type": "group"
                  "participants":
                    - "userId": "685acbe0e129932fbb7a0fc2"
                      "role": "admin"
                  "createdAt": "2024-01-15T10:00:00.000Z"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "404":
          "description": "Project or chat not found (exact backend message)."
          "$ref": "#/components/responses/ProjectNotFound"
      "x-display-name": "Get chat details"
      "x-sdk-method": "get"
  "/api/chat/projects/{projectId}/me/chat-e2ee-key":
    "put":
      "tags":
        - "chat"
      "summary": "Register chat E2EE identity public key"
      "description": "Stores your long-term public key for end-to-end encrypted chat (key agreement). Private keys never leave the client. Other participants use this to encrypt messages to you."
      "operationId": "chat.putChatE2eeKey"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
      "requestBody":
        "required": true
        "description": "Identity public key material for E2EE chat (base64). Private keys stay on the client."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "identityPublicKey"
              "properties":
                "identityPublicKey":
                  "type": "string"
                  "description": "Base64-encoded public key (algorithm defined by client; opaque to server)."
                "keyVersion":
                  "type": "integer"
                  "description": "Optional; defaults to incrementing stored version."
            "example":
              "identityPublicKey": "dGVzdEtleUJhc2U2NA=="
              "keyVersion": 1
      "responses":
        "200":
          "description": "Key saved"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
                    "properties":
                      "identityPublicKey":
                        "type": "string"
                      "keyVersion":
                        "type": "integer"
                      "updatedAt":
                        "type": "string"
                        "format": "date-time"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
      "x-display-name": "Register chat E2EE public key"
      "x-sdk-method": "putChatE2eeKey"
  "/api/chat/projects/{projectId}/chats/{chatId}/e2ee/participant-keys":
    "get":
      "tags":
        - "chat"
      "summary": "List participant E2EE public keys"
      "description": "Returns registered identity public keys for users in this chat (for client-side key distribution and encryption)."
      "operationId": "chat.getChatE2eeParticipantKeys"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "chatId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Chat ID."
      "responses":
        "200":
          "description": "Participant keys"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "array"
                    "items":
                      "type": "object"
                      "properties":
                        "userId":
                          "type": "string"
                        "identityPublicKey":
                          "type": "string"
                        "keyVersion":
                          "type": "integer"
                        "updatedAt":
                          "type": "string"
                          "format": "date-time"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "404":
          "description": "Project or chat not found (exact backend message)."
          "$ref": "#/components/responses/ProjectNotFound"
      "x-display-name": "List participant E2EE keys"
      "x-sdk-method": "getChatE2eeParticipantKeys"
  "/api/chat/projects/{projectId}/chats/{chatId}/messages":
    "post":
      "tags":
        - "chat"
      "summary": "Send message"
      "description": "Send a message (text, image, video, audio, file, location, contact) to a chat with optional replyTo and mentions. For end-to-end encryption, use type=text with e2ee.ciphertext (base64) instead of plaintext content; server stores ciphertext only."
      "operationId": "chat.sendMessage"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "chatId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Chat ID."
      "requestBody":
        "required": true
        "description": "Message type and content, or E2EE ciphertext for text messages. Plaintext requires content; E2EE requires type=text and e2ee.ciphertext (omit plaintext content)."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "type"
              "properties":
                "type":
                  "type": "string"
                  "enum":
                    - "text"
                    - "image"
                    - "video"
                    - "audio"
                    - "file"
                    - "location"
                    - "contact"
                "content":
                  "type": "string"
                  "description": "Plaintext body; omit when sending e2ee (use e2ee.ciphertext for E2EE text)."
                "e2ee":
                  "type": "object"
                  "description": "Opaque end-to-end encrypted payload (base64 ciphertext). Server cannot decrypt. Only for type=text."
                  "properties":
                    "version":
                      "type": "integer"
                      "default": 1
                    "scheme":
                      "type": "string"
                      "example": "mudbase-e2ee-v1"
                    "ciphertext":
                      "type": "string"
                      "description": "Base64-encoded ciphertext."
                    "nonce":
                      "type": "string"
                    "ephemeralPublicKey":
                      "type": "string"
                    "senderKeyId":
                      "type": "string"
                "replyTo":
                  "type": "string"
                "mentions":
                  "type": "array"
                  "items":
                    "type": "string"
            "example":
              "type": "text"
              "content": "Hello everyone!"
              "replyTo": null
              "mentions": []
      "responses":
        "201":
          "description": "Message sent"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
                    "properties":
                      "_id":
                        "type": "string"
                      "content":
                        "type": "string"
                      "sender":
                        "type": "string"
                      "createdAt":
                        "type": "string"
                        "format": "date-time"
              "example":
                "success": true
                "data":
                  "_id": "65a1b2c3d4e5f6789012345g"
                  "content": "Hello everyone"
                  "sender": "65a1b2c3d4e5f6789012345"
                  "createdAt": "2024-01-15T10:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
      "x-display-name": "Send message"
      "x-sdk-method": "sendMessage"
    "get":
      "tags":
        - "chat"
      "summary": "Get chat messages"
      "description": "Returns paginated messages for a chat with optional before/after cursor for time-based pagination."
      "operationId": "chat.getMessages"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "chatId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Chat ID."
        - "name": "page"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 1
          "description": "Page number (1-based)."
        - "name": "limit"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 50
          "description": "Number of messages per page."
        - "name": "before"
          "in": "query"
          "schema":
            "type": "string"
            "format": "date-time"
          "description": "Return messages before this timestamp (cursor)."
        - "name": "after"
          "in": "query"
          "schema":
            "type": "string"
            "format": "date-time"
          "description": "Return messages after this timestamp (cursor)."
      "responses":
        "200":
          "description": "Messages list"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
                    "properties":
                      "messages":
                        "type": "array"
                        "items":
                          "type": "object"
                          "properties":
                            "_id":
                              "type": "string"
                            "content":
                              "type": "string"
                            "sender":
                              "type": "object"
                              "properties":
                                "_id":
                                  "type": "string"
                                "firstName":
                                  "type": "string"
                            "createdAt":
                              "type": "string"
                              "format": "date-time"
                      "total":
                        "type": "integer"
              "example":
                "success": true
                "data":
                  "messages":
                    - "_id": "65a1b2c3d4e5f6789012345g"
                      "content": "Hello everyone"
                      "sender":
                        "_id": "65a1b2c3d4e5f6789012345"
                        "firstName": "John"
                      "createdAt": "2024-01-15T10:00:00.000Z"
                  "total": 1
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
      "x-display-name": "Get chat messages"
      "x-sdk-method": "getMessages"
  "/api/chat/projects/{projectId}/chats/{chatId}/messages/read":
    "post":
      "tags":
        - "chat"
      "summary": "Mark messages as read"
      "description": "Mark one or more messages as read for the current user in the chat."
      "operationId": "chat.markAsRead"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "chatId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Chat ID."
      "requestBody":
        "required": true
        "description": "Array of message IDs to mark as read."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "messageIds"
              "properties":
                "messageIds":
                  "type": "array"
                  "items":
                    "type": "string"
            "example":
              "messageIds":
                - "65a1b2c3d4e5f6789012345g"
                - "65a1b2c3d4e5f6789012345h"
      "responses":
        "200":
          "description": "Messages marked as read"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
                    "properties":
                      "modifiedCount":
                        "type": "integer"
              "example":
                "success": true
                "data":
                  "modifiedCount": 5
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
      "x-display-name": "Mark messages as read"
      "x-sdk-method": "markAsRead"
  "/api/chat/projects/{projectId}/chats/{chatId}/messages/{messageId}/reactions":
    "post":
      "tags":
        - "chat"
      "summary": "Add reaction to message"
      "description": "Add an emoji reaction to a message."
      "operationId": "chat.addReaction"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "chatId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Chat ID."
        - "name": "messageId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Message ID."
      "requestBody":
        "required": true
        "description": "Emoji reaction (e.g. 👍, ❤️)."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "emoji"
              "properties":
                "emoji":
                  "type": "string"
            "example":
              "emoji": "👍"
      "responses":
        "200":
          "description": "Reaction added"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "array"
                    "items":
                      "type": "object"
                      "properties":
                        "emoji":
                          "type": "string"
                        "users":
                          "type": "array"
                          "items":
                            "type": "string"
              "example":
                "success": true
                "data":
                  - "emoji": "👍"
                    "users":
                      - "65a1b2c3d4e5f6789012345"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
      "x-display-name": "Add reaction to message"
      "x-sdk-method": "addReaction"
    "delete":
      "tags":
        - "chat"
      "summary": "Remove reaction from message"
      "description": "Remove the current user's emoji reaction from a message."
      "operationId": "chat.removeReaction"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "chatId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Chat ID."
        - "name": "messageId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Message ID."
      "requestBody":
        "required": true
        "description": "Emoji to remove (must match the reaction added by the user)."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "emoji"
              "properties":
                "emoji":
                  "type": "string"
            "example":
              "emoji": "👍"
      "responses":
        "200":
          "description": "Reaction removed"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "array"
                    "items":
                      "type": "object"
                      "properties":
                        "emoji":
                          "type": "string"
                        "count":
                          "type": "integer"
                        "users":
                          "type": "array"
                          "items":
                            "type": "string"
              "example":
                "success": true
                "data":
                  - "emoji": "👍"
                    "count": 2
                    "users":
                      - "685acbe0e129932fbb7a0fc2"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
      "x-display-name": "Remove reaction from message"
      "x-sdk-method": "removeReaction"
  "/api/chat/projects/{projectId}/chats/{chatId}/messages/{messageId}":
    "patch":
      "tags":
        - "chat"
      "summary": "Edit message"
      "description": "Update the content of a message (sender only; supports edit history)."
      "operationId": "chat.editMessage"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "chatId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Chat ID."
        - "name": "messageId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Message ID."
      "requestBody":
        "required": true
        "description": "New plaintext content (non-E2EE messages) or new e2ee ciphertext (E2EE messages). One of content or e2ee.ciphertext is required."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "properties":
                "content":
                  "type": "string"
                  "description": "New plaintext (non-E2EE messages only)."
                "e2ee":
                  "type": "object"
                  "description": "New opaque ciphertext (E2EE messages only)."
                  "properties":
                    "version":
                      "type": "integer"
                    "scheme":
                      "type": "string"
                    "ciphertext":
                      "type": "string"
                    "nonce":
                      "type": "string"
                    "ephemeralPublicKey":
                      "type": "string"
                    "senderKeyId":
                      "type": "string"
            "example":
              "content": "Updated message content"
      "responses":
        "200":
          "description": "Message edited"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
                    "properties":
                      "_id":
                        "type": "string"
                      "content":
                        "type": "string"
                      "isE2ee":
                        "type": "boolean"
                      "e2ee":
                        "type": "object"
                      "editedAt":
                        "type": "string"
              "example":
                "success": true
                "data":
                  "_id": "65a1b2c3d4e5f6789012345g"
                  "content": "Updated message content"
                  "editedAt": "2024-01-15T11:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Edit message"
      "x-sdk-method": "editMessage"
    "delete":
      "tags":
        - "chat"
      "summary": "Delete message"
      "description": "Delete a message from the chat (sender or admin). May be soft-delete or permanent depending on implementation."
      "operationId": "chat.deleteMessage"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "chatId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Chat ID."
        - "name": "messageId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Message ID."
      "responses":
        "200":
          "description": "Message deleted"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "Message deleted successfully"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
        "404":
          "description": "Project or message not found (exact backend message)."
          "$ref": "#/components/responses/ProjectNotFound"
      "x-display-name": "Delete message"
      "x-sdk-method": "deleteMessage"
  "/api/chat/projects/{projectId}/chats/{chatId}/participants":
    "post":
      "tags":
        - "chat"
      "summary": "Add participant to chat"
      "description": "Add a user to the chat with an optional role (admin or member)."
      "operationId": "chat.addParticipant"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "chatId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Chat ID."
      "requestBody":
        "required": true
        "description": "User ID to add and optional role (admin, member)."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "userId"
              "properties":
                "userId":
                  "type": "string"
                "role":
                  "type": "string"
                  "enum":
                    - "admin"
                    - "member"
            "example":
              "userId": "685acbe0e129932fbb7a0fc2"
              "role": "member"
      "responses":
        "200":
          "description": "Participant added"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
                    "properties":
                      "participants":
                        "type": "array"
                        "items":
                          "type": "object"
                          "properties":
                            "userId":
                              "type": "string"
                            "role":
                              "type": "string"
                            "addedAt":
                              "type": "string"
                              "format": "date-time"
              "example":
                "success": true
                "data":
                  "participants":
                    - "userId": "685acbe0e129932fbb7a0fc2"
                      "role": "member"
                      "addedAt": "2024-01-15T11:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
      "x-display-name": "Add participant to chat"
      "x-sdk-method": "addParticipant"
    "delete":
      "tags":
        - "chat"
      "summary": "Remove participant from chat"
      "description": "Remove a user from the chat by userId."
      "operationId": "chat.removeParticipant"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "chatId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Chat ID."
      "requestBody":
        "required": true
        "description": "User ID of the participant to remove."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "userId"
              "properties":
                "userId":
                  "type": "string"
            "example":
              "userId": "685acbe0e129932fbb7a0fc2"
      "responses":
        "200":
          "description": "Participant removed"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/MessageResponse"
              "example":
                "message": "Participant removed successfully"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
      "x-display-name": "Remove participant from chat"
      "x-sdk-method": "removeParticipant"
  "/api/integrations/projects/{projectId}/integrations":
    "get":
      "tags":
        - "integrations"
      "summary": "Get project integrations"
      "operationId": "integrations.list"
      "description": "List all integrations configured for a project.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
      "responses":
        "200":
          "description": "Integrations list"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "integrations":
                    "type": "array"
                    "items":
                      "type": "object"
                      "properties":
                        "_id":
                          "type": "string"
                        "name":
                          "type": "string"
                        "provider":
                          "type": "string"
                        "status":
                          "type": "string"
              "example":
                "integrations":
                  - "_id": "65a1b2c3d4e5f6789012345i"
                    "name": "Twitter Integration"
                    "provider": "twitter"
                    "status": "active"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
      "x-display-name": "Get project integrations"
      "x-sdk-method": "list"
  "/api/integrations/projects/{projectId}/integrations/{integrationId}/execute":
    "post":
      "tags":
        - "integrations"
      "summary": "Execute integration"
      "operationId": "integrations.execute"
      "description": "Execute an integration action (API call) with specified endpoint and parameters.

        Accepts BearerToken (JWT) or ApiKeyAuth (X-API-Key).\n"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "integrationId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Integration ID to execute."
      "requestBody":
        "required": true
        "description": "Endpoint path, HTTP method, optional params and body for the integration call."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "endpoint"
                - "method"
              "properties":
                "endpoint":
                  "type": "string"
                "method":
                  "type": "string"
                  "enum":
                    - "GET"
                    - "POST"
                    - "PUT"
                    - "PATCH"
                    - "DELETE"
                "params":
                  "type": "object"
                "body":
                  "type": "object"
            "example":
              "endpoint": "/api/v1/users"
              "method": "GET"
              "params": {}
              "body": {}
      "responses":
        "200":
          "description": "Integration executed"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "success":
                    "type": "boolean"
                  "data":
                    "type": "object"
              "example":
                "success": true
                "data":
                  "status": 200
                  "response": {}
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Execute integration"
      "x-sdk-method": "execute"
  "/health":
    "get":
      "tags":
        - "health"
      "summary": "Health check"
      "operationId": "health.check"
      "description": "Liveness/readiness probe for load balancers and orchestrators. Returns status of core services (database, redis, storage, email, sms).

        No authentication required. Use for uptime checks and deployment health gates.\n"
      "security": []
      "responses":
        "200":
          "description": "System health status"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/HealthResponse"
              "example":
                "status": "healthy"
                "timestamp": "2024-01-15T10:00:00.000Z"
                "services":
                  "database": "healthy"
                  "redis": "healthy"
                  "storage": "healthy"
                  "email": "healthy"
                  "sms": "healthy"
                "version": "1.0.0"
                "uptime": 3600
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "Health check"
      "x-sdk-method": "check"
  "/api/status":
    "get":
      "tags":
        - "health"
      "summary": "System status"
      "operationId": "health.systemStatus"
      "description": "Returns detailed system status (uptime, memory, CPU, service health). Requires project JWT or API key. Used for admin or monitoring dashboards."
      "security":
        - "BearerToken": []
      "responses":
        "200":
          "description": "Detailed system status"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/SystemStatusResponse"
              "example":
                "success": true
                "data":
                  "uptime": 86400
                  "memory":
                    "used": 2147483648
                    "total": 4294967296
                    "percentage": 50
                  "cpu":
                    "usage": 12.5
                  "services":
                    "database": "operational"
                    "redis": "operational"
                    "storage": "operational"
                    "messaging": "operational"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "description": "Access denied or insufficient permissions."
          "$ref": "#/components/responses/Forbidden"
      "x-display-name": "System status"
      "x-sdk-method": "systemStatus"
  "/api/compliance/security-event":
    "post":
      "tags":
        - "compliance"
      "summary": "Log security event"
      "operationId": "compliance.logSecurityEvent"
      "description": "Log a security event for compliance and audit (e.g. SOC 2, GDPR). Event type and severity are required; optional details (userId, resource, ipAddress, etc.) for forensics."
      "security":
        - "BearerToken": []
      "requestBody":
        "required": true
        "description": "Event type (e.g. unauthorized_access_attempt, brute_force_attempt), severity (low–critical), and optional details object for context."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "eventType"
                - "severity"
              "properties":
                "eventType":
                  "type": "string"
                  "enum":
                    - "unauthorized_access_attempt"
                    - "brute_force_attempt"
                    - "suspicious_api_activity"
                    - "private_key_export"
                    - "bulk_data_export"
                    - "admin_privilege_escalation"
                    - "data_breach_detected"
                    - "mfa_bypass_attempt"
                  "example": "unauthorized_access_attempt"
                "severity":
                  "type": "string"
                  "enum":
                    - "low"
                    - "medium"
                    - "high"
                    - "critical"
                  "example": "high"
                "details":
                  "type": "object"
                  "properties":
                    "userId":
                      "type": "string"
                    "resource":
                      "type": "string"
                    "ipAddress":
                      "type": "string"
                    "userAgent":
                      "type": "string"
                    "action":
                      "type": "string"
                    "reason":
                      "type": "string"
            "example":
              "eventType": "unauthorized_access_attempt"
              "severity": "high"
              "details":
                "userId": "685acbe0e129932fbb7a0fc2"
                "resource": "admin-panel"
                "ipAddress": "192.168.1.100"
                "action": "blocked"
                "reason": "Insufficient permissions"
      "responses":
        "200":
          "description": "Security event logged"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "message":
                    "type": "string"
                    "example": "Security event logged"
                  "event":
                    "type": "object"
                    "properties":
                      "_id":
                        "type": "string"
                      "eventType":
                        "type": "string"
                      "severity":
                        "type": "string"
                      "timestamp":
                        "type": "string"
                        "format": "date-time"
              "example":
                "success": true
                "message": "Security event recorded"
                "eventId": "evt_abc123"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
      "x-display-name": "Log security event"
      "x-sdk-method": "logSecurityEvent"
  "/api/realtime/projects/{projectId}/analytics":
    "get":
      "tags":
        - "realtimeAnalytics"
      "summary": "Get project real-time analytics"
      "operationId": "realtimeAnalytics.getProject"
      "description": "Returns real-time metrics for a specific project (active connections, events, etc.)"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
            "example": "685ad30be129932fbb7a1047"
          "description": "Project ID (MongoDB ObjectId) to get real-time analytics for."
      "responses":
        "200":
          "description": "Project analytics data"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "projectId":
                    "type": "string"
                  "activeConnections":
                    "type": "integer"
                    "example": 42
                  "totalEvents":
                    "type": "integer"
                    "example": 15234
                  "lastActivity":
                    "type": "string"
                    "format": "date-time"
                  "timestamp":
                    "type": "string"
                    "format": "date-time"
              "example":
                "projectId": "685ad30be129932fbb7a1047"
                "activeConnections": 42
                "totalEvents": 15234
                "lastActivity": "2024-01-15T10:00:00.000Z"
                "timestamp": "2024-01-15T10:00:00.000Z"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "404":
          "description": "Project not found (exact backend message)."
          "$ref": "#/components/responses/ProjectNotFound"
      "x-display-name": "Get project real-time analytics"
      "x-sdk-method": "getProject"
  "/api/realtime/projects/{projectId}/active-users":
    "get":
      "tags":
        - "realtimeAnalytics"
      "summary": "Get active users for a project"
      "operationId": "realtimeAnalytics.getActiveUsers"
      "description": "Returns list of currently connected users"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
      "responses":
        "200":
          "description": "List of active users"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "users":
                    "type": "array"
                    "items":
                      "type": "object"
                      "properties":
                        "userId":
                          "type": "string"
                        "connectedAt":
                          "type": "string"
                          "format": "date-time"
                        "socketId":
                          "type": "string"
                  "count":
                    "type": "integer"
                  "timestamp":
                    "type": "string"
                    "format": "date-time"
              "example":
                "users": []
                "count": 0
                "timestamp": "2024-01-15T10:00:00.000Z"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "404":
          "description": "Project not found (exact backend message)."
          "$ref": "#/components/responses/ProjectNotFound"
      "x-display-name": "Get active users for a project"
      "x-sdk-method": "getActiveUsers"
  "/api/realtime/projects/{projectId}/presence":
    "post":
      "tags":
        - "realtimeAnalytics"
      "summary": "Check presence status for users"
      "operationId": "realtimeAnalytics.checkUserPresence"
      "description": "Returns online status for specified user IDs"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
      "requestBody":
        "required": true
        "description": "Array of user IDs to check presence for."
        "content":
          "application/json":
            "schema":
              "type": "object"
              "required":
                - "userIds"
              "properties":
                "userIds":
                  "type": "array"
                  "items":
                    "type": "string"
                  "example":
                    - "685acbe0e129932fbb7a0fc2"
                    - "685acbe0e129932fbb7a0fc3"
            "example":
              "userIds":
                - "685acbe0e129932fbb7a0fc2"
                - "685acbe0e129932fbb7a0fc3"
      "responses":
        "200":
          "description": "Presence status for each user"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "presence":
                    "type": "object"
                    "additionalProperties":
                      "type": "object"
                      "properties":
                        "online":
                          "type": "boolean"
                        "lastSeen":
                          "type": "string"
                          "format": "date-time"
                  "timestamp":
                    "type": "string"
                    "format": "date-time"
              "example":
                "presence": {}
                "timestamp": "2024-01-15T10:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "404":
          "description": "Project not found (exact backend message)."
          "$ref": "#/components/responses/ProjectNotFound"
      "x-display-name": "Check presence status for users"
      "x-sdk-method": "checkUserPresence"
  "/api/realtime/projects/{projectId}/throughput":
    "get":
      "tags":
        - "realtimeAnalytics"
      "summary": "Get event throughput metrics"
      "operationId": "realtimeAnalytics.getEventThroughput"
      "description": "Returns event throughput for a project"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "window"
          "in": "query"
          "schema":
            "type": "integer"
            "default": 60000
          "description": "Time window in milliseconds"
      "responses":
        "200":
          "description": "Throughput metrics"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "windowMs":
                    "type": "integer"
                    "example": 60000
                  "totalEvents":
                    "type": "integer"
                    "example": 523
                  "eventsPerSecond":
                    "type": "number"
                    "example": 8.72
                  "byType":
                    "type": "object"
                    "additionalProperties":
                      "type": "integer"
                  "timestamp":
                    "type": "string"
                    "format": "date-time"
              "example":
                "windowMs": 60000
                "totalEvents": 523
                "eventsPerSecond": 8.72
                "byType": {}
                "timestamp": "2024-01-15T10:00:00.000Z"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "404":
          "description": "Project not found (exact backend message)."
          "$ref": "#/components/responses/ProjectNotFound"
      "x-display-name": "Get event throughput metrics"
      "x-sdk-method": "getEventThroughput"
  "/api/realtime/projects/{projectId}/history":
    "get":
      "tags":
        - "realtimeAnalytics"
      "summary": "Get historical analytics"
      "operationId": "realtimeAnalytics.getHistoricalAnalytics"
      "description": "Returns historical analytics for charting"
      "security":
        - "BearerToken": []
      "parameters":
        - "name": "projectId"
          "in": "path"
          "required": true
          "schema":
            "type": "string"
          "description": "Project ID."
        - "name": "period"
          "in": "query"
          "schema":
            "type": "string"
            "enum":
              - "hour"
              - "day"
              - "week"
            "default": "hour"
          "description": "Time period for historical data"
      "responses":
        "200":
          "description": "Historical analytics data"
          "content":
            "application/json":
              "schema":
                "type": "object"
                "properties":
                  "projectId":
                    "type": "string"
                  "period":
                    "type": "string"
                  "data":
                    "type": "array"
                    "items":
                      "type": "object"
                      "properties":
                        "timestamp":
                          "type": "string"
                          "format": "date-time"
                        "connections":
                          "type": "integer"
                        "events":
                          "type": "integer"
                  "generatedAt":
                    "type": "string"
                    "format": "date-time"
              "example":
                "projectId": "685ad30be129932fbb7a1047"
                "period": "hour"
                "data": []
                "generatedAt": "2024-01-15T10:00:00.000Z"
        "400":
          "description": "Bad request or validation error."
          "$ref": "#/components/responses/BadRequest"
        "401":
          "description": "Authentication required or invalid token."
          "$ref": "#/components/responses/Unauthorized"
        "404":
          "description": "Project not found (exact backend message)."
          "$ref": "#/components/responses/ProjectNotFound"
      "x-display-name": "Get historical analytics"
      "x-sdk-method": "getHistoricalAnalytics"
"components":
  "securitySchemes":
    "BearerToken":
      "type": "http"
      "scheme": "bearer"
      "bearerFormat": "JWT"
      "description": "JWT Bearer token for app and user operations. Can be used instead of or alongside ApiKeyAuth for app operations.


        **Implementation Status**: ✅ Fully implemented in all app-scoped endpoints.


        **How it works**:

        - Provide JWT token in Authorization: Bearer <token> header

        - Token is obtained from authentication endpoints (/api/auth/login, /api/auth/register, etc.)

        - Token contains user ID and access context

        - Project access is validated for the authenticated user


        **When to use**:

        - User-facing applications

        - When you need user identity and context

        - When you want role-based access control (RBAC)

        - When you need audit trails with user information


        **Note**: If both Authorization Bearer token and X-API-Key are provided, JWT authentication is tried first.\n"
    "InternalApiKey":
      "type": "apiKey"
      "in": "header"
      "name": "X-Internal-Api-Key"
      "description": "Platform internal key (INTERNAL_API_KEY). Not for public SDKs.\n"
    "ApiKeyAuth":
      "type": "apiKey"
      "in": "header"
      "name": "X-API-Key"
      "description": "Project-level API key for programmatic access.

        Used for server-to-server integrations and SDK-based access.

        Can be used instead of or alongside BearerToken (JWT token).


        **Implementation Status**: ✅ Fully implemented in all app-scoped endpoints.


        **How it works**:

        - Provide API key in X-API-Key header

        - API key must be active and not expired

        - API key must have appropriate permissions for the resource/action

        - API key is rate-limited per key configuration


        **When to use**:

        - Server-to-server integrations

        - SDK-based access

        - Automated scripts and background jobs

        - Programmatic API access without user context


        **Permissions**: API keys can have permissions for:

        - `database` - Data and collection operations

        - `storage` - File and bucket operations

        - `functions` - Function execution

        - `auth` - Authentication operations

        - `realtime` - Real-time operations


        **Rate Limiting**: Each API key has configurable rate limits (default: 1000 requests/hour).


        **Obtain from**: Create and manage API keys in the dashboard.


        **Note**: If both Authorization Bearer token and X-API-Key are provided, JWT authentication is tried first.\n"
  "schemas":
    "AppRoleFeaturePermissions":
      "type": "object"
      "description": |
        Per-role feature toggles for app JWTs: `{ [resource]: { [action]: boolean } }`.
        Use resource and action names that match the public API contract (see multi-role guide and simulate-permissions).
        **Messaging** accepts legacy keys (`email`, `sms`, `push`, …) and newer names (`send_email`, `send_sms`, …) as synonyms.
        Common resources: `messaging`, `integration`, `functions`, `data`, `search`, `usage`, `storage`, `chat`, `realtime`, `roleElevation`, `webhooks`.
      "properties": {}
      "additionalProperties":
        "type": "object"
        "additionalProperties":
          "type": "boolean"
      "example":
        "messaging":
          "email": true
          "sms": true
          "push": false
        "integration":
          "read": true
          "execute": true
    "AppRoleCollectionCrudAction":
      "type": "string"
      "description": "A single CRUD-style action on a collection."
      "enum":
        - "create"
        - "read"
        - "update"
        - "delete"
    "AppRoleCollectionPermissionActionsArray":
      "type": "array"
      "description": "Shorthand list of CRUD actions allowed on the collection."
      "items":
        "$ref": "#/components/schemas/AppRoleCollectionCrudAction"
    "AppRoleCollectionPermissionWithConditions":
      "type": "object"
      "description": "Explicit actions plus optional filter conditions for scoped access."
      "properties":
        "actions":
          "type": "array"
          "items":
            "$ref": "#/components/schemas/AppRoleCollectionCrudAction"
        "conditions":
          "type": "object"
    "AppRoleCollectionPermissionValue":
      "description": "Per-collection permission: either a CRUD action array or an object with `actions` and optional `conditions`."
      "oneOf":
        - "$ref": "#/components/schemas/AppRoleCollectionPermissionActionsArray"
        - "$ref": "#/components/schemas/AppRoleCollectionPermissionWithConditions"
    "RegisterRequest":
      "description": "Request body for app user registration (email, password, name, projectId)."
      "type": "object"
      "required":
        - "email"
        - "password"
        - "firstName"
        - "lastName"
      "properties":
        "email":
          "type": "string"
          "format": "email"
          "example": "john.doe@mudbase.dev"
        "password":
          "type": "string"
          "minLength": 8
          "example": "SecurePass123!"
        "firstName":
          "type": "string"
          "example": "John"
        "lastName":
          "type": "string"
          "example": "Doe"
        "orgName":
          "type": "string"
          "example": "Mudbase"
    "LoginRequest":
      "description": "Credentials for local email/password sign-in (email and password)."
      "type": "object"
      "required":
        - "email"
        - "password"
      "properties":
        "email":
          "type": "string"
          "format": "email"
          "example": "john.doe@mudbase.dev"
        "password":
          "type": "string"
          "example": "SecurePass123!"
    "AuthResponse":
      "description": "Response after successful login or registration (token, refreshToken, user)."
      "type": "object"
      "properties":
        "message":
          "type": "string"
        "token":
          "type": "string"
          "description": "JWT access token (use in Authorization Bearer header)"
        "refreshToken":
          "type": "string"
          "description": "JWT refresh token (use with POST /api/auth/refresh to get new token pair)"
        "expiresIn":
          "type": "integer"
          "description": "Access token TTL in seconds (e.g. 1800 for 30 minutes)"
        "user":
          "$ref": "#/components/schemas/User"
    "SessionResponse":
      "description": "Current session with user and authenticated flag."
      "type": "object"
      "properties":
        "user":
          "$ref": "#/components/schemas/User"
        "authenticated":
          "type": "boolean"
    "MagicLinkRequest":
      "description": "Email and projectId to send a passwordless magic link; optional redirectUrl."
      "type": "object"
      "required":
        - "email"
        - "projectId"
      "properties":
        "email":
          "type": "string"
          "format": "email"
        "projectId":
          "type": "string"
        "redirectUrl":
          "type": "string"
    "OTPSendRequest":
      "description": "Request to send OTP via SMS or email for the given project."
      "type": "object"
      "required":
        - "projectId"
        - "method"
      "properties":
        "phone":
          "type": "string"
        "email":
          "type": "string"
          "format": "email"
        "projectId":
          "type": "string"
        "method":
          "type": "string"
          "enum":
            - "sms"
            - "email"
    "OTPVerifyRequest":
      "description": "OTP code and identifier (phone/email) for verification."
      "type": "object"
      "required":
        - "projectId"
        - "otp"
      "properties":
        "identifier":
          "type": "string"
        "otp":
          "type": "string"
        "projectId":
          "type": "string"
    "User":
      "description": "Authenticated user profile (id, email, name, roles, project access)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
        "email":
          "type": "string"
          "format": "email"
        "firstName":
          "type": "string"
        "lastName":
          "type": "string"
        "fullName":
          "type": "string"
        "avatar":
          "type": "string"
        "role":
          "type": "string"
          "enum":
            - "owner"
            - "admin"
            - "member"
            - "viewer"
        "emailVerified":
          "type": "boolean"
        "phoneVerified":
          "type": "boolean"
        "twoFactorEnabled":
          "type": "boolean"
        "lastLogin":
          "type": "string"
          "format": "date-time"
        "createdAt":
          "type": "string"
          "format": "date-time"
        "updatedAt":
          "type": "string"
          "format": "date-time"
        "org":
          "$ref": "#/components/schemas/OrganizationSummary"
    "UpdateUserRequest":
      "description": "Fields to update on the user profile (firstName, lastName, avatar)."
      "type": "object"
      "properties":
        "firstName":
          "type": "string"
        "lastName":
          "type": "string"
        "avatar":
          "type": "string"
    "ChangePasswordRequest":
      "description": "Current password and new password for change-password flow."
      "type": "object"
      "required":
        - "currentPassword"
        - "newPassword"
      "properties":
        "currentPassword":
          "type": "string"
        "newPassword":
          "type": "string"
          "minLength": 8
    "TwoFASetupResponse":
      "description": "2FA setup data (secret, QR code URL, manual entry key)."
      "type": "object"
      "properties":
        "secret":
          "type": "string"
        "qrCode":
          "type": "string"
        "manualEntryKey":
          "type": "string"
    "Organization":
      "description": "Organization (org) entity with plan, usage, limits, and billing."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
        "name":
          "type": "string"
        "slug":
          "type": "string"
        "description":
          "type": "string"
        "logo":
          "type": "string"
          "format": "uri"
          "description": "Optional logo URL. Org-related emails use the platform logo (env); this field is for legacy or future UI use only."
        "website":
          "type": "string"
        "plan":
          "$ref": "#/components/schemas/Plan"
        "usage":
          "$ref": "#/components/schemas/Usage"
        "limits":
          "$ref": "#/components/schemas/Limits"
        "billing":
          "$ref": "#/components/schemas/Billing"
        "settings":
          "type": "object"
        "createdAt":
          "type": "string"
          "format": "date-time"
        "updatedAt":
          "type": "string"
          "format": "date-time"
    "OrganizationSummary":
      "description": "Short organization reference (id, name, slug)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
        "name":
          "type": "string"
        "slug":
          "type": "string"
    "UpdateOrganizationRequest":
      "description": "Fields to update on an organization (name, description, logo, website, settings)."
      "type": "object"
      "properties":
        "name":
          "type": "string"
        "description":
          "type": "string"
        "logo":
          "type": "string"
          "format": "uri"
          "description": "Optional logo URL. Not used for emails (org emails use platform logo)."
        "website":
          "type": "string"
        "settings":
          "type": "object"
    "InviteMemberRequest":
      "description": "Email and role for inviting a member to an organization."
      "type": "object"
      "required":
        - "email"
        - "role"
      "properties":
        "email":
          "type": "string"
          "format": "email"
        "role":
          "type": "string"
          "enum":
            - "admin"
            - "member"
            - "viewer"
    "Plan":
      "description": "Subscription plan (name, price, currency, interval, features)."
      "type": "object"
      "properties":
        "name":
          "type": "string"
        "price":
          "type": "number"
        "currency":
          "type": "string"
        "interval":
          "type": "string"
        "features":
          "type": "array"
          "items":
            "type": "string"
    "Usage":
      "description": "Usage counts (projects, users, storage, bandwidth, apiCalls, dbReads, dbWrites)."
      "type": "object"
      "properties":
        "projects":
          "type": "integer"
        "users":
          "type": "integer"
        "storage":
          "type": "integer"
        "bandwidth":
          "type": "integer"
        "apiCalls":
          "type": "integer"
        "dbReads":
          "type": "integer"
        "dbWrites":
          "type": "integer"
    "Limits":
      "description": "Limit values for plan (projects, users, storage, etc.)."
      "type": "object"
      "properties":
        "projects":
          "type": "integer"
        "users":
          "type": "integer"
        "storage":
          "type": "integer"
        "bandwidth":
          "type": "integer"
        "apiCalls":
          "type": "integer"
        "dbReads":
          "type": "integer"
        "dbWrites":
          "type": "integer"
    "Billing":
      "description": "Billing info (next billing date, payment method, last payment)."
      "type": "object"
      "properties":
        "nextBillingDate":
          "type": "string"
          "format": "date-time"
        "paymentMethod":
          "type": "string"
        "lastPayment":
          "type": "object"
          "properties":
            "amount":
              "type": "number"
            "date":
              "type": "string"
              "format": "date-time"
            "status":
              "type": "string"
    "UsageResponse":
      "description": "Response containing usage, limits, plan, and billing."
      "type": "object"
      "properties":
        "usage":
          "$ref": "#/components/schemas/Usage"
        "limits":
          "$ref": "#/components/schemas/Limits"
        "plan":
          "$ref": "#/components/schemas/Plan"
        "billing":
          "$ref": "#/components/schemas/Billing"
    "Project":
      "description": "Project entity (id, name, config, usage)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
        "name":
          "type": "string"
        "description":
          "type": "string"
        "slug":
          "type": "string"
        "org":
          "type": "string"
        "auth":
          "$ref": "#/components/schemas/AuthConfig"
        "database":
          "$ref": "#/components/schemas/DatabaseConfig"
        "storage":
          "$ref": "#/components/schemas/StorageConfig"
        "settings":
          "$ref": "#/components/schemas/ProjectSettings"
        "usage":
          "$ref": "#/components/schemas/ProjectUsage"
        "createdAt":
          "type": "string"
          "format": "date-time"
        "updatedAt":
          "type": "string"
          "format": "date-time"
    "ProjectSettings":
      "type": "object"
      "description": "Project-level settings. Toggles for verification and default user status apply to app and role-based signup.\n"
      "properties":
        "allowAnonymousAuth":
          "type": "boolean"
          "default": true
          "description": "Allow anonymous (unauthenticated) users"
        "requireEmailVerification":
          "type": "boolean"
          "default": true
          "description": "When true, users who sign up with email do not receive a token until they verify their email; login is blocked until verified."
        "requirePhoneVerification":
          "type": "boolean"
          "default": false
          "description": "When true, users who sign in with phone (e.g. OTP) must have verified their phone before receiving a token."
        "defaultUserAccountStatus":
          "type": "string"
          "enum":
            - "pending"
            - "active"
          "default": "active"
          "description": "Default account status for new signups. **active** = user can use the app immediately.

            **pending** = user must be approved by an org owner/admin (PATCH org user status to active) before they can perform protected operations.\n"
        "enableRealtime":
          "type": "boolean"
          "default": true
        "enableStorage":
          "type": "boolean"
          "default": true
        "enableFunctions":
          "type": "boolean"
          "default": false
    "CreateProjectRequest":
      "type": "object"
      "required":
        - "name"
      "properties":
        "name":
          "type": "string"
          "example": "Mudbase Platform"
        "description":
          "type": "string"
          "example": "Main platform for Mudbase services"
        "slug":
          "type": "string"
          "example": "mudbase-platform"
      "description": "Project settings (requireEmailVerification, requirePhoneVerification, defaultUserAccountStatus) are not accepted on create; use PATCH to update settings after creation.\n"
    "UpdateProjectRequest":
      "description": "Fields to update on a project (name, description, logoUrl, settings, auth)."
      "type": "object"
      "properties":
        "name":
          "type": "string"
          "example": "Mudbase Platform"
        "description":
          "type": "string"
          "example": "Main platform for Mudbase services"
        "logoUrl":
          "type": "string"
          "format": "uri"
          "description": "Public URL for the project logo/brand image. Prefer uploading via **POST /api/projects/{id}/logo** (stored under logo/project/ in platform storage). Used in project-related emails.\n"
        "settings":
          "$ref": "#/components/schemas/ProjectSettings"
          "description": "Update project settings. Toggle **requireEmailVerification** (default true), **requirePhoneVerification** (default false),

            and **defaultUserAccountStatus** (pending | active, default active) to control how new users sign up and when they can sign in.\n"
          "example":
            "requireEmailVerification": true
            "requirePhoneVerification": false
            "defaultUserAccountStatus": "active"
        "auth":
          "$ref": "#/components/schemas/AuthConfig"
    "AuthConfig":
      "description": "Project auth configuration (providers, notifyOnNewSignIn)."
      "type": "object"
      "properties":
        "providers":
          "type": "array"
          "items":
            "$ref": "#/components/schemas/AuthProvider"
        "notifyOnNewSignIn":
          "type": "boolean"
          "default": false
          "description": "When true, a \"new sign-in detected\" email is sent to the user on each app sign-in (local or OAuth).

            Counts against the org's messaging/email plan quota. Default false. Organization-based sign-in always sends this email (no quota deduction).\n"
    "AuthProvider":
      "description": "Single auth provider (name, enabled, config)."
      "type": "object"
      "properties":
        "name":
          "type": "string"
        "enabled":
          "type": "boolean"
        "config":
          "type": "object"
    "DatabaseConfig":
      "description": "Database configuration (collections list)."
      "type": "object"
      "properties":
        "collections":
          "type": "array"
          "items":
            "type": "string"
    "StorageConfig":
      "description": "Storage configuration (buckets list)."
      "type": "object"
      "properties":
        "buckets":
          "type": "array"
          "items":
            "type": "string"
    "ProjectUsage":
      "description": "Project usage counts (apiCalls, storage, bandwidth, dbReads, dbWrites)."
      "type": "object"
      "properties":
        "apiCalls":
          "type": "integer"
        "storage":
          "type": "integer"
        "bandwidth":
          "type": "integer"
        "dbReads":
          "type": "integer"
        "dbWrites":
          "type": "integer"
    "ProjectUsageResponse":
      "description": "Response with project usage and limits."
      "type": "object"
      "properties":
        "usage":
          "$ref": "#/components/schemas/ProjectUsage"
        "limits":
          "$ref": "#/components/schemas/Limits"
    "Collection":
      "description": "Collection schema (id, name, slug, project, fields, permissions, settings)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
        "name":
          "type": "string"
        "slug":
          "type": "string"
        "project":
          "type": "string"
        "fields":
          "type": "array"
          "items":
            "$ref": "#/components/schemas/Field"
        "permissions":
          "type": "array"
          "items":
            "$ref": "#/components/schemas/Permission"
        "settings":
          "type": "object"
        "createdAt":
          "type": "string"
          "format": "date-time"
        "updatedAt":
          "type": "string"
          "format": "date-time"
    "CreateCollectionRequest":
      "description": "Payload to create a collection (name, slug, fields, permissions, settings)."
      "type": "object"
      "required":
        - "name"
        - "fields"
      "properties":
        "name":
          "type": "string"
        "slug":
          "type": "string"
        "fields":
          "type": "array"
          "items":
            "$ref": "#/components/schemas/Field"
        "permissions":
          "type": "array"
          "items":
            "$ref": "#/components/schemas/Permission"
        "settings":
          "type": "object"
    "UpdateCollectionRequest":
      "description": "Fields to update on a collection (name, fields, permissions, settings)."
      "type": "object"
      "properties":
        "name":
          "type": "string"
        "fields":
          "type": "array"
          "items":
            "$ref": "#/components/schemas/Field"
        "permissions":
          "type": "array"
          "items":
            "$ref": "#/components/schemas/Permission"
        "settings":
          "type": "object"
    "Field":
      "description": "Collection field definition (name, type, required, unique, default, validation)."
      "type": "object"
      "required":
        - "name"
        - "type"
      "properties":
        "name":
          "type": "string"
        "type":
          "type": "string"
          "enum":
            - "string"
            - "number"
            - "boolean"
            - "date"
            - "datetime"
            - "email"
            - "url"
            - "text"
            - "array"
            - "object"
            - "reference"
            - "file"
            - "enum"
            - "json"
        "required":
          "type": "boolean"
        "unique":
          "type": "boolean"
        "default":
          "oneOf":
            - "type": "string"
            - "type": "number"
            - "type": "boolean"
        "validation":
          "type": "object"
        "ui":
          "type": "object"
    "Permission":
      "description": "Role-based permission (role, actions, fields, condition)."
      "type": "object"
      "properties":
        "role":
          "type": "string"
        "actions":
          "type": "array"
          "items":
            "type": "string"
            "enum":
              - "create"
              - "read"
              - "update"
              - "delete"
        "fields":
          "type": "array"
          "items":
            "type": "string"
        "condition":
          "type": "object"
    "DataListResponse":
      "description": "Paginated list of documents from a collection."
      "type": "object"
      "properties":
        "data":
          "type": "array"
          "items":
            "type": "object"
            "description": "Document from the collection (includes _id, createdAt, updatedAt, and all collection fields). Additional fields are defined in the collection schema."
            "properties":
              "_id":
                "type": "string"
                "description": "Document ID (MongoDB ObjectId) - use this as documentId in API calls"
                "example": "696bbe5b99eeb7f929a93e0b"
              "createdAt":
                "type": "string"
                "format": "date-time"
                "description": "Document creation timestamp"
              "updatedAt":
                "type": "string"
                "format": "date-time"
                "description": "Document last update timestamp"
            "additionalProperties": true
        "pagination":
          "$ref": "#/components/schemas/Pagination"
    "DataResponse":
      "description": "Single document or message and data payload."
      "type": "object"
      "properties":
        "message":
          "type": "string"
        "data":
          "type": "object"
    "Pagination":
      "description": "Pagination metadata (page, limit, total, totalPages)."
      "type": "object"
      "properties":
        "page":
          "type": "integer"
        "limit":
          "type": "integer"
        "total":
          "type": "integer"
        "totalPages":
          "type": "integer"
    "UploadFilesToBucketMetadataRequest":
      "description": "Optional metadata for file upload (folder, tags). Use with application/json when not sending binary files."
      "type": "object"
      "properties":
        "folder":
          "type": "string"
        "tags":
          "type": "array"
          "items":
            "type": "string"
    "UploadFilesToBucketRequest":
      "description": "Multipart form body for uploading files to a bucket (files array required; optional folder and tags)."
      "type": "object"
      "required":
        - "files"
      "properties":
        "files":
          "type": "array"
          "items":
            "type": "string"
            "format": "binary"
        "folder":
          "type": "string"
        "tags":
          "type": "array"
          "items":
            "type": "string"
    "FileUploadResponse":
      "description": "Response after file upload (message, file metadata)."
      "type": "object"
      "properties":
        "message":
          "type": "string"
        "file":
          "$ref": "#/components/schemas/FileMetadata"
    "FileMetadata":
      "description": "File metadata (id, filename, originalName, mimeType, size, url)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
        "filename":
          "type": "string"
        "originalName":
          "type": "string"
        "mimeType":
          "type": "string"
        "size":
          "type": "integer"
        "url":
          "type": "string"
        "publicUrl":
          "type": "string"
        "bucket":
          "type": "string"
        "projectId":
          "type": "string"
        "isPublic":
          "type": "boolean"
        "uploadedBy":
          "type": "string"
        "createdAt":
          "type": "string"
          "format": "date-time"
    "FileListResponse":
      "description": "Paginated list of file metadata."
      "type": "object"
      "properties":
        "files":
          "type": "array"
          "items":
            "$ref": "#/components/schemas/FileMetadata"
        "pagination":
          "$ref": "#/components/schemas/Pagination"
    "ApiKey":
      "description": "API key entity (id, name, project, permissions, rateLimit, usage, isActive, expiresAt)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
        "name":
          "type": "string"
        "project":
          "$ref": "#/components/schemas/ProjectSummary"
        "permissions":
          "type": "array"
          "items":
            "$ref": "#/components/schemas/ApiKeyPermission"
        "rateLimit":
          "$ref": "#/components/schemas/RateLimit"
        "usage":
          "$ref": "#/components/schemas/ApiKeyUsage"
        "isActive":
          "type": "boolean"
        "expiresAt":
          "type": "string"
          "format": "date-time"
        "createdBy":
          "$ref": "#/components/schemas/UserSummary"
        "createdAt":
          "type": "string"
          "format": "date-time"
    "ApiKeyWithSecret":
      "description": "API key with secret (returned only on create; store secret securely)."
      "allOf":
        - "$ref": "#/components/schemas/ApiKey"
        - "type": "object"
          "properties":
            "secret":
              "type": "string"
    "ApiKeyPermission":
      "description": "Permission scope (resource, actions)."
      "type": "object"
      "required":
        - "resource"
        - "actions"
      "properties":
        "resource":
          "type": "string"
          "enum":
            - "auth"
            - "database"
            - "storage"
            - "functions"
            - "realtime"
            - "messaging"
          "description": "Resource scope for this permission (auth, database, storage, functions, realtime, messaging)"
        "actions":
          "type": "array"
          "items":
            "type": "string"
            "enum":
              - "create"
              - "read"
              - "update"
              - "delete"
          "description": "Allowed actions on the resource"
    "CreateApiKeyRequest":
      "description": "Payload to create an API key (name, projectId, permissions, rateLimit, expiresAt)."
      "type": "object"
      "required":
        - "name"
        - "projectId"
      "properties":
        "name":
          "type": "string"
          "minLength": 2
          "maxLength": 100
        "projectId":
          "type": "string"
          "pattern": "^[0-9a-fA-F]{24}$"
          "description": "MongoDB ObjectId of the project"
        "permissions":
          "type": "array"
          "items":
            "$ref": "#/components/schemas/ApiKeyPermission"
          "description": "Optional. Permission objects (resource + actions). Omit or pass [] for full access (all resources and actions). Include only the entries you want; remove resources or actions to restrict the key."
        "rateLimit":
          "$ref": "#/components/schemas/RateLimit"
        "expiresAt":
          "type": "string"
          "format": "date-time"
          "description": "Optional. When provided, must be a valid ISO 8601 date-time in the future. Omit for no expiration."
    "UpdateApiKeyRequest":
      "description": "Fields to update on an API key (name, permissions, rateLimit, isActive)."
      "type": "object"
      "properties":
        "name":
          "type": "string"
          "minLength": 2
          "maxLength": 100
        "permissions":
          "type": "array"
          "items":
            "$ref": "#/components/schemas/ApiKeyPermission"
        "rateLimit":
          "$ref": "#/components/schemas/RateLimit"
        "isActive":
          "type": "boolean"
    "RateLimit":
      "description": "Rate limit (requests per window)."
      "type": "object"
      "properties":
        "requests":
          "type": "integer"
        "window":
          "type": "integer"
    "ApiKeyUsage":
      "description": "API key usage (request count, lastUsed)."
      "type": "object"
      "properties":
        "requests":
          "type": "integer"
        "lastUsed":
          "type": "string"
          "format": "date-time"
    "ApiKeyUsageResponse":
      "description": "API key usage and status response."
      "type": "object"
      "properties":
        "usage":
          "$ref": "#/components/schemas/ApiKeyUsage"
        "rateLimit":
          "$ref": "#/components/schemas/RateLimit"
        "isActive":
          "type": "boolean"
        "expiresAt":
          "type": "string"
          "format": "date-time"
    "ProjectSummary":
      "description": "Short project reference (id, name, slug)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
        "name":
          "type": "string"
        "slug":
          "type": "string"
    "UserSummary":
      "description": "Short user reference (id, firstName, lastName, email)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
        "firstName":
          "type": "string"
        "lastName":
          "type": "string"
        "email":
          "type": "string"
          "format": "email"
    "CreateBucketRequest":
      "description": "Payload to create a bucket (name, isPublic, settings)."
      "type": "object"
      "required":
        - "name"
      "properties":
        "name":
          "type": "string"
          "description": "The name of the bucket"
        "isPublic":
          "type": "boolean"
          "default": false
          "description": "Whether the bucket is publicly accessible"
        "settings":
          "type": "object"
          "description": "Additional bucket settings"
    "BucketResponse":
      "description": "Response after bucket create/update (success, message, bucket)."
      "type": "object"
      "properties":
        "success":
          "type": "boolean"
        "message":
          "type": "string"
        "bucket":
          "$ref": "#/components/schemas/Bucket"
    "Bucket":
      "description": "Bucket entity (id, name, projectId, isPublic, createdAt, updatedAt)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
        "name":
          "type": "string"
        "projectId":
          "type": "string"
        "isPublic":
          "type": "boolean"
        "createdAt":
          "type": "string"
          "format": "date-time"
        "updatedAt":
          "type": "string"
          "format": "date-time"
    "BucketListResponse":
      "description": "Paginated list of buckets."
      "type": "object"
      "properties":
        "success":
          "type": "boolean"
        "buckets":
          "type": "array"
          "items":
            "$ref": "#/components/schemas/Bucket"
        "pagination":
          "$ref": "#/components/schemas/Pagination"
    "UpdateBucketRequest":
      "description": "Fields to update on a bucket (name, isPublic, settings)."
      "type": "object"
      "properties":
        "name":
          "type": "string"
          "description": "Updated name of the bucket"
        "isPublic":
          "type": "boolean"
          "description": "Update whether the bucket is publicly accessible"
        "settings":
          "type": "object"
          "description": "Updated bucket settings"
    "FileResponse":
      "description": "Response with file metadata (success, file)."
      "type": "object"
      "properties":
        "success":
          "type": "boolean"
        "file":
          "$ref": "#/components/schemas/FileMetadata"
    "SignedUrlResponse":
      "description": "Signed URL for temporary file access (url, expiresAt or expiresIn)."
      "type": "object"
      "properties":
        "success":
          "type": "boolean"
        "url":
          "type": "string"
          "description": "Signed URL for file access"
        "expiresAt":
          "type": "string"
          "format": "date-time"
          "description": "Expiration time of the signed URL (optional - some endpoints return expiresIn instead)"
        "expiresIn":
          "type": "integer"
          "description": "Time-to-live in seconds for the signed URL (optional)"
    "PresignedPostResponse":
      "description": "Presigned POST data for direct upload (key, url, fields, expiresIn)."
      "type": "object"
      "properties":
        "key":
          "type": "string"
          "description": "Object key (S3) clients should upload to"
        "url":
          "type": "string"
          "description": "URL to POST the multipart form to"
        "fields":
          "type": "object"
          "description": "Form fields required for the presigned POST (Policy, X-Amz-Signature, etc.)"
        "expiresIn":
          "type": "integer"
          "description": "Expiration of the presigned POST in seconds"
    "ConfirmUploadResponse":
      "description": "Result of upload confirmation (fileId, status, scan)."
      "type": "object"
      "properties":
        "fileId":
          "type": "string"
        "status":
          "type": "string"
          "enum":
            - "ok"
            - "quarantined"
            - "error"
        "scan":
          "type": "object"
          "description": "Virus scan result (provider, status, detections, raw analysis)"
          "properties":
            "status":
              "type": "string"
            "provider":
              "type": "string"
            "detections":
              "type": "integer"
            "analysis":
              "type": "object"
              "description": "Raw analysis object returned by the scanner (e.g., VirusTotal)"
    "WebhookListResponse":
      "description": "Paginated list of webhook logs."
      "type": "object"
      "properties":
        "webhooks":
          "type": "array"
          "items":
            "$ref": "#/components/schemas/WebhookLog"
        "total":
          "type": "integer"
        "page":
          "type": "integer"
        "limit":
          "type": "integer"
        "totalPages":
          "type": "integer"
    "WebhookLog":
      "description": "Single webhook delivery log (url, method, event, status, payload, response, duration, attempts)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
        "url":
          "type": "string"
        "method":
          "type": "string"
        "event":
          "type": "string"
        "status":
          "type": "string"
          "enum":
            - "success"
            - "failed"
            - "pending"
        "statusCode":
          "type": "integer"
        "payload":
          "type": "object"
        "response":
          "type": "object"
        "duration":
          "type": "integer"
        "attempts":
          "type": "integer"
        "error":
          "type": "string"
        "nextRetry":
          "type": "string"
          "format": "date-time"
        "createdAt":
          "type": "string"
          "format": "date-time"
    "TriggerWebhookRequest":
      "description": "Payload to trigger a webhook (projectId, url, event, payload, method)."
      "type": "object"
      "required":
        - "projectId"
        - "url"
        - "event"
        - "payload"
      "properties":
        "projectId":
          "type": "string"
        "url":
          "type": "string"
        "event":
          "type": "string"
        "payload":
          "type": "object"
        "method":
          "type": "string"
          "default": "POST"
    "WebhookStatsResponse":
      "description": "Webhook delivery stats (statusStats, eventStats, period)."
      "type": "object"
      "properties":
        "statusStats":
          "type": "array"
          "items":
            "type": "object"
            "properties":
              "_id":
                "type": "string"
              "count":
                "type": "integer"
              "avgDuration":
                "type": "number"
        "eventStats":
          "type": "array"
          "items":
            "type": "object"
            "properties":
              "_id":
                "type": "string"
              "count":
                "type": "integer"
              "successRate":
                "type": "number"
        "period":
          "type": "string"
    "FunctionListResponse":
      "description": "Paginated list of functions."
      "type": "object"
      "properties":
        "success":
          "type": "boolean"
        "data":
          "type": "object"
          "properties":
            "functions":
              "type": "array"
              "items":
                "$ref": "#/components/schemas/Function"
            "pagination":
              "$ref": "#/components/schemas/Pagination"
    "Function":
      "description": "Serverless function entity (id, name, description, projectId, trigger, stats, isActive)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
        "name":
          "type": "string"
        "description":
          "type": "string"
        "projectId":
          "type": "string"
        "trigger":
          "$ref": "#/components/schemas/FunctionTrigger"
        "stats":
          "$ref": "#/components/schemas/FunctionStats"
        "isActive":
          "type": "boolean"
        "createdBy":
          "type": "string"
        "createdAt":
          "type": "string"
          "format": "date-time"
        "updatedAt":
          "type": "string"
          "format": "date-time"
    "CreateFunctionRequest":
      "description": "Payload to create a function (name, description, code, trigger, environment)."
      "type": "object"
      "required":
        - "name"
        - "code"
        - "trigger"
      "properties":
        "name":
          "type": "string"
        "description":
          "type": "string"
        "code":
          "type": "string"
          "description": "Function body (async, has access to payload, db, files, messaging, wallet, utils, env, console)"
        "trigger":
          "$ref": "#/components/schemas/FunctionTrigger"
        "environment":
          "type": "object"
          "additionalProperties":
            "type": "string"
          "description": "Per-function env vars injected into sandbox"
    "UpdateFunctionRequest":
      "description": "Fields to update on a function (name, description, code, trigger, environment, isActive, limits, retryPolicy)."
      "type": "object"
      "properties":
        "name":
          "type": "string"
        "description":
          "type": "string"
        "code":
          "type": "string"
        "trigger":
          "$ref": "#/components/schemas/FunctionTrigger"
        "environment":
          "type": "object"
        "isActive":
          "type": "boolean"
        "limits":
          "type": "object"
          "properties":
            "timeout":
              "type": "integer"
              "description": "Max execution time in ms (default 30000)"
            "maxPayloadSize":
              "type": "integer"
              "description": "Max payload size in bytes (default 1MB)"
            "maxExecutionsPerMinute":
              "type": "integer"
            "maxExecutionsPerHour":
              "type": "integer"
        "retryPolicy":
          "type": "object"
          "properties":
            "enabled":
              "type": "boolean"
            "maxRetries":
              "type": "integer"
            "backoffMs":
              "type": "integer"
        "versionComment":
          "type": "string"
          "description": "Comment for version when code is updated"
    "FunctionTrigger":
      "description": "Function trigger config (type, event, schedule, path, method, collectionId, bucketId)."
      "type": "object"
      "required":
        - "type"
      "properties":
        "type":
          "type": "string"
          "enum":
            - "http"
            - "event"
            - "document"
            - "file"
            - "webhook"
            - "wallet"
            - "cron"
            - "messaging"
          "description": "Trigger type"
        "event":
          "type": "string"
          "description": "Event name (e.g. create, update, delete for document; uploaded, deleted for file; tx, balance for wallet)"
        "schedule":
          "type": "string"
          "description": "For cron - minutely, hourly, daily, weekly, or custom cron expression"
        "path":
          "type": "string"
          "description": "HTTP path for http triggers"
        "method":
          "type": "string"
          "enum":
            - "GET"
            - "POST"
            - "PUT"
            - "DELETE"
        "collectionId":
          "type": "string"
          "format": "objectid"
          "description": "For document triggers - filter by collection"
        "bucketId":
          "type": "string"
          "format": "objectid"
          "description": "For file triggers - filter by bucket"
    "FunctionStats":
      "description": "Function execution stats (total, successful, failed, avgExecutionTime, lastExecution)."
      "type": "object"
      "properties":
        "totalExecutions":
          "type": "integer"
        "successfulExecutions":
          "type": "integer"
        "failedExecutions":
          "type": "integer"
        "avgExecutionTime":
          "type": "number"
        "lastExecution":
          "type": "string"
          "format": "date-time"
    "FunctionResponse":
      "description": "Response containing a single function (success, data)."
      "type": "object"
      "properties":
        "success":
          "type": "boolean"
        "data":
          "$ref": "#/components/schemas/Function"
    "FunctionExecutionResponse":
      "description": "Response from function execution (success, result, error, executionTime)."
      "type": "object"
      "properties":
        "success":
          "type": "boolean"
        "data":
          "type": "object"
          "properties":
            "success":
              "type": "boolean"
            "result":
              "type": "object"
            "error":
              "type": "string"
            "executionTime":
              "type": "integer"
              "description": "Duration in milliseconds"
    "FunctionLogsResponse":
      "description": "Paginated function execution logs and stats."
      "type": "object"
      "properties":
        "success":
          "type": "boolean"
        "data":
          "type": "object"
          "properties":
            "executions":
              "type": "array"
              "items":
                "$ref": "#/components/schemas/FunctionExecution"
            "stats":
              "$ref": "#/components/schemas/FunctionStats"
    "FunctionExecution":
      "description": "Single function execution record (id, executedAt, executionTime, success, payload, result, error)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
        "executedAt":
          "type": "string"
          "format": "date-time"
        "executionTime":
          "type": "integer"
        "success":
          "type": "boolean"
        "payload":
          "type": "object"
        "result":
          "type": "object"
        "error":
          "type": "string"
        "triggerType":
          "type": "string"
        "triggerEvent":
          "type": "string"
        "invokedBy":
          "type": "string"
          "enum":
            - "manual"
            - "api_key"
            - "trigger"
            - "cron"
        "retryCount":
          "type": "integer"
    "PushNotificationRequest":
      "description": "Push notification payload (tokens, title, body, data, imageUrl)."
      "type": "object"
      "required":
        - "tokens"
        - "title"
        - "body"
      "properties":
        "tokens":
          "type": "array"
          "items":
            "type": "string"
        "title":
          "type": "string"
        "body":
          "type": "string"
        "data":
          "type": "object"
        "imageUrl":
          "type": "string"
    "EmailRequest":
      "description": "Email payload (to, subject, html, text, templateId, templateData)."
      "type": "object"
      "required":
        - "to"
        - "subject"
      "properties":
        "to":
          "oneOf":
            - "type": "string"
            - "type": "array"
              "items":
                "type": "string"
        "subject":
          "type": "string"
        "html":
          "type": "string"
        "text":
          "type": "string"
        "templateId":
          "type": "string"
        "templateData":
          "type": "object"
    "SMSRequest":
      "description": "SMS payload (to, message, from)."
      "type": "object"
      "required":
        - "to"
        - "message"
      "properties":
        "to":
          "type": "string"
        "message":
          "type": "string"
        "from":
          "type": "string"
    "MessageSentResponse":
      "description": "Response after sending a message (success, data with id, type, status, recipients, sentAt)."
      "type": "object"
      "properties":
        "success":
          "type": "boolean"
        "data":
          "type": "object"
          "properties":
            "_id":
              "type": "string"
            "type":
              "type": "string"
            "status":
              "type": "string"
            "recipients":
              "type": "integer"
            "successCount":
              "type": "integer"
            "failureCount":
              "type": "integer"
            "messageId":
              "type": "string"
            "sentAt":
              "type": "string"
              "format": "date-time"
    "MessageHistoryResponse":
      "description": "Paginated message history (messages, pagination)."
      "type": "object"
      "properties":
        "success":
          "type": "boolean"
        "data":
          "type": "object"
          "properties":
            "messages":
              "type": "array"
              "items":
                "$ref": "#/components/schemas/Message"
            "pagination":
              "$ref": "#/components/schemas/Pagination"
    "Message":
      "description": "Single message record (id, type, title, body, recipients, status, sentAt)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
        "type":
          "type": "string"
          "enum":
            - "push"
            - "email"
            - "sms"
        "title":
          "type": "string"
        "body":
          "type": "string"
        "subject":
          "type": "string"
        "recipients":
          "type": "integer"
        "successCount":
          "type": "integer"
        "failureCount":
          "type": "integer"
        "status":
          "type": "string"
          "enum":
            - "sent"
            - "failed"
            - "pending"
        "sentAt":
          "type": "string"
          "format": "date-time"
    "MessageStatsResponse":
      "description": "Message statistics (totalMessages, byType, byStatus, successRate, period)."
      "type": "object"
      "properties":
        "success":
          "type": "boolean"
        "data":
          "type": "object"
          "properties":
            "totalMessages":
              "type": "integer"
            "byType":
              "type": "object"
              "properties":
                "push":
                  "type": "integer"
                "email":
                  "type": "integer"
                "sms":
                  "type": "integer"
            "byStatus":
              "type": "object"
              "properties":
                "sent":
                  "type": "integer"
                "failed":
                  "type": "integer"
                "pending":
                  "type": "integer"
            "successRate":
              "type": "number"
            "period":
              "type": "object"
              "properties":
                "startDate":
                  "type": "string"
                  "format": "date-time"
                "endDate":
                  "type": "string"
                  "format": "date-time"
    "UsageStatsResponse":
      "description": "Usage statistics response."
      "type": "object"
      "properties":
        "usage":
          "$ref": "#/components/schemas/Usage"
        "limits":
          "$ref": "#/components/schemas/Limits"
        "plan":
          "$ref": "#/components/schemas/Plan"
        "period":
          "type": "string"
        "percentages":
          "type": "object"
          "properties":
            "apiCalls":
              "type": "number"
            "storage":
              "type": "number"
            "bandwidth":
              "type": "number"
    "ProjectUsageStatsResponse":
      "description": "Project-level usage stats (project, usage, period)."
      "type": "object"
      "properties":
        "project":
          "type": "object"
          "properties":
            "id":
              "type": "string"
            "name":
              "type": "string"
        "usage":
          "$ref": "#/components/schemas/ProjectUsage"
        "period":
          "type": "string"
    "UsageTrendsResponse":
      "description": "Usage trends over time (trends array, period)."
      "type": "object"
      "properties":
        "trends":
          "type": "array"
          "items":
            "type": "object"
            "properties":
              "_id":
                "type": "object"
                "properties":
                  "year":
                    "type": "integer"
                  "month":
                    "type": "integer"
                  "day":
                    "type": "integer"
              "apiCalls":
                "type": "integer"
              "storage":
                "type": "integer"
              "bandwidth":
                "type": "integer"
              "dbReads":
                "type": "integer"
              "dbWrites":
                "type": "integer"
        "period":
          "type": "string"
    "SearchResponse":
      "description": "Full-text search response (results, pagination, query, searchTime)."
      "type": "object"
      "properties":
        "success":
          "type": "boolean"
        "data":
          "type": "object"
          "properties":
            "results":
              "type": "array"
              "items":
                "$ref": "#/components/schemas/SearchResult"
            "pagination":
              "$ref": "#/components/schemas/Pagination"
            "query":
              "type": "string"
            "searchTime":
              "type": "integer"
    "SearchResult":
      "description": "Single search hit (collection, item with _id and score, highlight)."
      "type": "object"
      "properties":
        "collection":
          "type": "string"
        "item":
          "type": "object"
          "properties":
            "_id":
              "type": "string"
            "score":
              "type": "number"
        "highlight":
          "type": "object"
    "HealthResponse":
      "description": "Health check response (status, timestamp, services, version, uptime)."
      "type": "object"
      "properties":
        "status":
          "type": "string"
          "enum":
            - "healthy"
            - "unhealthy"
        "timestamp":
          "type": "string"
          "format": "date-time"
        "services":
          "type": "object"
          "properties":
            "database":
              "type": "string"
            "redis":
              "type": "string"
            "storage":
              "type": "string"
            "email":
              "type": "string"
            "sms":
              "type": "string"
        "version":
          "type": "string"
        "uptime":
          "type": "integer"
    "SystemStatusResponse":
      "description": "System status (uptime, memory, cpu, requests, database, storage)."
      "type": "object"
      "properties":
        "success":
          "type": "boolean"
        "data":
          "type": "object"
          "properties":
            "uptime":
              "type": "integer"
            "memory":
              "type": "object"
              "properties":
                "used":
                  "type": "integer"
                "total":
                  "type": "integer"
                "percentage":
                  "type": "number"
            "cpu":
              "type": "object"
              "properties":
                "usage":
                  "type": "number"
                "cores":
                  "type": "integer"
            "requests":
              "type": "object"
              "properties":
                "total":
                  "type": "integer"
                "successful":
                  "type": "integer"
                "errors":
                  "type": "integer"
                "errorRate":
                  "type": "number"
            "database":
              "type": "object"
              "properties":
                "connections":
                  "type": "integer"
                "maxConnections":
                  "type": "integer"
                "responseTime":
                  "type": "integer"
            "storage":
              "type": "object"
              "properties":
                "used":
                  "type": "integer"
                "available":
                  "type": "integer"
                "percentage":
                  "type": "number"
    "NonCustodialAddress":
      "description": "Registered non-custodial wallet address (id, address, chain, label, projectId)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
          "example": "65a1b2c3d4e5f6789012345a"
        "address":
          "type": "string"
          "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
        "chain":
          "type": "string"
          "enum":
            - "ethereum"
            - "binance"
            - "polygon"
            - "celo"
            - "bitcoin"
        "org":
          "type": "string"
          "example": "685acbe0e129932fbb7a0fc3"
        "project":
          "type": "string"
          "example": "685ad30be129932fbb7a1047"
        "derivationPath":
          "type": "string"
          "nullable": true
          "example": "m/44'/60'/0'/0/5"
        "label":
          "type": "string"
          "nullable": true
          "example": "User Wallet 5"
        "isActive":
          "type": "boolean"
          "example": true
        "registeredAt":
          "type": "string"
          "format": "date-time"
          "example": "2026-01-22T10:00:00.000Z"
        "lastSyncedAt":
          "type": "string"
          "format": "date-time"
          "nullable": true
          "example": "2026-01-22T10:05:00.000Z"
        "createdAt":
          "type": "string"
          "format": "date-time"
          "example": "2026-01-22T10:00:00.000Z"
        "updatedAt":
          "type": "string"
          "format": "date-time"
          "example": "2026-01-22T10:00:00.000Z"
    "WalletTransactionWebhookPayload":
      "description": "Example webhook payload for wallet.transaction.confirmed (reusable example payload)."
      "type": "object"
      "properties":
        "event":
          "type": "string"
          "example": "wallet.transaction.confirmed"
        "data":
          "type": "object"
          "description": "Payload data (addressId, address, chain, txHash, transaction, etc.)"
        "timestamp":
          "type": "string"
          "format": "date-time"
          "example": "2026-02-01T21:05:16.462Z"
      "example":
        "event": "wallet.transaction.confirmed"
        "data":
          "addressId": "65a1b2c3d4e5f6789012345a"
          "address": "0x1194d844f5c5a9adc488835e1f506dafbb579341"
          "chain": "celo"
          "txHash": "0xa2939ae9a783fde2b6b9f2c2a8e4733545574849177879f755c84d7947716230"
          "transaction":
            "_id": "65a1b2c3d4e5f6789012345b"
            "txHash": "0xa2939ae9a783fde2b6b9f2c2a8e4733545574849177879f755c84d7947716230"
            "chain": "celo"
            "type": "deposit"
            "status": "completed"
        "timestamp": "2026-02-01T21:05:16.462Z"
    "NonCustodialAddressResponse":
      "description": "Response after registering or fetching a non-custodial address (success, message, data)."
      "type": "object"
      "properties":
        "success":
          "type": "boolean"
          "example": true
        "message":
          "type": "string"
          "example": "Address registered successfully"
        "data":
          "$ref": "#/components/schemas/NonCustodialAddress"
    "WalletBalance":
      "description": "Wallet balance (address, chain, confirmed, unconfirmed, total, currency, lastUpdated)."
      "type": "object"
      "properties":
        "address":
          "type": "string"
          "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
        "chain":
          "type": "string"
          "example": "ethereum"
        "confirmed":
          "type": "string"
          "description": "Confirmed balance (string to handle large numbers)"
          "example": "1.5"
        "unconfirmed":
          "type": "string"
          "description": "Unconfirmed balance (string to handle large numbers)"
          "example": "0.0"
        "total":
          "type": "string"
          "description": "Total balance (string to handle large numbers)"
          "example": "1.5"
        "currency":
          "type": "string"
          "example": "ETH"
        "lastUpdated":
          "type": "string"
          "format": "date-time"
          "example": "2026-01-22T10:05:00.000Z"
    "WalletTransaction":
      "description": "Wallet transaction record (txHash, address, chain, from, to, amount, status, confirmations, etc.)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
          "example": "65a1b2c3d4e5f6789012345b"
        "txHash":
          "type": "string"
          "example": "0xabc123def4567890123456789012345678901234567890123456789012345678"
        "mainTxHash":
          "type": "string"
          "example": "0xabc123def4567890123456789012345678901234567890123456789012345678"
        "address":
          "type": "string"
          "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
        "chain":
          "type": "string"
          "example": "ethereum"
        "from":
          "type": "string"
          "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
        "to":
          "type": "string"
          "example": "0xdef4567890123456789012345678901234567890"
        "fromAddress":
          "type": "string"
          "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
        "toAddress":
          "type": "string"
          "example": "0xdef4567890123456789012345678901234567890"
        "amount":
          "type": "string"
          "description": "Transaction amount (string to handle large numbers)"
          "example": "0.1"
        "currency":
          "type": "string"
          "example": "ETH"
        "type":
          "type": "string"
          "example": "transfer"
        "status":
          "type": "string"
          "enum":
            - "pending"
            - "completed"
            - "failed"
          "example": "completed"
        "mainTxStatus":
          "type": "string"
          "enum":
            - "pending"
            - "confirmed"
            - "failed"
          "example": "confirmed"
        "confirmations":
          "type": "integer"
          "example": 12
        "blockNumber":
          "type": "integer"
          "nullable": true
          "example": 12345678
        "blockHash":
          "type": "string"
          "nullable": true
          "example": "0xdef7890123456789012345678901234567890123456789012345678901234567"
        "networkFee":
          "type": "string"
          "description": "Network fee (string to handle large numbers)"
          "example": "0.00021"
        "mainTxConfirmedAt":
          "type": "string"
          "format": "date-time"
          "nullable": true
          "example": "2026-01-22T10:00:00.000Z"
        "createdAt":
          "type": "string"
          "format": "date-time"
          "example": "2026-01-22T10:00:00.000Z"
        "updatedAt":
          "type": "string"
          "format": "date-time"
          "example": "2026-01-22T10:00:00.000Z"
    "WalletWebhook":
      "description": "Wallet webhook config (id, url, events, chain, address, secret, isActive)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
          "example": "65a1b2c3d4e5f6789012345c"
        "url":
          "type": "string"
          "format": "uri"
          "example": "https://your-app.com/webhooks/wallet"
        "events":
          "type": "array"
          "items":
            "type": "string"
            "enum":
              - "wallet.balance.updated"
              - "wallet.transaction.confirmed"
              - "wallet.transaction.failed"
          "example":
            - "wallet.balance.updated"
            - "wallet.transaction.confirmed"
        "filters":
          "type": "object"
          "properties":
            "addresses":
              "type": "array"
              "items":
                "type": "string"
              "example":
                - "65a1b2c3d4e5f6789012345a"
            "chains":
              "type": "array"
              "items":
                "type": "string"
                "enum":
                  - "ethereum"
                  - "binance"
                  - "polygon"
                  - "celo"
                  - "bitcoin"
              "example":
                - "ethereum"
        "isActive":
          "type": "boolean"
          "example": true
        "stats":
          "type": "object"
          "properties":
            "totalDeliveries":
              "type": "integer"
              "example": 150
            "successfulDeliveries":
              "type": "integer"
              "example": 148
            "failedDeliveries":
              "type": "integer"
              "example": 2
            "lastDeliveryAt":
              "type": "string"
              "format": "date-time"
              "nullable": true
              "example": "2026-01-22T10:05:00.000Z"
        "createdAt":
          "type": "string"
          "format": "date-time"
          "example": "2026-01-22T10:00:00.000Z"
        "updatedAt":
          "type": "string"
          "format": "date-time"
          "example": "2026-01-22T10:00:00.000Z"
    "PaymentIntent":
      "description": "Payment intent for checkout (id, amount, currency, status, etc.)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
          "example": "65a1b2c3d4e5f6789012345f"
        "paymentId":
          "type": "string"
          "description": "Unique payment identifier"
          "example": "pmt_abc123xyz789"
        "merchant":
          "type": "string"
          "description": "Merchant ID"
        "project":
          "type": "string"
          "description": "Project ID"
        "amount":
          "type": "number"
          "description": "Payment amount"
          "example": 50
        "currency":
          "type": "string"
          "default": "USD"
          "example": "USD"
        "network":
          "type": "string"
          "enum":
            - "polygon"
            - "arbitrum"
            - "tron"
            - "solana"
            - "lightning"
            - "ton"
          "example": "polygon"
        "token":
          "type": "string"
          "enum":
            - "USDC"
            - "USDT"
            - "BTC"
          "example": "USDC"
        "type":
          "type": "string"
          "enum":
            - "one_time"
            - "subscription"
          "example": "one_time"
        "status":
          "type": "string"
          "enum":
            - "created"
            - "awaiting_payment"
            - "partially_paid"
            - "confirmed"
            - "completed"
            - "expired"
            - "failed"
          "example": "awaiting_payment"
        "finalityStatus":
          "type": "string"
          "enum":
            - "pending_confirmation"
            - "confirmed"
            - "finalized"
          "example": "pending_confirmation"
        "totalDue":
          "type": "number"
          "description": "Total amount due including fees"
          "example": 50.86
        "commission":
          "type": "number"
          "description": "Platform commission"
          "example": 0.85
        "merchantReceives":
          "type": "number"
          "description": "Amount merchant receives after commission"
          "example": 49.15
        "expiresAt":
          "type": "string"
          "format": "date-time"
          "example": "2024-01-15T12:00:00.000Z"
        "metadata":
          "type": "object"
          "description": "Additional metadata"
        "createdAt":
          "type": "string"
          "format": "date-time"
        "updatedAt":
          "type": "string"
          "format": "date-time"
    "PaymentRefund":
      "description": "Payment refund record (id, paymentId, amount, status, reason, createdAt)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
        "paymentIntent":
          "type": "string"
          "description": "Payment intent ID"
        "merchant":
          "type": "string"
          "description": "Merchant ID"
        "amount":
          "type": "number"
          "description": "Refund amount"
        "reason":
          "type": "string"
          "description": "Refund reason"
        "status":
          "type": "string"
          "enum":
            - "pending"
            - "approved"
            - "rejected"
            - "processed"
            - "failed"
          "example": "pending"
        "isCrossChain":
          "type": "boolean"
          "description": "True if cross-chain refund"
          "default": false
        "sourceNetwork":
          "type": "string"
          "description": "Source network for refund"
        "targetNetwork":
          "type": "string"
          "description": "Target network for cross-chain refund"
        "approvedBy":
          "type": "string"
          "description": "User ID who approved"
        "approvedAt":
          "type": "string"
          "format": "date-time"
        "refundTx":
          "type": "string"
          "description": "Refund transaction hash"
        "refundedAt":
          "type": "string"
          "format": "date-time"
        "createdAt":
          "type": "string"
          "format": "date-time"
        "updatedAt":
          "type": "string"
          "format": "date-time"
    "PaymentSubscription":
      "description": "Subscription record (id, plan, status, currentPeriodEnd, etc.)."
      "type": "object"
      "properties":
        "_id":
          "type": "string"
        "merchant":
          "type": "string"
          "description": "Merchant ID"
        "project":
          "type": "string"
          "description": "Project ID"
        "amount":
          "type": "number"
          "description": "Subscription amount"
        "interval":
          "type": "string"
          "enum":
            - "month"
            - "year"
          "example": "month"
        "network":
          "type": "string"
          "enum":
            - "polygon"
            - "arbitrum"
            - "tron"
            - "solana"
            - "lightning"
            - "ton"
        "token":
          "type": "string"
          "enum":
            - "USDC"
            - "USDT"
            - "BTC"
        "status":
          "type": "string"
          "enum":
            - "active"
            - "paused"
            - "cancelled"
            - "expired"
          "example": "active"
        "nextPaymentAt":
          "type": "string"
          "format": "date-time"
          "description": "Next payment due date"
        "gracePeriodDays":
          "type": "integer"
          "default": 3
          "description": "Grace period in days"
        "earlyPaymentAllowed":
          "type": "boolean"
          "default": true
        "latePaymentAllowed":
          "type": "boolean"
          "default": true
        "prorationEnabled":
          "type": "boolean"
          "default": false
        "createdAt":
          "type": "string"
          "format": "date-time"
        "updatedAt":
          "type": "string"
          "format": "date-time"
    "MessageResponse":
      "description": "Generic message response (e.g. success or info message)."
      "type": "object"
      "properties":
        "message":
          "type": "string"
    "Error":
      "description": "API error payload. The backend returns an **error** string (required); **code**, **details**, **timestamp**, **path**, and **requestId** are optional.

        The **error** message is exactly as returned by the backend and varies by endpoint (e.g. \"File not found\", \"Project not found\", \"Invalid token.\").\n"
      "type": "object"
      "required":
        - "error"
      "properties":
        "error":
          "type": "string"
          "description": "Exact error message from the backend"
        "code":
          "type": "string"
        "details":
          "oneOf":
            - "type": "string"
            - "type": "object"
        "timestamp":
          "type": "string"
          "format": "date-time"
        "path":
          "type": "string"
        "requestId":
          "type": "string"
  "responses":
    "NotFound":
      "description": "Resource not found. The **error** field contains the exact backend message, e.g. \"File not found\", \"Project not found\", \"User not found\", \"Project not found or access denied\", \"Webhook not found\", \"Organization not found\".\n"
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "File not found"
    "FileNotFound":
      "description": "File not found (exact backend message for file/storage endpoints)."
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "File not found"
    "ProjectNotFound":
      "description": "Project not found (exact backend message for project endpoints)."
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "Project not found"
    "UserNotFound":
      "description": "User not found (exact backend message for user endpoints)."
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "User not found"
    "OrganizationNotFound":
      "description": "Organization not found (exact backend message for org endpoints)."
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "Organization not found"
    "WebhookNotFound":
      "description": "Webhook not found (exact backend message for webhook endpoints)."
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "Webhook not found"
    "PaymentIntentNotFound":
      "description": "Payment intent not found (exact backend message for payment endpoints)."
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "Payment intent not found"
    "SubscriptionNotFound":
      "description": "Subscription not found (exact backend message for subscription endpoints)."
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "Subscription not found"
    "PaymentNotFound":
      "description": "Payment not found (exact backend message for payment admin endpoints)."
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "Payment not found"
    "FunctionNotFound":
      "description": "Function not found (exact backend message for functions endpoints)."
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "Function not found"
    "RoleNotFound":
      "description": "Role not found (exact backend message for role-elevation endpoints)."
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "Role not found"
    "ProjectOrAccessDenied":
      "description": "Project not found or access denied (exact backend message)."
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "Project not found or access denied"
    "Unauthorized":
      "description": "Not authenticated. The **error** field contains the exact backend message, e.g. \"Invalid token.\", \"Access denied. No token provided.\", \"Authentication required\", \"Invalid API key\", \"API key expired\".\n"
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "Invalid token."
    "Forbidden":
      "description": "Access denied. The **error** field contains the exact backend message, e.g. \"Access denied\", \"Insufficient permissions\", \"You don't have permission to view this organization's projects\", \"Account suspended\".\n"
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "Access denied"
    "BadRequest":
      "description": "Bad request or validation error. The **error** field contains the exact backend message, e.g. \"Validation failed\", \"projectId is required\", \"No file provided\", \"Invalid project ID format\". **details** may contain validation errors when present.\n"
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "Validation failed"
            "details":
              "email": "Email is required"
              "password": "Password must be at least 8 characters"
    "Conflict":
      "description": "Resource conflict (e.g. \"Project with this slug already exists\", \"Webhook already succeeded\")."
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "Project with this slug already exists"
    "TooManyRequests":
      "description": "Rate limit exceeded. The **error** field contains the exact backend message, e.g. \"API key rate limit exceeded\", \"Please wait before requesting another magic link\".\n"
      "content":
        "application/json":
          "schema":
            "allOf":
              - "$ref": "#/components/schemas/Error"
              - "type": "object"
                "properties":
                  "retryAfter":
                    "type": "integer"
          "example":
            "error": "API key rate limit exceeded"
    "InternalServerError":
      "description": "Server error. The **error** field contains the exact backend message, e.g. \"Authentication failed\", \"Failed to upload file\", \"Failed to fetch project\".\n"
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "Failed to upload file"
    "ServiceUnavailable":
      "description": "Service temporarily unavailable. Returned when the account or project is restricted (e.g. suspended due to unpaid overage,

        spend limit exceeded, or API usage limit reached). End-users see a generic message; the real reason is logged server-side only.\n"
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
          "example":
            "error": "Service temporarily unavailable. Please try again later."
            "code": "SERVICE_UNAVAILABLE"
  "examples":
    "UserExample":
      "value":
        "_id": "685acbe0e129932fbb7a0fc2"
        "email": "john.doe@mudbase.dev"
        "firstName": "John"
        "lastName": "Doe"
        "role": "owner"
        "emailVerified": true
        "twoFactorEnabled": false
        "org":
          "_id": "685acbe0e129932fbb7a0fc3"
          "name": "Mudbase"
          "slug": "mudbase"
        "createdAt": "2024-01-15T10:00:00.000Z"
        "updatedAt": "2024-01-15T10:00:00.000Z"
    "ProjectExample":
      "value":
        "_id": "685ad30be129932fbb7a1047"
        "name": "Mudbase Platform"
        "description": "Main platform for Mudbase services"
        "slug": "mudbase-platform"
        "org": "685acbe0e129932fbb7a0fc3"
        "apiKey": "pk_live_abc123xyz789"
        "createdAt": "2024-01-15T10:00:00.000Z"
        "updatedAt": "2024-01-15T10:00:00.000Z"
    "CollectionExample":
      "value":
        "_id": "685ada8fd9416ac02f171abf"
        "name": "users"
        "slug": "users"
        "project": "685ad30be129932fbb7a1047"
        "fields":
          - "name": "email"
            "type": "email"
            "required": true
            "unique": true
          - "name": "firstName"
            "type": "string"
            "required": true
          - "name": "lastName"
            "type": "string"
            "required": true
          - "name": "role"
            "type": "string"
            "enum":
              - "developer"
              - "admin"
              - "viewer"
            "default": "developer"
        "createdAt": "2024-01-15T10:00:00.000Z"
        "updatedAt": "2024-01-15T10:00:00.000Z"
