openapi: 3.0.3
info:
  title: 'M2 Partner API Documentation'
  description: 'Backend API for the M2 Partner referral platform. Covers authentication, partner onboarding, referral management, property activity timeline, commission tracking, and admin operations.'
  version: 1.0.0
servers:
  -
    url: 'http://m2-partner-api.test'
tags:
  -
    name: Authentication
    description: ''
  -
    name: Onboarding
    description: ''
  -
    name: Me
    description: ''
  -
    name: Referrals
    description: ''
  -
    name: 'Property Timeline'
    description: ''
  -
    name: 'Admin: Users'
    description: ''
  -
    name: 'Admin: Commissions'
    description: ''
  -
    name: 'Admin: Payouts'
    description: ''
  -
    name: General
    description: "\nSystem-level endpoints for CMS management, AI helpers and API overdraft status."
  -
    name: 'Admin: Referrals'
    description: ''
  -
    name: Entries
    description: "\nEndpoints for creating, reading, updating and deleting dynamic module entries."
  -
    name: Fields
    description: "\nEndpoints for retrieving available field type definitions."
  -
    name: Modules
    description: "\nEndpoints for managing CMS module definitions (schema, fields, types)."
  -
    name: Notifications
    description: "\nEndpoints for managing and retrieving user notifications."
components:
  securitySchemes:
    default:
      type: http
      scheme: bearer
      description: 'Obtain a token via <code>POST /api/auth/login</code> with your email and password. Pass the returned token as <code>Authorization: Bearer {token}</code> on all subsequent requests.'
security:
  -
    default: []
paths:
  /api/auth/login:
    post:
      summary: Login
      operationId: login
      description: 'Authenticate with email and password to receive a JWT token.'
      parameters: []
      responses: {  }
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  description: "The user's email address."
                  example: admin@example.com
                password:
                  type: string
                  description: "The user's password."
                  example: secret
              required:
                - email
                - password
      security: []
  '/api/auth/confirm/{confirmationCode}':
    get:
      summary: 'Confirm email'
      operationId: confirmEmail
      description: "Confirms a newly registered user's email address using the code sent by email."
      parameters: []
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: INVALID_USER_CONFIRMATION_CODE
                  body: []
                properties:
                  message:
                    type: string
                    example: INVALID_USER_CONFIRMATION_CODE
                  body:
                    type: array
                    example: []
      tags:
        - Authentication
      security: []
    parameters:
      -
        in: path
        name: confirmationCode
        description: ''
        example: architecto
        required: true
        schema:
          type: string
  /api/password/request_reset:
    post:
      summary: 'Request password reset'
      operationId: requestPasswordReset
      description: 'Sends a password reset link to the given email address.'
      parameters: []
      responses: {  }
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  description: "The user's registered email address."
                  example: user@example.com
              required:
                - email
      security: []
  /api/password/reset:
    post:
      summary: 'Reset password'
      operationId: resetPassword
      description: 'Sets a new password using the token received via email.'
      parameters: []
      responses: {  }
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  description: "The user's email address."
                  example: user@example.com
                token:
                  type: string
                  description: 'The password reset token received by email.'
                  example: abc123xyz
                password:
                  type: string
                  description: 'The new password.'
                  example: newpass456
              required:
                - email
                - token
                - password
      security: []
  /api/auth/register:
    post:
      summary: Register
      operationId: register
      description: "Creates a new user account. Requires a valid sponsor invite code.\nSends a 6-digit verification code to the provided email.\n\nTerms of Service are NOT accepted here — the user accepts them later via\n`POST /api/auth/accept-tos`, after email verification (see the registration flow)."
      parameters: []
      responses:
        201:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: REGISTRATION_SUCCESS
                  body:
                    user_id: 42
                properties:
                  message:
                    type: string
                    example: REGISTRATION_SUCCESS
                  body:
                    type: object
                    properties:
                      user_id:
                        type: integer
                        example: 42
        406:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: VALIDATION_ERROR
                  body:
                    invite_code:
                      - 'Invalid invite code.'
                properties:
                  message:
                    type: string
                    example: VALIDATION_ERROR
                  body:
                    type: object
                    properties:
                      invite_code:
                        type: array
                        example:
                          - 'Invalid invite code.'
                        items:
                          type: string
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                invite_code:
                  type: string
                  description: 'Referral code of the sponsoring partner.'
                  example: AB12CD34
                first_name:
                  type: string
                  description: ''
                  example: Jelena
                last_name:
                  type: string
                  description: ''
                  example: Petrović
                email:
                  type: string
                  description: ''
                  example: jelena@example.com
                password:
                  type: string
                  description: 'Minimum 8 characters.'
                  example: Secret123!
                phone:
                  type: string
                  description: ''
                  example: '+381641234567'
              required:
                - invite_code
                - first_name
                - last_name
                - email
                - password
                - phone
      security: []
  /api/auth/social_login:
    post:
      summary: 'Social login'
      operationId: socialLogin
      description: 'Authenticates (or registers) a user via a social OAuth provider. Logs in an existing user or creates a new account.'
      parameters: []
      responses: {  }
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  description: "The user's email from the OAuth provider."
                  example: user@example.com
                provider:
                  type: string
                  description: 'The OAuth provider name.'
                  example: google
                provider_id:
                  type: string
                  description: "The user's ID from the OAuth provider."
                  example: '1234567890'
                first_name:
                  type: string
                  description: 'optional First name (used when creating a new account).'
                  example: John
                last_name:
                  type: string
                  description: 'optional Last name (used when creating a new account).'
                  example: Doe
              required:
                - email
                - provider
                - provider_id
      security: []
  '/api/auth/register/{invitationCode}':
    post:
      summary: 'Register with invitation'
      operationId: registerWithInvitation
      description: 'Creates a new confirmed user account using an invitation code. The email is pre-filled from the invitation.'
      parameters: []
      responses: {  }
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                first_name:
                  type: string
                  description: 'First name.'
                  example: John
                last_name:
                  type: string
                  description: 'Last name.'
                  example: Doe
                password:
                  type: string
                  description: Password.
                  example: secret123
              required:
                - first_name
                - last_name
                - password
      security: []
    parameters:
      -
        in: path
        name: invitationCode
        description: ''
        example: architecto
        required: true
        schema:
          type: string
  /api/password/change:
    post:
      summary: 'Change password'
      operationId: changePassword
      description: "Changes the authenticated user's password. Requires the current password for verification."
      parameters: []
      responses: {  }
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                old_password:
                  type: string
                  description: 'The current password.'
                  example: oldpass123
                new_password:
                  type: string
                  description: 'The new password.'
                  example: newpass456
              required:
                - old_password
                - new_password
  /api/auth/refresh:
    get:
      summary: 'Refresh token'
      operationId: refreshToken
      description: 'Issues a new JWT token using the current valid token.'
      parameters: []
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Authentication
  /api/auth/logout:
    get:
      summary: Logout
      operationId: logout
      description: 'Invalidates the current JWT token, ending the session.'
      parameters: []
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Authentication
  /api/auth/me:
    get:
      summary: 'Get authenticated user'
      operationId: getAuthenticatedUser
      description: "Retrieves the currently authenticated user's profile and relations."
      parameters: []
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Authentication
  /api/auth/impersonate/stop:
    get:
      summary: 'Stop impersonating user'
      operationId: stopImpersonatingUser
      description: 'Invalidates the impersonation token and issues a fresh token for the original super admin user.'
      parameters: []
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Authentication
  '/api/auth/impersonate/{id}':
    get:
      summary: 'Start impersonating user'
      operationId: startImpersonatingUser
      description: "Issues a new token with the target user's ID embedded as a custom claim, allowing the super admin to act as that user."
      parameters: []
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Authentication
    parameters:
      -
        in: path
        name: id
        description: 'The ID of the impersonate.'
        example: architecto
        required: true
        schema:
          type: string
  '/api/auth/clear/{id}':
    post:
      summary: 'Clear user tokens'
      operationId: clearUserTokens
      description: 'Invalidates all active JWT tokens for the specified user. Requires super admin role.'
      parameters: []
      responses: {  }
      tags:
        - Authentication
    parameters:
      -
        in: path
        name: id
        description: 'The ID of the clear.'
        example: architecto
        required: true
        schema:
          type: string
  '/api/auth/clear-all/{force}':
    post:
      summary: 'Clear all tokens'
      operationId: clearAllTokens
      description: 'Invalidates all active JWT tokens for all users. Super admins are skipped unless `force=1`. Requires super admin role.'
      parameters: []
      responses: {  }
      tags:
        - Authentication
    parameters:
      -
        in: path
        name: force
        description: 'Optional parameter.'
        required: true
        schema:
          type: string
        examples:
          omitted:
            summary: 'When the value is omitted'
            value: ''
          present:
            summary: 'When the value is present'
            value: architecto
  /api/auth/verify-email:
    post:
      summary: 'Verify email'
      operationId: verifyEmail
      description: "Submits the 6-digit code sent to the user's email during registration.\nOn success, status changes to `pending_tos` — the user must still accept the\nTerms of Service via `POST /api/auth/accept-tos` before admins are notified."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: EMAIL_VERIFIED
                  body: {  }
                properties:
                  message:
                    type: string
                    example: EMAIL_VERIFIED
                  body:
                    type: object
                    properties: {  }
        406:
          description: ''
          content:
            application/json:
              schema:
                oneOf:
                  -
                    description: ''
                    type: object
                    example:
                      message: CODE_EXPIRED
                      body: {  }
                    properties:
                      message:
                        type: string
                        example: CODE_EXPIRED
                      body:
                        type: object
                        properties: {  }
                  -
                    description: ''
                    type: object
                    example:
                      message: CODE_INVALID
                      body: {  }
                    properties:
                      message:
                        type: string
                        example: CODE_INVALID
                      body:
                        type: object
                        properties: {  }
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  description: ''
                  example: jelena@example.com
                code:
                  type: string
                  description: '6-digit numeric code.'
                  example: '123456'
              required:
                - email
                - code
      security: []
  /api/auth/accept-tos:
    post:
      summary: 'Accept Terms of Service'
      operationId: acceptTermsOfService
      description: "Final registration step (\"Završi registraciju\"). The user accepts both the\nTerms of Service / Privacy Policy and the confidentiality agreement. Only valid\nonce the email has been verified (status `pending_tos`). On success the status\nchanges to `pending_approval` and admins are notified."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOS_ACCEPTED
                  body: {  }
                properties:
                  message:
                    type: string
                    example: TOS_ACCEPTED
                  body:
                    type: object
                    properties: {  }
        406:
          description: ''
          content:
            application/json:
              schema:
                oneOf:
                  -
                    description: ''
                    type: object
                    example:
                      message: TOS_INVALID_STATE
                      body: {  }
                    properties:
                      message:
                        type: string
                        example: TOS_INVALID_STATE
                      body:
                        type: object
                        properties: {  }
                  -
                    description: ''
                    type: object
                    example:
                      message: VALIDATION_ERROR
                      body:
                        tos_accepted:
                          - 'The tos accepted field must be accepted.'
                    properties:
                      message:
                        type: string
                        example: VALIDATION_ERROR
                      body:
                        type: object
                        properties:
                          tos_accepted:
                            type: array
                            example:
                              - 'The tos accepted field must be accepted.'
                            items:
                              type: string
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  description: ''
                  example: jelena@example.com
                tos_accepted:
                  type: boolean
                  description: 'Acceptance of the Terms of Service & Privacy Policy. Must be true.'
                  example: true
                confidentiality_accepted:
                  type: boolean
                  description: 'Acceptance of the confidentiality agreement. Must be true.'
                  example: true
              required:
                - email
                - tos_accepted
                - confidentiality_accepted
      security: []
  /api/auth/resend-verification:
    post:
      summary: 'Resend verification code'
      operationId: resendVerificationCode
      description: 'Resends the 6-digit email verification code. Rate-limited to 3 per hour.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: VERIFICATION_CODE_SENT
                  body: {  }
                properties:
                  message:
                    type: string
                    example: VERIFICATION_CODE_SENT
                  body:
                    type: object
                    properties: {  }
        429:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: RATE_LIMIT_EXCEEDED
                  body: {  }
                properties:
                  message:
                    type: string
                    example: RATE_LIMIT_EXCEEDED
                  body:
                    type: object
                    properties: {  }
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  description: ''
                  example: jelena@example.com
              required:
                - email
      security: []
  /api/auth/registration-status:
    get:
      summary: 'Registration status'
      operationId: registrationStatus
      description: "Returns whether the pending user has been approved by an admin.\nUsed by the \"Check status\" button on the pending approval screen."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: REGISTRATION_STATUS
                  body:
                    approved: false
                    status: pending_approval
                properties:
                  message:
                    type: string
                    example: REGISTRATION_STATUS
                  body:
                    type: object
                    properties:
                      approved:
                        type: boolean
                        example: false
                      status:
                        type: string
                        example: pending_approval
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  description: ''
                  example: jelena@example.com
              required:
                - email
      security: []
  /api/auth/forgot-password:
    post:
      summary: 'Forgot password'
      operationId: forgotPassword
      description: "Sends a 6-digit password reset code to the user's email.\nThis overrides the default PCMS link-based reset — the app uses a code input."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: PASSWORD_RESET_CODE_SENT
                  body: {  }
                properties:
                  message:
                    type: string
                    example: PASSWORD_RESET_CODE_SENT
                  body:
                    type: object
                    properties: {  }
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  description: ''
                  example: jelena@example.com
              required:
                - email
      security: []
  /api/auth/reset-password:
    post:
      summary: 'Reset password'
      operationId: resetPassword
      description: 'Verifies the 6-digit code and sets a new password.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: PASSWORD_RESET_SUCCESS
                  body: {  }
                properties:
                  message:
                    type: string
                    example: PASSWORD_RESET_SUCCESS
                  body:
                    type: object
                    properties: {  }
        406:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: CODE_EXPIRED
                  body: {  }
                properties:
                  message:
                    type: string
                    example: CODE_EXPIRED
                  body:
                    type: object
                    properties: {  }
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  description: ''
                  example: jelena@example.com
                code:
                  type: string
                  description: '6-digit code from email.'
                  example: '654321'
                password:
                  type: string
                  description: 'New password, minimum 8 characters.'
                  example: NewSecret123!
              required:
                - email
                - code
                - password
      security: []
  '/api/onboarding/invite/{code}':
    get:
      summary: 'Validate invite code'
      operationId: validateInviteCode
      description: "Checks whether a referral code is valid and returns the sponsor's name.\nUsed on the first onboarding screen before registration."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: INVITE_CODE_VALID
                  body:
                    sponsor_first_name: Marko
                    sponsor_last_name: Marković
                properties:
                  message:
                    type: string
                    example: INVITE_CODE_VALID
                  body:
                    type: object
                    properties:
                      sponsor_first_name:
                        type: string
                        example: Marko
                      sponsor_last_name:
                        type: string
                        example: Marković
        404:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: INVITE_CODE_INVALID
                  body: {  }
                properties:
                  message:
                    type: string
                    example: INVITE_CODE_INVALID
                  body:
                    type: object
                    properties: {  }
      tags:
        - Onboarding
      security: []
    parameters:
      -
        in: path
        name: code
        description: 'The referral code to validate.'
        example: AB12CD34
        required: true
        schema:
          type: string
  /api/me:
    get:
      summary: 'Get profile'
      operationId: getProfile
      description: "Returns the authenticated user's profile."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: ME_RETRIEVED
                  body:
                    id: 1
                    first_name: Jelena
                    last_name: Petrović
                    email: jelena@example.com
                    phone: '+381641234567'
                    status: active
                    referral_code: AB12CD34
                    roles:
                      - partner
                properties:
                  message:
                    type: string
                    example: ME_RETRIEVED
                  body:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 1
                      first_name:
                        type: string
                        example: Jelena
                      last_name:
                        type: string
                        example: Petrović
                      email:
                        type: string
                        example: jelena@example.com
                      phone:
                        type: string
                        example: '+381641234567'
                      status:
                        type: string
                        example: active
                      referral_code:
                        type: string
                        example: AB12CD34
                      roles:
                        type: array
                        example:
                          - partner
                        items:
                          type: string
      tags:
        - Me
    patch:
      summary: 'Update profile'
      operationId: updateProfile
      description: "Updates the authenticated user's profile fields."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: ME_UPDATED
                  body:
                    id: 1
                properties:
                  message:
                    type: string
                    example: ME_UPDATED
                  body:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 1
      tags:
        - Me
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                first_name:
                  type: string
                  description: optional
                  example: Jelena
                last_name:
                  type: string
                  description: optional
                  example: Petrović
                phone:
                  type: string
                  description: optional
                  example: '+381641234567'
  /api/me/dashboard:
    get:
      summary: Dashboard
      operationId: dashboard
      description: 'Returns KPI summary and latest activity feed for the home screen.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: DASHBOARD_RETRIEVED
                  body:
                    earnings_total: 1250.0
                    earnings_pending: 250.0
                    referrals_count: 5
                    active_count: 3
                    team_count: 2
                    activity_feed: []
                properties:
                  message:
                    type: string
                    example: DASHBOARD_RETRIEVED
                  body:
                    type: object
                    properties:
                      earnings_total:
                        type: number
                        example: 1250.0
                      earnings_pending:
                        type: number
                        example: 250.0
                      referrals_count:
                        type: integer
                        example: 5
                      active_count:
                        type: integer
                        example: 3
                      team_count:
                        type: integer
                        example: 2
                      activity_feed:
                        type: array
                        example: []
      tags:
        - Me
  /api/me/digital-card:
    get:
      summary: 'Digital card'
      operationId: digitalCard
      description: "Returns data for the partner's digital business card and QR code."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: DIGITAL_CARD_RETRIEVED
                  body:
                    first_name: Jelena
                    last_name: Petrović
                    status: candidate
                    referral_code: AB12CD34
                    qr_payload: 'https://m2-partner-api.test/join/AB12CD34'
                properties:
                  message:
                    type: string
                    example: DIGITAL_CARD_RETRIEVED
                  body:
                    type: object
                    properties:
                      first_name:
                        type: string
                        example: Jelena
                      last_name:
                        type: string
                        example: Petrović
                      status:
                        type: string
                        example: candidate
                      referral_code:
                        type: string
                        example: AB12CD34
                      qr_payload:
                        type: string
                        example: 'https://m2-partner-api.test/join/AB12CD34'
      tags:
        - Me
  /api/me/earnings:
    get:
      summary: Earnings
      operationId: earnings
      description: 'Returns earnings summary and commission bracket information.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: EARNINGS_RETRIEVED
                  body:
                    total: 1250.0
                    pending: 250.0
                    paid: 1000.0
                    brackets:
                      seller:
                        -
                          min: 750
                          max: 5000
                          rate: 10
                        -
                          min: 5001
                          max: 10000
                          rate: 13
                        -
                          min: 10001
                          max: null
                          rate: 15
                      buyer:
                        -
                          min: 750
                          max: 5000
                          rate: 7
                        -
                          min: 5001
                          max: 10000
                          rate: 8
                        -
                          min: 10001
                          max: null
                          rate: 10
                properties:
                  message:
                    type: string
                    example: EARNINGS_RETRIEVED
                  body:
                    type: object
                    properties:
                      total:
                        type: number
                        example: 1250.0
                      pending:
                        type: number
                        example: 250.0
                      paid:
                        type: number
                        example: 1000.0
                      brackets:
                        type: object
                        properties:
                          seller:
                            type: array
                            example:
                              -
                                min: 750
                                max: 5000
                                rate: 10
                              -
                                min: 5001
                                max: 10000
                                rate: 13
                              -
                                min: 10001
                                max: null
                                rate: 15
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                  example: 750
                                max:
                                  type: integer
                                  example: 5000
                                rate:
                                  type: integer
                                  example: 10
                          buyer:
                            type: array
                            example:
                              -
                                min: 750
                                max: 5000
                                rate: 7
                              -
                                min: 5001
                                max: 10000
                                rate: 8
                              -
                                min: 10001
                                max: null
                                rate: 10
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                  example: 750
                                max:
                                  type: integer
                                  example: 5000
                                rate:
                                  type: integer
                                  example: 7
      tags:
        - Me
  /api/me/team:
    get:
      summary: 'My team'
      operationId: myTeam
      description: "Returns a list of partners sponsored by the authenticated user,\nincluding the sponsor's earnings from each (10% of their commissions)."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TEAM_RETRIEVED
                  body:
                    team:
                      -
                        id: 2
                        first_name: Ana
                        last_name: Anić
                        role: candidate
                        completed_deals: 1
                        my_earnings: 50.0
                properties:
                  message:
                    type: string
                    example: TEAM_RETRIEVED
                  body:
                    type: object
                    properties:
                      team:
                        type: array
                        example:
                          -
                            id: 2
                            first_name: Ana
                            last_name: Anić
                            role: candidate
                            completed_deals: 1
                            my_earnings: 50
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                              example: 2
                            first_name:
                              type: string
                              example: Ana
                            last_name:
                              type: string
                              example: Anić
                            role:
                              type: string
                              example: candidate
                            completed_deals:
                              type: integer
                              example: 1
                            my_earnings:
                              type: number
                              example: 50.0
      tags:
        - Me
  /api/me/activities:
    get:
      summary: 'Activities (email log)'
      operationId: activitiesemailLog
      description: "Returns the authenticated user's email notification history.\nPowers the Activity Center (bell icon) in the app."
      parameters:
        -
          in: query
          name: filter
          description: 'optional Filter by period: `week` or `month`.'
          example: week
          required: false
          schema:
            type: string
            description: 'optional Filter by period: `week` or `month`.'
            example: week
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: ACTIVITIES_RETRIEVED
                  body:
                    activities:
                      -
                        template: referral_activity
                        subject: 'Update on your referral: Marko'
                        sent_at: '2026-06-01 10:00:00'
                        reference_type: referral
                        reference_id: 5
                properties:
                  message:
                    type: string
                    example: ACTIVITIES_RETRIEVED
                  body:
                    type: object
                    properties:
                      activities:
                        type: array
                        example:
                          -
                            template: referral_activity
                            subject: 'Update on your referral: Marko'
                            sent_at: '2026-06-01 10:00:00'
                            reference_type: referral
                            reference_id: 5
                        items:
                          type: object
                          properties:
                            template:
                              type: string
                              example: referral_activity
                            subject:
                              type: string
                              example: 'Update on your referral: Marko'
                            sent_at:
                              type: string
                              example: '2026-06-01 10:00:00'
                            reference_type:
                              type: string
                              example: referral
                            reference_id:
                              type: integer
                              example: 5
      tags:
        - Me
  /api/referrals:
    get:
      summary: 'List referrals'
      operationId: listReferrals
      description: "Returns referrals filtered by role: partners see only their own,\nagents see assigned referrals, admins see all."
      parameters:
        -
          in: query
          name: status
          description: 'optional Filter by status.'
          example: qualified
          required: false
          schema:
            type: string
            description: 'optional Filter by status.'
            example: qualified
        -
          in: query
          name: search
          description: 'optional Search by client name.'
          example: Marko
          required: false
          schema:
            type: string
            description: 'optional Search by client name.'
            example: Marko
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: REFERRALS_RETRIEVED
                  body:
                    referrals: []
                    total: 0
                properties:
                  message:
                    type: string
                    example: REFERRALS_RETRIEVED
                  body:
                    type: object
                    properties:
                      referrals:
                        type: array
                        example: []
                      total:
                        type: integer
                        example: 0
      tags:
        - Referrals
    post:
      summary: 'Create referral'
      operationId: createReferral
      description: 'Submits a new client referral. Runs duplicate detection automatically.'
      parameters: []
      responses:
        201:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: REFERRAL_CREATED
                  body:
                    id: 1
                    duplicate_flag: false
                    duplicate_score: 0
                properties:
                  message:
                    type: string
                    example: REFERRAL_CREATED
                  body:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 1
                      duplicate_flag:
                        type: boolean
                        example: false
                      duplicate_score:
                        type: integer
                        example: 0
        406:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: VALIDATION_ERROR
                  body:
                    gdpr_consent:
                      - 'GDPR consent is required.'
                properties:
                  message:
                    type: string
                    example: VALIDATION_ERROR
                  body:
                    type: object
                    properties:
                      gdpr_consent:
                        type: array
                        example:
                          - 'GDPR consent is required.'
                        items:
                          type: string
      tags:
        - Referrals
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                client_name:
                  type: string
                  description: ''
                  example: 'Marko Marković'
                client_phone:
                  type: string
                  description: ''
                  example: '+381641234567'
                client_email:
                  type: string
                  description: optional
                  example: marko@example.com
                  nullable: true
                transaction_type:
                  type: string
                  description: 'One of: sale, buy, rent_out, rent_in.'
                  example: sale
                property_type:
                  type: string
                  description: 'One of: apartment, house, commercial, land, other.'
                  example: apartment
                estimated_value:
                  type: number
                  description: 'optional Estimated property value in EUR.'
                  example: 150000.0
                  nullable: true
                monthly_rent:
                  type: number
                  description: 'optional Required for rent_out/rent_in, min 500.'
                  example: 600.0
                  nullable: true
                gdpr_consent:
                  type: boolean
                  description: 'Must be true.'
                  example: true
                property_description:
                  type: string
                  description: optional
                  example: 'Three-bedroom apartment in Novi Beograd'
                  nullable: true
              required:
                - client_name
                - client_phone
                - transaction_type
                - property_type
                - gdpr_consent
  /api/referrals/check-duplicate:
    post:
      summary: 'Check for duplicates'
      operationId: checkForDuplicates
      description: 'Pre-submission duplicate check. Returns a score and list of potential matches.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: DUPLICATE_CHECK_COMPLETE
                  body:
                    score: 80
                    flagged: true
                    matches:
                      -
                        referral_id: 3
                        score: 80
                properties:
                  message:
                    type: string
                    example: DUPLICATE_CHECK_COMPLETE
                  body:
                    type: object
                    properties:
                      score:
                        type: integer
                        example: 80
                      flagged:
                        type: boolean
                        example: true
                      matches:
                        type: array
                        example:
                          -
                            referral_id: 3
                            score: 80
                        items:
                          type: object
                          properties:
                            referral_id:
                              type: integer
                              example: 3
                            score:
                              type: integer
                              example: 80
      tags:
        - Referrals
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                client_name:
                  type: string
                  description: ''
                  example: 'Marko Marković'
                client_phone:
                  type: string
                  description: ''
                  example: '+381641234567'
                client_email:
                  type: string
                  description: optional
                  example: marko@example.com
                  nullable: true
              required:
                - client_name
                - client_phone
  '/api/referrals/{id}':
    get:
      summary: 'Get referral'
      operationId: getReferral
      description: 'Returns a single referral with all fields.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: REFERRAL_RETRIEVED
                  body:
                    referral: {  }
                properties:
                  message:
                    type: string
                    example: REFERRAL_RETRIEVED
                  body:
                    type: object
                    properties:
                      referral:
                        type: object
                        properties: {  }
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: FORBIDDEN
                  body: {  }
                properties:
                  message:
                    type: string
                    example: FORBIDDEN
                  body:
                    type: object
                    properties: {  }
      tags:
        - Referrals
    parameters:
      -
        in: path
        name: id
        description: 'The referral ID.'
        example: 1
        required: true
        schema:
          type: integer
  '/api/referrals/{id}/status':
    patch:
      summary: 'Update referral status'
      operationId: updateReferralStatus
      description: 'Updates the status of a referral. Admin/agent only.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: REFERRAL_STATUS_UPDATED
                  body:
                    id: 1
                    status: qualified
                properties:
                  message:
                    type: string
                    example: REFERRAL_STATUS_UPDATED
                  body:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 1
                      status:
                        type: string
                        example: qualified
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: FORBIDDEN
                  body: {  }
                properties:
                  message:
                    type: string
                    example: FORBIDDEN
                  body:
                    type: object
                    properties: {  }
      tags:
        - Referrals
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  type: string
                  description: 'One of: qualified, in_progress, price_agreed, completed, rejected.'
                  example: qualified
              required:
                - status
    parameters:
      -
        in: path
        name: id
        description: ''
        example: 1
        required: true
        schema:
          type: integer
  '/api/referrals/{id}/reject':
    post:
      summary: 'Reject referral'
      operationId: rejectReferral
      description: "Rejects a referral with a mandatory reason. Notifies the referrer by email.\nAdmin/agent only."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: REFERRAL_REJECTED
                  body:
                    id: 1
                properties:
                  message:
                    type: string
                    example: REFERRAL_REJECTED
                  body:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 1
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: FORBIDDEN
                  body: {  }
                properties:
                  message:
                    type: string
                    example: FORBIDDEN
                  body:
                    type: object
                    properties: {  }
      tags:
        - Referrals
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                rejection_reason:
                  type: string
                  description: ''
                  example: 'Klijent je već u kontaktu sa drugom agencijom.'
              required:
                - rejection_reason
    parameters:
      -
        in: path
        name: id
        description: ''
        example: 1
        required: true
        schema:
          type: integer
  '/api/referrals/{referralId}/activities':
    get:
      summary: 'List activities'
      operationId: listActivities
      description: "Returns the property timeline for a referral.\nPartners only see activities with `visibility = referrer`; admins/agents see all."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: ACTIVITIES_RETRIEVED
                  body:
                    activities: []
                properties:
                  message:
                    type: string
                    example: ACTIVITIES_RETRIEVED
                  body:
                    type: object
                    properties:
                      activities:
                        type: array
                        example: []
      tags:
        - 'Property Timeline'
    post:
      summary: 'Add activity'
      operationId: addActivity
      description: 'Adds a new timeline activity to a referral. Admin/agent only.'
      parameters: []
      responses:
        201:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: ACTIVITY_CREATED
                  body:
                    id: 1
                properties:
                  message:
                    type: string
                    example: ACTIVITY_CREATED
                  body:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 1
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: FORBIDDEN
                  body: {  }
                properties:
                  message:
                    type: string
                    example: FORBIDDEN
                  body:
                    type: object
                    properties: {  }
      tags:
        - 'Property Timeline'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                activity_type_id:
                  type: integer
                  description: 'ID of the activity type.'
                  example: 3
                description:
                  type: string
                  description: 'Visible to the referrer.'
                  example: 'Client meeting scheduled for Monday.'
                agent_notes:
                  type: string
                  description: 'optional Internal notes, not visible to referrer.'
                  example: 'Client seems motivated.'
                  nullable: true
                visibility:
                  type: string
                  description: "optional referrer or admin_only. Defaults to the activity type's default."
                  example: referrer
                  nullable: true
                amount:
                  type: number
                  description: 'optional Deal amount relevant to this step.'
                  example: 175000.0
                  nullable: true
                next_action:
                  type: string
                  description: 'optional What happens next.'
                  example: 'Send offer'
                  nullable: true
                due_date:
                  type: string
                  description: 'optional Expected date (Y-m-d).'
                  example: '2026-06-15'
                  nullable: true
              required:
                - activity_type_id
                - description
    parameters:
      -
        in: path
        name: referralId
        description: ''
        example: 1
        required: true
        schema:
          type: integer
  /api/admin/users:
    get:
      summary: 'List users'
      operationId: listUsers
      description: 'Returns all users with filtering. Includes pending approval queue.'
      parameters:
        -
          in: query
          name: status
          description: 'optional Filter by status.'
          example: pending_approval
          required: false
          schema:
            type: string
            description: 'optional Filter by status.'
            example: pending_approval
        -
          in: query
          name: search
          description: 'optional Search by name or email.'
          example: Jelena
          required: false
          schema:
            type: string
            description: 'optional Search by name or email.'
            example: Jelena
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: USERS_RETRIEVED
                  body:
                    users: []
                    total: 0
                properties:
                  message:
                    type: string
                    example: USERS_RETRIEVED
                  body:
                    type: object
                    properties:
                      users:
                        type: array
                        example: []
                      total:
                        type: integer
                        example: 0
      tags:
        - 'Admin: Users'
  '/api/admin/users/{id}/approve':
    post:
      summary: 'Approve user'
      operationId: approveUser
      description: 'Sets user status to `active`, generates a referral code, and sends a welcome email.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: USER_APPROVED
                  body:
                    id: 42
                    referral_code: AB12CD34
                properties:
                  message:
                    type: string
                    example: USER_APPROVED
                  body:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 42
                      referral_code:
                        type: string
                        example: AB12CD34
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: FORBIDDEN
                  body: {  }
                properties:
                  message:
                    type: string
                    example: FORBIDDEN
                  body:
                    type: object
                    properties: {  }
      tags:
        - 'Admin: Users'
    parameters:
      -
        in: path
        name: id
        description: ''
        example: 42
        required: true
        schema:
          type: integer
  '/api/admin/users/{id}/block':
    post:
      summary: 'Block user'
      operationId: blockUser
      description: 'Sets user status to `blocked`, preventing login.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: USER_BLOCKED
                  body:
                    id: 42
                properties:
                  message:
                    type: string
                    example: USER_BLOCKED
                  body:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 42
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: FORBIDDEN
                  body: {  }
                properties:
                  message:
                    type: string
                    example: FORBIDDEN
                  body:
                    type: object
                    properties: {  }
      tags:
        - 'Admin: Users'
    parameters:
      -
        in: path
        name: id
        description: ''
        example: 42
        required: true
        schema:
          type: integer
  '/api/admin/users/{id}/promote':
    post:
      summary: 'Promote to partner'
      operationId: promoteToPartner
      description: 'Force-promotes a candidate to partner role regardless of deal count.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: USER_PROMOTED
                  body:
                    id: 42
                properties:
                  message:
                    type: string
                    example: USER_PROMOTED
                  body:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 42
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: FORBIDDEN
                  body: {  }
                properties:
                  message:
                    type: string
                    example: FORBIDDEN
                  body:
                    type: object
                    properties: {  }
      tags:
        - 'Admin: Users'
    parameters:
      -
        in: path
        name: id
        description: ''
        example: 42
        required: true
        schema:
          type: integer
  /api/admin/commissions/preview:
    get:
      summary: 'Preview commission'
      operationId: previewCommission
      description: "Calculates the commission breakdown for a referral before confirming.\nIncludes referral bonus if the referrer has a sponsor."
      parameters:
        -
          in: query
          name: referral_id
          description: 'The referral to calculate for.'
          example: 5
          required: true
          schema:
            type: integer
            description: 'The referral to calculate for.'
            example: 5
        -
          in: query
          name: agency_commission
          description: 'Agency commission amount in EUR (NOT property price).'
          example: 3500.0
          required: true
          schema:
            type: number
            description: 'Agency commission amount in EUR (NOT property price).'
            example: 3500.0
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: COMMISSION_PREVIEW
                  body:
                    rate: 0.1
                    partner_amount: 350.0
                    sponsor_bonus: 35.0
                    sub_partner_net: 315.0
                    bonus_eligible: true
                properties:
                  message:
                    type: string
                    example: COMMISSION_PREVIEW
                  body:
                    type: object
                    properties:
                      rate:
                        type: number
                        example: 0.1
                      partner_amount:
                        type: number
                        example: 350.0
                      sponsor_bonus:
                        type: number
                        example: 35.0
                      sub_partner_net:
                        type: number
                        example: 315.0
                      bonus_eligible:
                        type: boolean
                        example: true
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: FORBIDDEN
                  body: {  }
                properties:
                  message:
                    type: string
                    example: FORBIDDEN
                  body:
                    type: object
                    properties: {  }
      tags:
        - 'Admin: Commissions'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                referral_id:
                  type: integer
                  description: 'Must match an existing stored value.'
                  example: 16
                agency_commission:
                  type: number
                  description: 'Must be at least 750.'
                  example: 662
              required:
                - referral_id
                - agency_commission
  /api/admin/commissions:
    post:
      summary: 'Create commission'
      operationId: createCommission
      description: "Confirms and persists the direct commission for a referral, and (if the\nreferrer has an eligible sponsor) auto-creates the sponsor's referral\nbonus — 10% of the direct amount, deducted from the sub-partner per the\nbruto=neto model. Admin only. This is the reset-proof home for commission\ncreation (PCMS module extensions are regenerated away by hard-reset/sync)."
      parameters: []
      responses:
        201:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: COMMISSION_CREATED
                  body:
                    direct_id: 1
                    direct_amount: 500.0
                    bonus_id: 2
                    sponsor_bonus: 50.0
                properties:
                  message:
                    type: string
                    example: COMMISSION_CREATED
                  body:
                    type: object
                    properties:
                      direct_id:
                        type: integer
                        example: 1
                      direct_amount:
                        type: number
                        example: 500.0
                      bonus_id:
                        type: integer
                        example: 2
                      sponsor_bonus:
                        type: number
                        example: 50.0
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: FORBIDDEN
                  body: {  }
                properties:
                  message:
                    type: string
                    example: FORBIDDEN
                  body:
                    type: object
                    properties: {  }
      tags:
        - 'Admin: Commissions'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                referral_id:
                  type: integer
                  description: ''
                  example: 5
                agency_commission:
                  type: number
                  description: 'Agency commission in EUR (min 750).'
                  example: 5000.0
              required:
                - referral_id
                - agency_commission
  /api/admin/payouts:
    post:
      summary: 'Initiate monthly payout'
      operationId: initiateMonthlyPayout
      description: 'Creates payout records for all partners with pending commissions and notifies them.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: PAYOUT_INITIATED
                  body:
                    payouts_created: 5
                    total_disbursed: 4250.0
                properties:
                  message:
                    type: string
                    example: PAYOUT_INITIATED
                  body:
                    type: object
                    properties:
                      payouts_created:
                        type: integer
                        example: 5
                      total_disbursed:
                        type: number
                        example: 4250.0
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: FORBIDDEN
                  body: {  }
                properties:
                  message:
                    type: string
                    example: FORBIDDEN
                  body:
                    type: object
                    properties: {  }
      tags:
        - 'Admin: Payouts'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                period_month:
                  type: integer
                  description: 'Month (1–12).'
                  example: 6
                period_year:
                  type: integer
                  description: Year.
                  example: 2026
              required:
                - period_month
                - period_year
  /api/refresh-api-overdraft-status:
    get:
      summary: 'Refresh API overdraft status'
      operationId: refreshAPIOverdraftStatus
      description: 'Refreshes and returns the current API overdraft flag. Used by the frontend to check if the API call limit is exceeded.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: API_OVERDRAFT_STATUS_REFRESH_SUCCESS
                  body:
                    api_overdraft_status: false
                properties:
                  message:
                    type: string
                    example: API_OVERDRAFT_STATUS_REFRESH_SUCCESS
                  body:
                    type: object
                    properties:
                      api_overdraft_status:
                        type: boolean
                        example: false
      tags:
        - General
      security: []
  /api/database-export:
    get:
      summary: 'Check export status'
      operationId: checkExportStatus
      description: 'Returns the current database export status and a list of available export files.'
      parameters: []
      responses:
        500:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: GENERAL_EXCEPTION
                  body:
                    message: "There's been an error!"
                    code: disabled
                    file: disabled
                    line: disabled
                    trace: disabled
                properties:
                  message:
                    type: string
                    example: GENERAL_EXCEPTION
                  body:
                    type: object
                    properties:
                      message:
                        type: string
                        example: "There's been an error!"
                      code:
                        type: string
                        example: disabled
                      file:
                        type: string
                        example: disabled
                      line:
                        type: string
                        example: disabled
                      trace:
                        type: string
                        example: disabled
      tags:
        - General
    post:
      summary: 'Export database'
      operationId: exportDatabase
      description: 'Dispatches an async job to export the database to a `.tar` archive. Check export status to poll for completion.'
      parameters: []
      responses: {  }
      tags:
        - General
  /api/database-import:
    get:
      summary: 'Check import status'
      operationId: checkImportStatus
      description: 'Returns the current database import status.'
      parameters: []
      responses:
        500:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: GENERAL_EXCEPTION
                  body:
                    message: "There's been an error!"
                    code: disabled
                    file: disabled
                    line: disabled
                    trace: disabled
                properties:
                  message:
                    type: string
                    example: GENERAL_EXCEPTION
                  body:
                    type: object
                    properties:
                      message:
                        type: string
                        example: "There's been an error!"
                      code:
                        type: string
                        example: disabled
                      file:
                        type: string
                        example: disabled
                      line:
                        type: string
                        example: disabled
                      trace:
                        type: string
                        example: disabled
      tags:
        - General
    post:
      summary: 'Import database'
      operationId: importDatabase
      description: 'Uploads a `.tar` database backup file and dispatches an async import job.'
      parameters: []
      responses: {  }
      tags:
        - General
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                  description: 'The `.tar` database backup file to import.'
              required:
                - file
  /api/photon/hard-reset:
    get:
      summary: 'Hard reset CMS'
      operationId: hardResetCMS
      description: 'Clears all dynamic models, migrations and DB tables, then rebuilds and re-seeds from scratch. Destructive — use with extreme caution.'
      parameters:
        -
          in: query
          name: clean
          description: 'optional If true, also removes generated model and migration files.'
          example: false
          required: false
          schema:
            type: boolean
            description: 'optional If true, also removes generated model and migration files.'
            example: false
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: PHOTON_HARD_RESET_SUCCESS
                  body: []
                properties:
                  message:
                    type: string
                    example: PHOTON_HARD_RESET_SUCCESS
                  body:
                    type: array
                    example: []
      tags:
        - General
  /api/photon/soft-reset:
    get:
      summary: 'Soft reset CMS'
      operationId: softResetCMS
      description: 'Resets the CMS to its default state while preserving module extenders. Useful when a project-specific seed is configured.'
      parameters:
        -
          in: query
          name: clean
          description: 'optional If true, also removes generated files.'
          example: false
          required: false
          schema:
            type: boolean
            description: 'optional If true, also removes generated files.'
            example: false
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: PHOTON_SOFT_RESET_SUCCESS
                  body: []
                properties:
                  message:
                    type: string
                    example: PHOTON_SOFT_RESET_SUCCESS
                  body:
                    type: array
                    example: []
      tags:
        - General
  /api/ai/translate:
    post:
      summary: 'Translate text (AI)'
      operationId: translateTextAI
      description: 'Translates the given text to the target language using OpenAI. Requires `OPENAI_API_KEY` to be configured.'
      parameters: []
      responses: {  }
      tags:
        - General
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                string:
                  type: string
                  description: 'The text to translate.'
                  example: 'Hello world'
                target_language_code:
                  type: string
                  description: 'ISO 639-1 language code of the target language.'
                  example: de
              required:
                - string
                - target_language_code
  /api/ai/edit:
    post:
      summary: 'Edit text (AI)'
      operationId: editTextAI
      description: 'Edits or rewrites text according to the given system prompt, using OpenAI. Requires `OPENAI_API_KEY` to be configured.'
      parameters: []
      responses: {  }
      tags:
        - General
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                text:
                  type: string
                  description: 'The text to edit or rewrite.'
                  example: 'This is a rough draft.'
                system_prompt:
                  type: string
                  description: 'Instructions for the AI on how to edit the text.'
                  example: 'Fix grammar and improve clarity.'
                target_language_code:
                  type: string
                  description: 'optional Target language code if translation is also needed.'
                  example: en
              required:
                - text
                - system_prompt
  '/api/admin/referrals/{id}':
    delete:
      summary: 'Remove referral from system'
      operationId: removeReferralFromSystem
      description: "Fully deletes a referral from the system (e.g. deal closed through another agency).\nDifferent from rejection — the record is permanently removed."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: REFERRAL_REMOVED
                  body:
                    id: 5
                properties:
                  message:
                    type: string
                    example: REFERRAL_REMOVED
                  body:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 5
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: FORBIDDEN
                  body: {  }
                properties:
                  message:
                    type: string
                    example: FORBIDDEN
                  body:
                    type: object
                    properties: {  }
      tags:
        - 'Admin: Referrals'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
                  description: 'Reason for removal.'
                  example: 'Deal closed through another agency.'
              required:
                - reason
    parameters:
      -
        in: path
        name: id
        description: ''
        example: 5
        required: true
        schema:
          type: integer
  '/api/{tableName}/{entryId}':
    get:
      summary: 'Retrieves a single dynamic module entry.'
      operationId: retrievesASingleDynamicModuleEntry
      description: ''
      parameters: []
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Entries
    delete:
      summary: 'Delete entry'
      operationId: deleteEntry
      description: 'Deletes a module entry. The entry must have no related entries in other modules unless `force` is passed.'
      parameters: []
      responses: {  }
      tags:
        - Entries
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                force:
                  type: boolean
                  description: 'optional Set to `true` to force delete even if the entry has related entries.'
                  example: false
    parameters:
      -
        in: path
        name: tableName
        description: ''
        example: architecto
        required: true
        schema:
          type: string
      -
        in: path
        name: entryId
        description: ''
        example: '564'
        required: true
        schema:
          type: string
  /api/filter:
    post:
      summary: 'Filter entries'
      operationId: filterEntries
      description: 'Returns paginated entries from one or more modules matching the given filter, sorting and pagination criteria.'
      parameters: []
      responses: {  }
      tags:
        - Entries
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                modules:
                  type: array
                  description: 'Module table name(s) to query.'
                  example:
                    - news
                  items:
                    type: string
                filter:
                  type: object
                  description: 'optional Filter criteria split into `system` and `fields` sub-objects.'
                  example: []
                  properties:
                    system:
                      type: object
                      description: 'optional System-level filter conditions (e.g. published, created_at range).'
                      example: []
                      properties: {  }
                    fields:
                      type: object
                      description: 'optional Field-level filter conditions.'
                      example: []
                      properties: {  }
                sorting:
                  type: object
                  description: 'optional Sorting configuration.'
                  example: []
                  properties:
                    field:
                      type: string
                      description: 'optional Field name to sort by.'
                      example: created_at
                    direction:
                      type: string
                      description: 'optional Sort direction (`asc` or `desc`).'
                      example: desc
                pagination:
                  type: object
                  description: 'optional Pagination settings.'
                  example: []
                  properties:
                    items_per_page:
                      type: integer
                      description: 'optional Number of items per page (max defined in config).'
                      example: 15
                    current_page:
                      type: integer
                      description: 'optional Current page number.'
                      example: 1
                include:
                  type: array
                  description: 'optional Related fields/relations to eager-load in the response.'
                  example:
                    - architecto
                  items:
                    type: string
              required:
                - modules
  '/api/export/download/{fileName}':
    get:
      summary: 'Download export'
      operationId: downloadExport
      description: 'Downloads a previously exported file by its file name. Use the file name returned by the export endpoint.'
      parameters: []
      responses:
        404:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: FILE_NOT_FOUND
                  body:
                    file: /Users/milanandjelkovic/Sites/m2-partner-api/storage/app/database-exports/architecto
                properties:
                  message:
                    type: string
                    example: FILE_NOT_FOUND
                  body:
                    type: object
                    properties:
                      file:
                        type: string
                        example: /Users/milanandjelkovic/Sites/m2-partner-api/storage/app/database-exports/architecto
      tags:
        - Entries
      security: []
    parameters:
      -
        in: path
        name: fileName
        description: ''
        example: architecto
        required: true
        schema:
          type: string
  '/api/nodes/{tableName}/{id}':
    get:
      summary: 'Get node children'
      operationId: getNodeChildren
      description: 'Returns the immediate children of the specified node, or root-level nodes if no ID is given.'
      parameters:
        -
          in: query
          name: child_modules
          description: 'optional Comma-separated list of scoped child module table names to include.'
          example: architecto
          required: false
          schema:
            type: string
            description: 'optional Comma-separated list of scoped child module table names to include.'
            example: architecto
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Entries
    parameters:
      -
        in: path
        name: tableName
        description: ''
        example: architecto
        required: true
        schema:
          type: string
      -
        in: path
        name: id
        description: 'The ID of the {tableName}.'
        example: architecto
        required: true
        schema:
          type: string
  '/api/nodes/{tableName}/ancestors/{id}':
    get:
      summary: 'Get node ancestors'
      operationId: getNodeAncestors
      description: 'Returns the ancestral tree path from the root down to the specified node.'
      parameters: []
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Entries
    parameters:
      -
        in: path
        name: tableName
        description: ''
        example: architecto
        required: true
        schema:
          type: string
      -
        in: path
        name: id
        description: 'The ID of the ancestor.'
        example: architecto
        required: true
        schema:
          type: string
  '/api/nodes/{tableName}':
    get:
      summary: 'Get node children'
      operationId: getNodeChildren
      description: 'Returns the immediate children of the specified node, or root-level nodes if no ID is given.'
      parameters:
        -
          in: query
          name: child_modules
          description: 'optional Comma-separated list of scoped child module table names to include.'
          example: architecto
          required: false
          schema:
            type: string
            description: 'optional Comma-separated list of scoped child module table names to include.'
            example: architecto
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Entries
    parameters:
      -
        in: path
        name: tableName
        description: ''
        example: architecto
        required: true
        schema:
          type: string
  /api/nodes/reposition:
    put:
      summary: 'Reposition node'
      operationId: repositionNode
      description: 'Repositions a node within the tree using a named action (e.g. moveLeft, makeChildOf).'
      parameters: []
      responses: {  }
      tags:
        - Entries
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                action:
                  type: string
                  description: 'The repositioning action to perform.'
                  example: moveLeft
                affected:
                  type: object
                  description: 'The node to reposition (must include `id` and `table_name`).'
                  example: []
                  properties: {  }
                target:
                  type: object
                  description: 'optional The target node for actions like `makeChildOf` or `moveBefore`.'
                  example: []
                  properties: {  }
              required:
                - action
                - affected
  '/api/extension_call/{tableName}/{entryId}/{action}/{parameters}':
    get:
      summary: 'Call extension action'
      operationId: callExtensionAction
      description: "Calls a custom action defined in the module's extension class."
      parameters: []
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Entries
    parameters:
      -
        in: path
        name: tableName
        description: ''
        example: architecto
        required: true
        schema:
          type: string
      -
        in: path
        name: entryId
        description: ''
        example: architecto
        required: true
        schema:
          type: string
      -
        in: path
        name: action
        description: ''
        example: architecto
        required: true
        schema:
          type: string
      -
        in: path
        name: parameters
        description: 'Optional parameter.'
        required: true
        schema:
          type: string
        examples:
          omitted:
            summary: 'When the value is omitted'
            value: ''
          present:
            summary: 'When the value is present'
            value: '{+-0pB'
  '/api/subscribe/{tableName}/{entryId}':
    post:
      summary: 'Subscribe to entry'
      operationId: subscribeToEntry
      description: 'Subscribes the authenticated user to change notifications for the specified entry.'
      parameters: []
      responses: {  }
      tags:
        - Entries
    delete:
      summary: 'Unsubscribe from entry'
      operationId: unsubscribeFromEntry
      description: 'Unsubscribes the authenticated user from change notifications for the specified entry.'
      parameters: []
      responses: {  }
      tags:
        - Entries
    parameters:
      -
        in: path
        name: tableName
        description: ''
        example: architecto
        required: true
        schema:
          type: string
      -
        in: path
        name: entryId
        description: ''
        example: architecto
        required: true
        schema:
          type: string
  '/api/{tableName}':
    post:
      summary: 'Create entry'
      operationId: createEntry
      description: 'Creates a new entry in the specified module. File uploads are supported for asset modules (multipart/form-data).'
      parameters: []
      responses: {  }
      tags:
        - Entries
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                system:
                  type: object
                  description: 'optional System-level fields (e.g. permissions, status overrides).'
                  example: []
                  properties: {  }
                fields:
                  type: object
                  description: "The module's field values keyed by field column name."
                  example: []
                  properties: {  }
              required:
                - fields
    put:
      summary: 'Mass update entries'
      operationId: massUpdateEntries
      description: 'Applies a bulk update to all module entries matching the given filter.'
      parameters: []
      responses: {  }
      tags:
        - Entries
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                filter:
                  type: object
                  description: 'optional Filter to select which entries to update.'
                  example: []
                  properties: {  }
                fields:
                  type: object
                  description: 'optional Field values to set on matched entries.'
                  example: []
                  properties: {  }
    parameters:
      -
        in: path
        name: tableName
        description: ''
        example: architecto
        required: true
        schema:
          type: string
  '/api/duplicate/{tableName}/{entryId}':
    post:
      summary: 'Duplicate entry'
      operationId: duplicateEntry
      description: 'Creates a copy of an existing module entry, preserving all field values.'
      parameters: []
      responses: {  }
      tags:
        - Entries
    parameters:
      -
        in: path
        name: tableName
        description: ''
        example: architecto
        required: true
        schema:
          type: string
      -
        in: path
        name: entryId
        description: ''
        example: architecto
        required: true
        schema:
          type: string
  '/api/{tableName}/{id}':
    put:
      summary: 'Update entry'
      operationId: updateEntry
      description: 'Updates field values on an existing module entry.'
      parameters: []
      responses: {  }
      tags:
        - Entries
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                system:
                  type: object
                  description: 'optional System-level overrides.'
                  example: []
                  properties: {  }
                fields:
                  type: object
                  description: 'The field values to update, keyed by column name.'
                  example: []
                  properties: {  }
              required:
                - fields
    parameters:
      -
        in: path
        name: tableName
        description: ''
        example: architecto
        required: true
        schema:
          type: string
      -
        in: path
        name: id
        description: 'The ID of the {tableName}.'
        example: architecto
        required: true
        schema:
          type: string
  '/api/export/{tableName}':
    post:
      summary: 'Export entries'
      operationId: exportEntries
      description: 'Exports module entries matching the given filter to a file (e.g. XLSX). Returns a file name to use with the download endpoint.'
      parameters: []
      responses: {  }
      tags:
        - Entries
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                file_type:
                  type: string
                  description: 'optional Export format.'
                  example: xlsx
                file_name:
                  type: string
                  description: 'optional Output file name (without extension). A UUID is used if omitted.'
                  example: news-export
                filter:
                  type: object
                  description: 'optional Filter criteria for which entries to export.'
                  example: []
                  properties: {  }
                sorting:
                  type: object
                  description: 'optional Sorting configuration.'
                  example: []
                  properties: {  }
                parameters:
                  type: object
                  description: 'optional Additional export-specific parameters.'
                  example: []
                  properties: {  }
    parameters:
      -
        in: path
        name: tableName
        description: ''
        example: architecto
        required: true
        schema:
          type: string
  '/api/export/{tableName}/{entryId}':
    post:
      summary: 'Export single entry'
      operationId: exportSingleEntry
      description: 'Exports a single module entry to a file.'
      parameters: []
      responses: {  }
      tags:
        - Entries
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                file_type:
                  type: string
                  description: 'optional Export format.'
                  example: xlsx
                file_name:
                  type: string
                  description: 'optional Output file name (without extension).'
                  example: entry-export
                parameters:
                  type: object
                  description: 'optional Additional export-specific parameters.'
                  example: []
                  properties: {  }
    parameters:
      -
        in: path
        name: tableName
        description: ''
        example: architecto
        required: true
        schema:
          type: string
      -
        in: path
        name: entryId
        description: ''
        example: architecto
        required: true
        schema:
          type: string
  '/api/count/{tableName}':
    post:
      summary: 'Count entries'
      operationId: countEntries
      description: 'Returns the total count of module entries matching the given filter.'
      parameters: []
      responses: {  }
      tags:
        - Entries
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                filter:
                  type: object
                  description: 'optional Filter criteria to apply before counting.'
                  example: []
                  properties: {  }
    parameters:
      -
        in: path
        name: tableName
        description: ''
        example: architecto
        required: true
        schema:
          type: string
  '/api/stats/{tableName}':
    get:
      summary: 'Get entry stats'
      operationId: getEntryStats
      description: "Returns aggregated statistics (totals, breakdowns) for the specified module's entries."
      parameters: []
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Entries
    parameters:
      -
        in: path
        name: tableName
        description: ''
        example: architecto
        required: true
        schema:
          type: string
  '/api/weekly-chart/{tableName}':
    post:
      summary: 'Get weekly chart data'
      operationId: getWeeklyChartData
      description: 'Returns entry counts grouped by week for charting purposes.'
      parameters: []
      responses: {  }
      tags:
        - Entries
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                chart_period:
                  type: integer
                  description: 'optional Number of weeks to include in the chart.'
                  example: 4
    parameters:
      -
        in: path
        name: tableName
        description: ''
        example: architecto
        required: true
        schema:
          type: string
  /api/field_types:
    get:
      summary: 'Retrieves all field types.'
      operationId: retrievesAllFieldTypes
      description: ''
      parameters: []
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Fields
  /api/modules:
    get:
      summary: 'List modules'
      operationId: listModules
      description: 'Returns all registered CMS modules with their field definitions.'
      parameters: []
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Modules
    post:
      summary: 'Create module'
      operationId: createModule
      description: 'Creates a new dynamic module with its database table and field definitions. Requires super admin + dev environment.'
      parameters: []
      responses: {  }
      tags:
        - Modules
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                module:
                  type: object
                  description: 'Module definition object.'
                  example: []
                  properties:
                    name:
                      type: string
                      description: 'Human-readable module name.'
                      example: 'News Articles'
                    table_name:
                      type: string
                      description: 'Database table name (snake_case).'
                      example: news_articles
                    type:
                      type: integer
                      description: 'Module type ID (1=non-sortable, 2=sortable, 3=multilevel, etc.).'
                      example: 1
                  required:
                    - name
                    - table_name
                    - type
                fields:
                  type: array
                  description: 'optional Array of field definition objects.'
                  example:
                    - architecto
                  items:
                    type: string
                reporting:
                  type: boolean
                  description: 'optional Enable reporting dashboard for this module.'
                  example: false
              required:
                - module
  '/api/modules/{table}':
    put:
      summary: 'Update module'
      operationId: updateModule
      description: "Updates an existing module's definition and field structure. Requires super admin + dev environment."
      parameters: []
      responses: {  }
      tags:
        - Modules
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                module:
                  type: object
                  description: 'Updated module definition object.'
                  example: []
                  properties: {  }
                fields:
                  type: array
                  description: 'optional Updated array of field definition objects.'
                  example:
                    - architecto
                  items:
                    type: string
                reporting:
                  type: boolean
                  description: 'optional Enable/disable reporting for this module.'
                  example: false
              required:
                - module
    get:
      summary: 'Get module'
      operationId: getModule
      description: "Returns a single module's definition including all field configurations."
      parameters: []
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Modules
    delete:
      summary: 'Delete module'
      operationId: deleteModule
      description: 'Permanently deletes a module and its database table. Requires super admin + dev environment.'
      parameters: []
      responses: {  }
      tags:
        - Modules
    parameters:
      -
        in: path
        name: table
        description: ''
        example: architecto
        required: true
        schema:
          type: string
  '/api/notify/{notification_name}':
    post:
      summary: 'Sends the specified notification.'
      operationId: sendsTheSpecifiedNotification
      description: ''
      parameters: []
      responses: {  }
      tags:
        - Notifications
    parameters:
      -
        in: path
        name: notification_name
        description: ''
        example: architecto
        required: true
        schema:
          type: string
  '/api/notifications/read/{notificationId}':
    get:
      summary: 'Marks the specific notification as read.'
      operationId: marksTheSpecificNotificationAsRead
      description: ''
      parameters: []
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Notifications
    parameters:
      -
        in: path
        name: notificationId
        description: ''
        example: architecto
        required: true
        schema:
          type: string
  /api/notifications/unread/count:
    get:
      summary: 'Counts unread notifications of the currently logged in user.'
      operationId: countsUnreadNotificationsOfTheCurrentlyLoggedInUser
      description: ''
      parameters: []
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Notifications
  /api/notifications/all:
    post:
      summary: 'Get notifications'
      operationId: getNotifications
      description: 'Retrieves paginated notifications for the authenticated user.'
      parameters: []
      responses: {  }
      tags:
        - Notifications
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                pagination:
                  type: object
                  description: 'optional Pagination settings.'
                  example: []
                  properties:
                    items_per_page:
                      type: integer
                      description: 'optional Items per page.'
                      example: 10
                    current_page:
                      type: integer
                      description: 'optional Current page.'
                      example: 1
  /api/notifications/unread:
    post:
      summary: 'Get unread notifications'
      operationId: getUnreadNotifications
      description: 'Retrieves paginated unread notifications for the authenticated user.'
      parameters: []
      responses: {  }
      tags:
        - Notifications
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                pagination:
                  type: object
                  description: 'optional Pagination settings.'
                  example: []
                  properties:
                    items_per_page:
                      type: integer
                      description: 'optional Items per page.'
                      example: 10
                    current_page:
                      type: integer
                      description: 'optional Current page.'
                      example: 1
  '/api/notifications/fcm/assign_token/{token}':
    get:
      summary: 'Assigns the specified FCM token to the currently logged in user.'
      operationId: assignsTheSpecifiedFCMTokenToTheCurrentlyLoggedInUser
      description: ''
      parameters: []
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Notifications
    parameters:
      -
        in: path
        name: token
        description: ''
        example: architecto
        required: true
        schema:
          type: string
  '/api/notifications/fcm/revoke_token/{token}':
    get:
      summary: 'Revokes the specified FCM token from the currently logged in user.'
      operationId: revokesTheSpecifiedFCMTokenFromTheCurrentlyLoggedInUser
      description: ''
      parameters: []
      responses:
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: TOKEN_EXPIRED
                  body: []
                properties:
                  message:
                    type: string
                    example: TOKEN_EXPIRED
                  body:
                    type: array
                    example: []
      tags:
        - Notifications
    parameters:
      -
        in: path
        name: token
        description: ''
        example: architecto
        required: true
        schema:
          type: string
