openapi: 3.0.3
info:
  title: UNA CMS API
  version: 1.0.0
  description: |
    # UNA CMS REST API Documentation

    Production-ready REST API for UNA CMS platform providing comprehensive access to content management,
    user profiles, events, groups, notifications, polls, and other platform features.

    **Current Version**: 1.0.0
    **Total Endpoints**: 52
    **Modules Covered**: 9 (Authentication, Content, Profiles, Events, Posts, Timeline, Groups, Notifications, Polls)

    **Note**: UNA's api.php does not enforce HTTP methods. All endpoints accept any HTTP method via query parameters. All examples in this documentation use GET for consistency.

    ---

    ## 🔐 Authentication

    All API requests require **dual authentication**:

    | Requirement | Method | How to Obtain |
    |-------------|--------|---------------|
    | **Bearer Token** | `Authorization: Bearer YOUR_TOKEN` | Studio > Settings > API > Keys |
    | **Session Cookie** | `Cookie: memberSession=SESSION_ID` | Login endpoint or browser session |

    ### Quick Start Authentication

    ```bash
    # Step 1: Get Bearer token from Studio
    BEARER_TOKEN="your_api_key_here"

    # Step 2: Login to get session cookie
    curl -s -H "Authorization: Bearer ${BEARER_TOKEN}" \
      "http://your-site.com/api.php?r=system/login/TemplServiceContent&params[]=USER_ID"

    # Step 3: Use both in subsequent requests
    curl -s \
      -H "Authorization: Bearer ${BEARER_TOKEN}" \
      --cookie "memberSession=SESSION_COOKIE" \
      "http://your-site.com/api.php?r=system/test/TemplServiceLogin"
    ```

    ---

    ## 📡 Request Format

    ### Endpoint Structure

    All requests use a single endpoint (`/api.php`) with the `r` parameter specifying the service:

    ```
    /api.php?r=module/method/ServiceClass&params=...
    ```

    **Format**: `module/method/ServiceClass`

    | Component | Description | Examples |
    |-----------|-------------|----------|
    | `module` | Module name | `system`, `bx_events`, `bx_posts` |
    | `method` | Service method | `get_info`, `browse`, `update` |
    | `ServiceClass` | Service class | `TemplServiceContent`, `Module` |

    ### Parameter Formats

    Parameters can be passed in **two ways**:

    #### 1. JSON Array (URL-encoded) - Recommended for complex data

    ```bash
    # Original JSON
    ["bx_persons", 43, {"description": "Updated bio"}]

    # URL-encoded
    PARAMS='["bx_persons",43,{"description":"Updated bio"}]'
    ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
    curl "...&params=${ENCODED}"
    ```

    #### 2. Array Style - Simple for basic parameters

    ```bash
    curl "...&params[]=bx_persons&params[]=43&params[]=picture&params[]=https://example.com/pic.jpg"
    ```

    ---

    ## 📦 Response Format

    ### Success Response (HTTP 200)

    ```json
    {
      "status": 200,
      "module": "system",
      "method": "test",
      "params": [5],
      "data": 10,
      "hash": "abc123def456..."
    }
    ```

    | Field | Type | Description |
    |-------|------|-------------|
    | `status` | integer | HTTP status code (always 200 for success) |
    | `module` | string | Module that handled the request |
    | `method` | string | Service method that was called |
    | `params` | array | Parameters that were passed |
    | `data` | mixed | Response data (type varies by endpoint) |
    | `hash` | string | MD5 hash of API configuration |

    ### Error Responses

    #### 403 Forbidden - Authentication Failed
    ```json
    {
      "status": 403,
      "error": "Access denied"
    }
    ```
    **Causes**: Invalid Bearer token, missing session cookie, or insufficient permissions.

    #### 404 Not Found - Service Not Found
    ```json
    {
      "status": 404,
      "error": "Service not found"
    }
    ```
    **Causes**: Invalid `r` parameter or service not marked as safe.

    #### 500 Internal Server Error - Permission Denied
    ```json
    {
      "status": 500,
      "error": "Permission denied"
    }
    ```
    **Causes**: User lacks permission to perform the requested action.

    ---

    ## 🔧 Advanced Features

    ### Condition Parameter

    Browse endpoints support custom SQL restrictions via the `condition` parameter:

    ```json
    {
      "condition": {
        "restriction": {
          "value": "1735689600",
          "field": "date_end",
          "operator": "<",
          "table": "bx_events_data"
        }
      }
    }
    ```

    **Example**: Browse past events for a group
    ```bash
    PARAMS='[495,{"condition":{"restriction":{"value":"UNIX_TIMESTAMP()","field":"date_end","operator":"<","table":"bx_events_data"}}}]'
    ```

    ---

    ## 📚 Additional Resources

    - **[Quick Start Guide](QUICK_START.md)** - Get started in 5 minutes
    - **[cURL Examples](curl_examples.md)** - 51 working examples for all endpoints
    - **[Test Suite](tests/README.md)** - 51 executable tests with 100% pass rate
    - **[API Documentation Plan](API_DOCUMENTATION_PLAN.md)** - Complete implementation details

    ---

    ## ⚙️ Technical Notes

    - **Service Safety**: Services must be marked as "safe" or "public" in the module's `serviceGetSafeServices()` method
    - **Session Management**: UNA uses database-backed sessions (never use native PHP `$_SESSION`)
    - **1:1 Test Mapping**: Every documented endpoint has a corresponding executable test
    - **Graceful Errors**: Tests handle permission issues and empty data gracefully

  contact:
    name: API Support
    url: https://github.com/k12stride/una-cms-service
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT

servers:
  - url: http://community.local.k12.com
    description: Local Docker development environment
  - url: https://your-site.com
    description: Production environment (replace with your actual domain)

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: |
        API key generated in Studio > Settings > API > Keys.

        **How to obtain**:
        1. Login to UNA Studio as administrator
        2. Navigate to Settings > API
        3. Click "Keys" tab
        4. Generate new API key or copy existing one

        **Usage**: Include in Authorization header as `Bearer YOUR_API_KEY`

    cookieAuth:
      type: apiKey
      in: cookie
      name: memberSession
      description: |
        Session cookie obtained via login endpoint or extracted from browser session.

        **How to obtain**:
        - **Option A (API)**: Call `system/login/TemplServiceContent` with user ID
        - **Option B (Browser)**: Extract from browser DevTools > Application > Cookies

        **Usage**: Include in Cookie header as `memberSession=SESSION_ID`

        **Note**: Session cookies expire based on UNA configuration (typically 30 days)

  schemas:
    ErrorResponse:
      type: object
      required:
        - status
        - error
      properties:
        status:
          type: integer
          description: HTTP status code
          enum: [403, 404, 500]
          example: 403
        error:
          type: string
          description: Human-readable error message
          example: "Access denied"
        data:
          type: string
          description: Additional error details (optional)
          example: ""
      example:
        status: 403
        error: "Access denied"

    SuccessResponse:
      type: object
      required:
        - status
        - module
        - method
        - params
        - data
        - hash
      properties:
        status:
          type: integer
          description: HTTP status code (always 200 for success)
          example: 200
        module:
          type: string
          description: Module that handled the request
          example: "system"
        method:
          type: string
          description: Service method that was called
          example: "test"
        params:
          type: array
          description: Parameters that were passed to the service
          items: {}
          example: [5]
        data:
          description: Response data (type and structure varies by endpoint)
          example: 10
        hash:
          type: string
          description: MD5 hash of API configuration for cache validation
          example: "abc123def456789"
      example:
        status: 200
        module: "system"
        method: "test"
        params: [5]
        data: 10
        hash: "abc123def456789"

    ContentInfo:
      type: object
      description: Generic content information object (profiles, posts, events, groups, etc.)
      properties:
        id:
          type: integer
          description: Unique content ID
          example: 43
        title:
          type: string
          description: Content title or name
          example: "John Doe"
        description:
          type: string
          description: Content description or bio
          example: "Software developer and educator"
        author:
          type: integer
          description: Author/creator profile ID
          example: 495
        added:
          type: integer
          description: Creation timestamp (Unix epoch)
          example: 1704067200
        changed:
          type: integer
          description: Last modification timestamp (Unix epoch)
          example: 1704153600
        status:
          type: string
          description: Content status
          enum: [active, pending, suspended, deleted]
          example: "active"

    EventInfo:
      type: object
      description: Event information object
      properties:
        id:
          type: integer
          description: Event ID
          example: 1
        event_name:
          type: string
          description: Event name/title
          example: "Annual Science Fair"
        event_desc:
          type: string
          description: Event description
          example: "Join us for our annual science fair..."
        date_start:
          type: integer
          description: Event start timestamp (Unix epoch)
          example: 1704067200
        date_end:
          type: integer
          description: Event end timestamp (Unix epoch)
          example: 1704153600
        location:
          type: string
          description: Event location
          example: "Main Auditorium"
        author:
          type: integer
          description: Event creator profile ID
          example: 495
        allow_view_to:
          type: integer
          description: Privacy level (negative for group-specific)
          example: -4
        status:
          type: string
          enum: [active, pending, suspended]
          example: "active"

    PollInfo:
      type: object
      description: Poll information object
      properties:
        id:
          type: integer
          description: Poll ID
          example: 2
        title:
          type: string
          description: Poll title/question
          example: "Do you love virtual schooling?"
        text:
          type: string
          description: Poll description
          example: "We'd like to know your opinion..."
        author:
          type: integer
          description: Poll creator profile ID
          example: 495
        added:
          type: integer
          description: Creation timestamp (Unix epoch)
          example: 1704067200
        status:
          type: string
          enum: [active, hidden]
          example: "active"

security:
  - bearerAuth: []
    cookieAuth: []

paths:
  /api.php:
    get:
      tags:
        - Authentication
        - Content Management
        - Profile Management
        - Events
        - Posts
        - Timeline
        - Groups
        - Notifications
        - Polls
      operationId: retrieveData
      summary: All API operations (GET method - UNA accepts all operations via GET)
      description: |
        **All API operations are accessible via GET requests.**

        Since UNA's api.php does not enforce HTTP methods, all operations (create, read, update, delete)
        can be performed using GET requests with query parameters. This unified approach simplifies API
        integration and provides consistent response formats across all modules.

        All requests use the same endpoint (`/api.php`) with the `r` parameter specifying which service
        to call. While this documentation also shows POST/DELETE/PATCH/PUT for semantic clarity, all
        operations work identically via GET.

        ---

        ## 🔍 Authentication & Testing

        - `system/test/TemplServiceLogin` - Test API connectivity (multiplies input by 2)
        - `system/login/TemplServiceContent` - Login user and obtain session cookie
        - `system/logout/TemplServiceLogin` - Logout user and destroy session

        ---

        ## 📄 Content Management (Universal)

        These endpoints work with any content type by specifying the module name:

        - `system/add/TemplServiceContent` - Create new content (events, posts, groups, etc.)
        - `system/delete/TemplServiceContent` - Delete content
        - `system/delete_file/TemplServiceContent` - Delete file attachment
        - `system/get_data_api/TemplCmtsServices` - Get comments for content
        - `system/get_info/TemplServiceContent` - Get content info (profiles, accounts, posts, events, groups, polls)
        - `system/get_link/TemplServiceContent` - Get content permalink URL
        - `system/replace_file/TemplServiceContent` - Replace file with URL (pictures, covers, attachments)
        - `system/update/TemplServiceContent` - Update existing content

        **Example**: Get profile info → `params=["bx_persons", 43]`
        **Example**: Get event info → `params=["bx_events", 1]`
        **Example**: Add event → `params=["bx_events", {"event_name": "New Event"}]`
        **Example**: Update post → `params=["bx_posts", 67, {"text": "Updated"}]`
        **Example**: Delete content → `params=["bx_events", 5]`

        ---

        ## 👤 Profile Management

        - Get profile info: `system/get_info/TemplServiceContent` with `params=["bx_persons", profile_id]`
        - Get account info: `system/get_info/TemplServiceContent` with `params=["sys_account", account_id]`

        ---

        ## 📅 Events Module (bx_events)

        - `bx_events/browse_context/Module` - Browse events for a specific group/context
        - `bx_events/browse_past_profiles/Module` - Browse past events (date_end < now)
        - `bx_events/calendar_data/Module` - Get calendar data for date range
        - `bx_events/check_in/Module` - Check in to an event
        - `bx_events/entity_add/Module` - Create a new event
        - `bx_events/entity_delete/Module` - Delete an event
        - `bx_events/entity_edit/Module` - Update an existing event
        - `bx_events/get_info_api/Module` - Get event details by ID

        **Advanced**: Supports `condition` parameter for custom SQL filtering

        ---

        ## 📝 Posts Module (bx_posts)

        - `bx_posts/browse_public/Module` - Browse public posts with pagination
        - `bx_posts/browse_favorite/Module` - Browse a user's favorited posts
        - `bx_posts/get_info_api/Module` - Get post details in API format

        ---

        ## 📰 Timeline Module (bx_timeline)

        - `bx_timeline/delete/Module` - Delete timeline event
        - `bx_timeline/get/Module` - Browse timeline items with filtering
        - `bx_timeline/get_posts/Module` - Get timeline posts for user/group
        - `bx_timeline/repost/Module` - Repost timeline event to your timeline

        ---

        ## 👥 Groups Module (bx_groups)

        - `bx_groups/browse_joined_entries/Module` - Browse groups a user has joined
        - `bx_groups/browse_recent_profiles/Module` - Browse recently created groups
        - `bx_groups/browse_top_profiles/Module` - Browse top/popular groups
        - `bx_groups/entity_delete/Module` - Delete a group
        - `bx_groups/get_info_api/Module` - Get group details by ID
        - `bx_groups/is_fan/Module` - Check if a user is a member of a group
        - `system/browse_members/TemplServiceProfiles` - Browse all members of a group (paginated)

        ---

        ## 🔔 Notifications Module (bx_notifications)

        - `bx_notifications/get_unread_notifications_num/Module` - Get unread count (simple)
        - `bx_notifications/get_unread_notifications_num_ex/Module` - Get unread count (extended)
        - `bx_notifications/get_block_view/Module` - Get notifications with filtering
        - `bx_notifications/mark_as_read/Module` - Mark all notifications as read

        **Note**: Some endpoints may return HTTP 500 if user lacks permissions

        ---

        ## 📊 Polls Module (bx_polls)

        - `bx_polls/get_info_api/Module` - Get poll details by ID
        - `bx_polls/browse/Module` - Browse polls with filtering
        - `bx_polls/get_block_results/Module` - Get poll voting results
        - `bx_polls/get_block_subentries/Module` - Get poll questions and answers

        **Note**: Some endpoints may return HTTP 500 if user lacks permissions
      parameters:
        - name: r
          in: query
          required: true
          description: |
            Service route in format: `module/method/ServiceClass`

            Routes are organized by module for easy navigation. See description above for
            detailed information about each endpoint.
          schema:
            type: string
            enum:
              # Authentication & Testing
              - system/test/TemplServiceLogin
              - system/login/TemplServiceContent
              - system/logout/TemplServiceLogin

              # Content Management (Universal)
              - system/add/TemplServiceContent
              - system/delete/TemplServiceContent
              - system/delete_file/TemplServiceContent
              - system/get_data_api/TemplCmtsServices
              - system/get_info/TemplServiceContent
              - system/get_link/TemplServiceContent
              - system/replace_file/TemplServiceContent
              - system/update/TemplServiceContent

              # Events Module (bx_events)
              - bx_events/browse_context/Module
              - bx_events/browse_past_profiles/Module
              - bx_events/calendar_data/Module
              - bx_events/check_in/Module
              - bx_events/entity_add/Module
              - bx_events/entity_delete/Module
              - bx_events/entity_edit/Module
              - bx_events/get_info_api/Module

              # Groups Module (bx_groups)
              - bx_groups/browse_joined_entries/Module
              - bx_groups/browse_recent_profiles/Module
              - bx_groups/browse_top_profiles/Module
              - bx_groups/entity_delete/Module
              - bx_groups/get_info_api/Module
              - bx_groups/is_fan/Module
              - system/browse_members/TemplServiceProfiles

              # Notifications Module (bx_notifications)
              - bx_notifications/get_block_view/Module
              - bx_notifications/get_unread_notifications_num/Module
              - bx_notifications/get_unread_notifications_num_ex/Module
              - bx_notifications/mark_as_read/Module

              # Polls Module (bx_polls)
              - bx_polls/browse/Module
              - bx_polls/get_block_results/Module
              - bx_polls/get_block_subentries/Module
              - bx_polls/get_info_api/Module

              # Posts Module (bx_posts)
              - bx_posts/browse_favorite/Module
              - bx_posts/browse_public/Module
              - bx_posts/get_info_api/Module

              # Timeline Module (bx_timeline)
              - bx_timeline/delete/Module
              - bx_timeline/get/Module
              - bx_timeline/get_posts/Module
              - bx_timeline/repost/Module
          example: system/test/TemplServiceLogin
        - name: params
          in: query
          required: false
          description: |
            Parameters for the service method. Can be passed in two formats:

            **Format 1: JSON Array (URL-encoded)** - Recommended for complex data
            ```
            params=%5B%22bx_persons%22%2C43%5D
            ```
            Decoded: `["bx_persons", 43]`

            **Format 2: Array Style** - Simple for basic parameters
            ```
            params[]=bx_persons&params[]=43
            ```

            **Common Examples**:
            - Test method: `[5]` (returns 10)
            - Get profile: `["bx_persons", 43]`
            - Get event: `[1]`
            - Browse with pagination: `[0, 10]` (start=0, per_page=10)
            - Update content: `["bx_persons", 43, {"description": "New bio"}]`

            **Advanced - Condition Parameter**:
            ```json
            [495, {"condition": {"restriction": {"value": "UNIX_TIMESTAMP()", "field": "date_end", "operator": "<", "table": "bx_events_data"}}}]
            ```
          schema:
            type: string
          examples:
            simple:
              summary: Simple parameter (test method)
              value: "[5]"
            get_content:
              summary: Get content by ID
              value: '["bx_persons", 43]'
            browse:
              summary: Browse with pagination
              value: '["recent", 0, 10]'
            update:
              summary: Update content
              value: '["bx_persons", 43, {"description": "Updated bio"}]'
            condition:
              summary: Browse with condition filter
              value: '[495, {"condition": {"restriction": {"value": "UNIX_TIMESTAMP()", "field": "date_end", "operator": "<", "table": "bx_events_data"}}}]'
        - name: profile_id
          in: query
          required: false
          description: |
            Group/context profile ID for browse_context operations.

            **Used by**: `bx_events/browse_context/Module`

            **Note**: In the database, group associations are stored as negative values
            (e.g., -4 for group 4), but the API accepts positive values.
          schema:
            type: integer
          example: 4
      responses:
        '200':
          description: |
            **Success** - Request completed successfully

            The response structure is consistent across all endpoints, with the `data` field
            containing endpoint-specific information.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
              examples:
                test_method:
                  summary: Test method response
                  value:
                    status: 200
                    module: "system"
                    method: "test"
                    params: [5]
                    data: 10
                    hash: "abc123def456"
                profile_info:
                  summary: Get profile info response
                  value:
                    status: 200
                    module: "system"
                    method: "get_info"
                    params: ["bx_persons", 43]
                    data:
                      id: 43
                      title: "John Doe"
                      description: "Software developer and educator"
                      author: 495
                      added: 1704067200
                      status: "active"
                    hash: "abc123def456"
                event_info:
                  summary: Get event info response
                  value:
                    status: 200
                    module: "bx_events"
                    method: "get_info_api"
                    params: [1]
                    data:
                      id: 1
                      event_name: "Annual Science Fair"
                      event_desc: "Join us for our annual science fair..."
                      date_start: 1704067200
                      date_end: 1704153600
                      location: "Main Auditorium"
                      author: 495
                      status: "active"
                    hash: "abc123def456"
                browse_posts:
                  summary: Browse posts response
                  value:
                    status: 200
                    module: "bx_posts"
                    method: "browse_public"
                    params: [{"start": 0, "per_page": 5}]
                    data:
                      - id: 67
                        title: "Welcome to our community!"
                        text: "We're excited to have you here..."
                        author: 495
                        added: 1704067200
                      - id: 68
                        title: "Important announcement"
                        text: "Please note the following changes..."
                        author: 43
                        added: 1704153600
                    hash: "abc123def456"
        '403':
          description: |
            **Access Denied** - Authentication failed or insufficient permissions

            **Common Causes**:
            - Invalid or expired Bearer token
            - Missing session cookie
            - User doesn't have permission to access this resource

            **Solution**: Verify your Bearer token and session cookie are valid and current.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: 403
                error: "Access denied"
        '404':
          description: |
            **Not Found** - Service or resource doesn't exist

            **Common Causes**:
            - Invalid `r` parameter (service route)
            - Service not marked as "safe" in module configuration
            - Resource ID doesn't exist

            **Solution**: Verify the service route is correct and the service is publicly accessible.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: 404
                error: "Service not found"
        '500':
          description: |
            **Internal Server Error** - Server-side error or permission denied

            **Common Causes**:
            - User lacks specific permissions for this operation
            - Database error
            - Invalid parameters causing PHP error

            **Note**: Some endpoints (notifications, polls) may return 500 for permission issues
            instead of 403. This is expected behavior and should be handled gracefully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: 500
                error: "Permission denied"
      x-test-files:
        # Authentication & Testing (1 test)
        - tests/auth/test_method.sh

        # Content Management (3 tests)
        - tests/content/test_get_info.sh
        - tests/content/test_get_link.sh
        - tests/content/test_get_post_comments.sh

        # Events Module (5 tests for GET operations)
        - tests/modules/events/test_browse_events_by_group.sh
        - tests/modules/events/test_browse_past_events.sh
        - tests/modules/events/test_browse_past_events_by_group.sh
        - tests/modules/events/test_calendar_data.sh
        - tests/modules/events/test_get_event_by_id.sh

        # Groups Module (3 tests for GET operations)
        - tests/modules/groups/test_browse_groups.sh
        - tests/modules/groups/test_browse_top_groups.sh
        - tests/modules/groups/test_get_group.sh

        # Notifications Module (4 tests)
        - tests/modules/notifications/test_get_notifications.sh
        - tests/modules/notifications/test_get_unread_count.sh
        - tests/modules/notifications/test_get_unread_count_extended.sh
        - tests/modules/notifications/test_mark_as_read.sh

        # Polls Module (4 tests)
        - tests/modules/polls/test_browse_polls.sh
        - tests/modules/polls/test_get_poll.sh
        - tests/modules/polls/test_get_poll_questions.sh
        - tests/modules/polls/test_get_poll_results.sh

        # Posts Module (3 tests for GET operations)
        - tests/modules/posts/test_browse_posts.sh
        - tests/modules/posts/test_get_post.sh
        - tests/modules/posts/test_get_post_info_api.sh

        # Timeline Module (2 tests for GET operations)
        - tests/modules/timeline/test_get_timeline_items.sh
        - tests/modules/timeline/test_get_timeline_posts.sh

        # Profile Management (2 tests)
        - tests/profiles/test_get_account_info.sh
        - tests/profiles/test_get_profile_info.sh
      x-code-samples:
        - lang: curl
          name: Test method
          source: |
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=system/test/TemplServiceLogin&params=[5]"
        - lang: curl
          name: Get event by ID
          source: |
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_events/get_info_api/Module&params[]=1"
        - lang: curl
          name: Browse events for group
          source: |
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_events/browse_context/Module&profile_id=194"
        - lang: curl
          name: Browse past events for group (with condition parameter)
          source: |
            CURRENT_TIME=$(date +%s)
            PARAMS='[{"condition":{"restriction":{"past_events":{"value":'${CURRENT_TIME}',"field":"date_end","operator":"<","table":"bx_events_data"}}}}]'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_events/browse_context/Module&profile_id=194&params=${ENCODED}"
        - lang: curl
          name: Get post comments
          source: |
            PARAMS='{"module":"bx_posts","object_id":67}'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=system/get_data_api/TemplCmtsServices&params=${ENCODED}"
        - lang: curl
          name: Get profile info
          source: |
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=system/get_info/TemplServiceContent&params[]=bx_persons&params[]=43"
        - lang: curl
          name: Get account info
          source: |
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=system/get_info/TemplServiceContent&params[]=sys_account&params[]=7"
        - lang: curl
          name: Browse public posts
          source: |
            PARAMS='{"start":0,"per_page":5}'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_posts/browse_public/Module&params=${ENCODED}"
        - lang: curl
          name: Browse favorite posts
          source: |
            # Get favorited posts for profile ID 43
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_posts/browse_favorite/Module&params[]=43"
        - lang: curl
          name: Get post info (API format)
          source: |
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_posts/get_info_api/Module&params[]=10"
        - lang: curl
          name: Get timeline posts
          source: |
            PARAMS='{"params":{"start":0,"per_page":5}}'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_timeline/get_posts/Module&params=${ENCODED}"
        - lang: curl
          name: Browse timeline items
          source: |
            PARAMS='{"start":0,"per_page":5}'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_timeline/get/Module&params=${ENCODED}"
        - lang: curl
          name: Get group by ID
          source: |
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_groups/get_info_api/Module&params=[4]"
        - lang: curl
          name: Browse recent groups
          source: |
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_groups/browse_recent_profiles/Module"
        - lang: curl
          name: Browse top groups
          source: |
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_groups/browse_top_profiles/Module"
        - lang: curl
          name: Browse joined groups
          source: |
            # Get groups that profile 51 has joined
            PARAMS='[51]'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)

            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_groups/browse_joined_entries/Module&params=${ENCODED}"
        - lang: curl
          name: Check group membership (is_fan)
          source: |
            # Check if profile 51 is a member of group 495
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_groups/is_fan/Module&params=[495,51]"

            # Returns: {"status":200,"data":1} if member, {"status":200,"data":0} if not
        - lang: curl
          name: Browse group members (paginated)
          source: |
            # Get first page (default 10 members)
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=system/browse_members/TemplServiceProfiles&params=[495,%22bx_groups_fans%22]"

            # Get with custom pagination (5 members per page, starting at 0)
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=system/browse_members/TemplServiceProfiles&params=[495,%22bx_groups_fans%22]&start=0&per_page=5"
        - lang: curl
          name: Get unread notifications count
          source: |
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_notifications/get_unread_notifications_num/Module"
        - lang: curl
          name: Get unread notifications count (extended)
          source: |
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_notifications/get_unread_notifications_num_ex/Module"
        - lang: curl
          name: Get notifications
          source: |
            PARAMS='["owner_and_connections",495,0,10,[]]'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_notifications/get_block_view/Module&params=${ENCODED}"
        - lang: curl
          name: Mark notifications as read
          source: |
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_notifications/mark_as_read/Module"
        - lang: curl
          name: Get poll by ID
          source: |
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_polls/get_info_api/Module&params=[2]"
        - lang: curl
          name: Browse polls
          source: |
            PARAMS='["recent",0,10]'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_polls/browse/Module&params=${ENCODED}"
        - lang: curl
          name: Get poll results
          source: |
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_polls/get_block_results/Module&params=[2]"
        - lang: curl
          name: Get poll questions
          source: |
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_polls/get_block_subentries/Module&params=[2]"

    post:
      tags:
        - Authentication
        - Content Management
        - Events
        - Posts
        - Timeline
        - Groups
      operationId: performAction
      summary: Perform actions (POST operations for creating and modifying data)
      description: |
        **POST operations for authentication, content creation, and data modification.**

        POST requests use the same endpoint structure as GET requests but are used for
        operations that create or modify data.

        ---

        ## 🔐 Authentication

        - `system/login/TemplServiceContent` - Login user and obtain session cookie

        **Example**: `params[]=495` (login as user ID 495)

        ---

        ## 📄 Content Management

        - `system/add/TemplServiceContent` - Create new content (events, posts, groups, etc.)
        - `system/update/TemplServiceContent` - Update existing content

        **Example - Add Event**: `params=["bx_events", {"event_name": "New Event", "date_start": 1704067200}]`
        **Example - Update Post**: `params=["bx_posts", 67, {"text": "Updated content"}]`

        ---

        ## 📅 Events Module

        - `bx_events/check_in/Module` - Check in to an event

        **Example**: `params[]=1` (check in to event ID 1)

        ---

        ## 📰 Timeline Module

        - `bx_timeline/delete/Module` - Delete timeline event
        - `bx_timeline/repost/Module` - Repost timeline event to your timeline

        ---

        ## 👥 Groups Module

        - `bx_groups/entity_delete/Module` - Delete a group

        **Example**: `params[]=4` (delete group ID 4)
      parameters:
        - name: r
          in: query
          required: true
          description: |
            Service route in format: `module/method/ServiceClass`

            See description above for available POST operations.
          schema:
            type: string
            enum:
              # Authentication
              - system/login/TemplServiceContent

              # Content Management
              - system/add/TemplServiceContent
              - system/update/TemplServiceContent

              # Events Module
              - bx_events/check_in/Module

              # Groups Module
              - bx_groups/entity_delete/Module

              # Timeline Module
              - bx_timeline/delete/Module
              - bx_timeline/repost/Module
          example: system/login/TemplServiceContent
        - name: params
          in: query
          required: true
          description: |
            Parameters for the service method.

            **Common Examples**:
            - Login: `params[]=495` (user ID)
            - Add content: `params=["bx_events", {"event_name": "New Event"}]`
            - Update content: `params=["bx_posts", 67, {"text": "Updated"}]`
            - Check in: `params[]=1` (event ID)
            - Delete: `params[]=4` (resource ID)
          schema:
            type: string
          examples:
            login:
              summary: Login user
              value: "params[]=495"
            add_event:
              summary: Add new event
              value: '["bx_events", {"event_name": "Annual Science Fair", "date_start": 1704067200, "date_end": 1704153600}]'
            update_post:
              summary: Update post
              value: '["bx_posts", 67, {"text": "Updated post content"}]'
            check_in:
              summary: Check in to event
              value: "params[]=1"
      responses:
        '200':
          description: |
            **Success** - Action completed successfully

            For login operations, the `data` field contains session information including
            the `memberSession` cookie value.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
              examples:
                login_success:
                  summary: Login response
                  value:
                    status: 200
                    module: "system"
                    method: "login"
                    params: [495]
                    data:
                      account_id: 12
                      profile_id: 495
                      content_id: 12
                      content_module: "bx_persons"
                      session: "ss.yJvh..."
                    hash: "abc123def456"
                add_content:
                  summary: Add content response
                  value:
                    status: 200
                    module: "system"
                    method: "add"
                    params: ["bx_events", {"event_name": "New Event"}]
                    data: 142
                    hash: "abc123def456"
                check_in:
                  summary: Check in response
                  value:
                    status: 200
                    module: "bx_events"
                    method: "check_in"
                    params: [1]
                    data: true
                    hash: "abc123def456"
        '400':
          description: |
            **Bad Request** - Missing or invalid parameters

            **Common Causes**:
            - Required parameters missing
            - Invalid parameter format
            - Invalid data types
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: 400
                error: "Missing required parameter"
        '403':
          description: |
            **Access Denied** - Authentication failed or insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: 403
                error: "Access denied"
        '404':
          description: |
            **Not Found** - Resource or service not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: 404
                error: "Resource not found"
        '500':
          description: |
            **Internal Server Error** - Server-side error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: 500
                error: "Internal server error"
      x-test-files:
        # Authentication (1 test)
        - tests/auth/test_login.sh

        # Content Management (1 test for POST)
        - tests/content/test_add_content.sh

        # Events Module (1 test for POST)
        - tests/modules/events/test_check_in_event.sh

        # Groups Module (3 tests for POST/DELETE)
        - tests/modules/groups/test_create_group.sh
        - tests/modules/groups/test_delete_group.sh
        - tests/modules/groups/test_update_group.sh

        # Posts Module (1 test for POST)
        - tests/modules/posts/test_update_post.sh

        # Timeline Module (2 tests for POST)
        - tests/modules/timeline/test_delete_timeline_event.sh
        - tests/modules/timeline/test_repost_timeline_event.sh
      x-code-samples:
        - lang: curl
          name: Login user
          source: |
            # No session cookie needed - only Bearer token required!
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              "http://community.local.k12.com/api.php?r=system/login/TemplServiceContent&params[]=12"
        - lang: curl
          name: Check in to event
          source: |
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_events/check_in/Module&params[]=5"
        - lang: curl
          name: Update post title
          source: |
            PARAMS='["bx_posts",10,{"title":"Updated Title"}]'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=system/update/TemplServiceContent&params=${ENCODED}"
        - lang: curl
          name: Delete timeline event
          source: |
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_timeline/delete/Module&params[]=2008"
        - lang: curl
          name: Repost timeline event
          source: |
            PARAMS='[43,43,"bx_posts","added",10]'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_timeline/repost/Module&params=${ENCODED}"
        - lang: curl
          name: Create group
          source: |
            PARAMS='["bx_groups",{"group_name":"Test Group","group_desc":"Test description","group_cat":"1","k12_tag_color":"#00CED1","allow_view_to":"3","allow_post_to":"3"}]'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s \
              -X POST \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=system/add/TemplServiceContent&params=${ENCODED}"
        - lang: curl
          name: Update group
          source: |
            PARAMS='["bx_groups",4,{"group_desc":"Updated description"}]'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s \
              -X POST \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=system/update/TemplServiceContent&params=${ENCODED}"
        - lang: curl
          name: Delete group
          source: |
            curl -s \
              -X POST \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_groups/entity_delete/Module&params[]=999"

    delete:
      tags:
        - Authentication
        - Content Management
        - Events
      operationId: removeResource
      summary: Remove resources (DELETE operations for logout and content deletion)
      description: |
        **DELETE operations for destroying sessions and deleting resources.**

        DELETE requests are used for operations that permanently remove data or end sessions.

        ---

        ## 🔐 Authentication

        - `system/logout/TemplServiceLogin` - Logout user and destroy session

        **Note**: After logout, the session cookie becomes invalid.

        ---

        ## 📄 Content Management

        - `system/delete/TemplServiceContent` - Delete content (events, posts, groups, etc.)
        - `system/delete_file/TemplServiceContent` - Delete file attachment

        **Example - Delete Event**: `params=["bx_events", 5]`
        **Example - Delete File**: `params=["bx_persons_pictures", 123]`

        ---

        ## 📅 Events Module

        - `bx_events/entity_delete/Module` - Delete an event

        **Example**: `params=[5]` (delete event ID 5)
      parameters:
        - name: r
          in: query
          required: true
          description: |
            Service route in format: `module/method/ServiceClass`

            See description above for available DELETE operations.
          schema:
            type: string
            enum:
              # Authentication
              - system/logout/TemplServiceLogin

              # Content Management
              - system/delete/TemplServiceContent
              - system/delete_file/TemplServiceContent

              # Events Module
              - bx_events/entity_delete/Module
          example: system/logout/TemplServiceLogin
        - name: params
          in: query
          required: false
          description: |
            Parameters for the delete operation.

            **Common Examples**:
            - Logout: No params needed
            - Delete content: `["bx_events", 5]` (module, ID)
            - Delete file: `["bx_persons_pictures", 123]` (storage object, file ID)
            - Delete event: `[5]` (event ID)
          schema:
            type: string
          examples:
            delete_content:
              summary: Delete content
              value: '["bx_events", 5]'
            delete_file:
              summary: Delete file
              value: '["bx_persons_pictures", 123]'
            delete_event:
              summary: Delete event
              value: '[5]'
      responses:
        '200':
          description: |
            **Success** - Resource deleted successfully

            For logout operations, the session is destroyed and the cookie becomes invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
              examples:
                logout:
                  summary: Logout response
                  value:
                    status: 200
                    module: "system"
                    method: "logout"
                    params: []
                    data: true
                    hash: "abc123def456"
                delete_content:
                  summary: Delete content response
                  value:
                    status: 200
                    module: "system"
                    method: "delete"
                    params: ["bx_events", 5]
                    data: true
                    hash: "abc123def456"
        '400':
          description: |
            **Bad Request** - Missing or invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: 400
                error: "Missing required parameter"
        '403':
          description: |
            **Access Denied** - Authentication failed or insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: 403
                error: "Access denied"
        '404':
          description: |
            **Not Found** - Resource doesn't exist
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: 404
                error: "Resource not found"
      x-test-files:
        # Authentication (1 test)
        - tests/auth/test_logout.sh

        # Content Management (2 tests for DELETE)
        - tests/content/test_delete_content.sh
        - tests/content/test_delete_file.sh

        # Events Module (1 test for DELETE)
        - tests/modules/events/test_delete_event.sh
      x-code-samples:
        - lang: curl
          name: Logout user
          source: |
            curl -s -X DELETE \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=system/logout/TemplServiceLogin"
        - lang: curl
          name: Delete event
          source: |
            PARAMS='[5]'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s -X DELETE \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_events/entity_delete/Module&params=${ENCODED}"



    put:
      tags:
        - Content Management
        - Events
      operationId: createResource
      summary: Create new resources (content, events)
      description: |
        PUT operations for creating new resources.
        Use the `r` parameter to specify which operation to perform.

        **Supported Operations**:
        - `system/add/TemplServiceContent` - Create new content
        - `bx_events/entity_add/Module` - Create a new event
      parameters:
        - name: r
          in: query
          required: true
          description: Service route (module/method/ServiceClass)
          schema:
            type: string
            enum:
              - system/add/TemplServiceContent
              - bx_events/entity_add/Module
          example: system/add/TemplServiceContent
        - name: params
          in: query
          required: true
          description: JSON array with module name and resource data
          schema:
            type: string
          example: '["bx_events",{"event_name":"New Event","event_cat":"1"}]'
      responses:
        '200':
          description: Success - resource created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: Bad request - missing or invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Access denied - user lacks creation permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      x-test-files:
        - tests/content/test_add_content.sh
        - tests/modules/events/test_create_event.sh
      x-code-samples:
        - lang: curl
          name: Create event
          source: |
            PARAMS='["bx_events",{"event_name":"New Event","event_cat":"1","event_desc":"Description","date_start":1738425600,"date_end":1738439200,"timezone":"UTC","location":"Online","allow_view_to":"3","allow_post_to":"3"}]'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s -X PUT \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=system/add/TemplServiceContent&params=${ENCODED}"

    patch:
      tags:
        - Content Management
        - Events
        - Profile Management
      operationId: modifyResource
      summary: Modify existing resources (PATCH operations for partial updates)
      description: |
        **PATCH operations for updating existing resources.**

        PATCH requests are used for partial updates to existing content. Only the fields
        specified in the request are modified; other fields remain unchanged.

        ---

        ## 📄 Content Management

        - `system/update/TemplServiceContent` - Update content (profiles, accounts, posts, events, groups)
        - `system/replace_file/TemplServiceContent` - Replace file with URL (pictures, covers, attachments)

        **Example - Update Profile**: `params=["bx_persons", 43, {"description": "Updated bio"}]`
        **Example - Update Event**: `params=["bx_events", 5, {"event_name": "New Name"}]`
        **Example - Replace Picture**: `params=["bx_persons", 43, "picture", "https://example.com/pic.jpg"]`

        ---

        ## 👤 Profile Management

        **Update Profile Description**:
        ```json
        ["bx_persons", 43, {"description": "Software developer and educator"}]
        ```

        **Update Account Email**:
        ```json
        ["sys_account", 7, {"email": "newemail@example.com"}]
        ```

        **Replace Profile Picture** (URL only):
        ```json
        ["bx_persons", 43, "picture", "https://example.com/image.jpg"]
        ```

        **Replace Profile Cover** (URL only):
        ```json
        ["bx_persons", 43, "cover", "https://example.com/cover.jpg"]
        ```

        ---

        ## 📅 Events Module

        - `bx_events/entity_edit/Module` - Update an existing event

        **Example**: `params=[5, {"event_name": "Updated Event Name", "location": "New Location"}]`
      parameters:
        - name: r
          in: query
          required: true
          description: |
            Service route in format: `module/method/ServiceClass`

            See description above for available PATCH operations.
          schema:
            type: string
            enum:
              # Content Management
              - system/replace_file/TemplServiceContent
              - system/update/TemplServiceContent

              # Events Module
              - bx_events/entity_edit/Module
          example: system/update/TemplServiceContent
        - name: params
          in: query
          required: true
          description: |
            Parameters for the update operation.

            **Format for update**: `[module, id, {fields}]` or `[id, {fields}]`
            **Format for replace_file**: `[module, id, field_name, url]`

            **Common Examples**:
            - Update profile: `["bx_persons", 43, {"description": "New bio"}]`
            - Update event: `[5, {"event_name": "Updated Name"}]`
            - Replace picture: `["bx_persons", 43, "picture", "https://example.com/pic.jpg"]`
          schema:
            type: string
          examples:
            update_profile:
              summary: Update profile description
              value: '["bx_persons", 43, {"description": "Updated bio"}]'
            update_account:
              summary: Update account email
              value: '["sys_account", 7, {"email": "new@example.com"}]'
            update_event:
              summary: Update event
              value: '[5, {"event_name": "Updated Event Name"}]'
            replace_picture:
              summary: Replace profile picture
              value: '["bx_persons", 43, "picture", "https://example.com/image.jpg"]'
            replace_cover:
              summary: Replace profile cover
              value: '["bx_persons", 43, "cover", "https://example.com/cover.jpg"]'
      responses:
        '200':
          description: |
            **Success** - Resource updated successfully

            The `data` field typically contains the updated resource ID or boolean true.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
              examples:
                update_profile:
                  summary: Update profile response
                  value:
                    status: 200
                    module: "system"
                    method: "update"
                    params: ["bx_persons", 43, {"description": "Updated bio"}]
                    data: 43
                    hash: "abc123def456"
                update_event:
                  summary: Update event response
                  value:
                    status: 200
                    module: "bx_events"
                    method: "entity_edit"
                    params: [5, {"event_name": "Updated Name"}]
                    data: true
                    hash: "abc123def456"
                replace_file:
                  summary: Replace file response
                  value:
                    status: 200
                    module: "system"
                    method: "replace_file"
                    params: ["bx_persons", 43, "picture", "https://example.com/pic.jpg"]
                    data: true
                    hash: "abc123def456"
        '400':
          description: |
            **Bad Request** - Missing or invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: 400
                error: "Missing required parameter"
        '403':
          description: |
            **Access Denied** - User is not the resource author or lacks permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: |
            **Not Found** - Resource doesn't exist
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: 404
                error: "Resource not found"
      x-test-files:
        # Content Management (2 tests for PATCH)
        - tests/content/test_replace_file.sh
        - tests/content/test_update_content.sh

        # Events Module (1 test for PATCH)
        - tests/modules/events/test_update_event.sh

        # Profile Management (4 tests for PATCH)
        - tests/profiles/test_replace_profile_cover.sh
        - tests/profiles/test_replace_profile_picture.sh
        - tests/profiles/test_update_account_email.sh
        - tests/profiles/test_update_profile_description.sh
      x-code-samples:
        - lang: curl
          name: Update event
          source: |
            PARAMS='[5,{"event_name":"Updated Event Name","location":"Updated Location"}]'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s -X PATCH \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=bx_events/entity_edit/Module&params=${ENCODED}"
        - lang: curl
          name: Update profile description
          source: |
            PARAMS='["bx_persons",43,{"description":"Updated profile description"}]'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s -X PATCH \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=system/update/TemplServiceContent&params=${ENCODED}"
        - lang: curl
          name: Update account email
          source: |
            PARAMS='["sys_account",7,{"email":"newemail@example.com"}]'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s -X PATCH \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=system/update/TemplServiceContent&params=${ENCODED}"
        - lang: curl
          name: Replace profile picture
          source: |
            PARAMS='["bx_persons",43,"picture","https://lipsum.app/150"]'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s -X PATCH \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=system/replace_file/TemplServiceContent&params=${ENCODED}"
        - lang: curl
          name: Replace profile cover
          source: |
            PARAMS='["bx_persons",43,"cover","https://lipsum.app/1200x400"]'
            ENCODED=$(echo -n "$PARAMS" | jq -sRr @uri)
            curl -s -X PATCH \
              -H "Authorization: Bearer YOUR_API_KEY" \
              --cookie "memberSession=YOUR_SESSION_COOKIE" \
              "http://community.local.k12.com/api.php?r=system/replace_file/TemplServiceContent&params=${ENCODED}"

tags:
  - name: Authentication
    description: |
      **Login, logout, and session management**

      Endpoints for authenticating users and managing sessions. All other API operations require
      valid authentication credentials obtained through these endpoints.

      **Key Operations**:
      - Test API connectivity
      - Login users and obtain session cookies
      - Logout and destroy sessions

  - name: Content Management
    description: |
      **Universal CRUD operations for all content types**

      Generic content management endpoints that work across all UNA modules (profiles, posts, events,
      groups, etc.). These endpoints provide a unified interface for creating, reading, updating, and
      deleting content.

      **Supported Content Types**: `bx_persons`, `sys_account`, `bx_posts`, `bx_events`, `bx_groups`, `bx_polls`

      **Key Operations**:
      - Get content information
      - Get content links
      - Add new content
      - Update existing content
      - Delete content
      - Replace/delete files (pictures, covers, attachments)

  - name: Profile Management
    description: |
      **User profile and account operations**

      Endpoints for managing user profiles (`bx_persons`) and accounts (`sys_account`). Profiles contain
      public information like name, bio, and pictures, while accounts contain private information like
      email and settings.

      **Key Operations**:
      - Get profile information
      - Get account information
      - Update profile descriptions
      - Update account email
      - Replace profile pictures and covers

  - name: Events
    description: |
      **Events module endpoints (bx_events)**

      Comprehensive event management including creation, browsing, calendar integration, and check-ins.
      Supports advanced filtering with condition parameters and group-specific event browsing.

      **Key Operations**:
      - Get event details by ID
      - Browse events (public, by group, past events)
      - Get calendar data for date range
      - Create, update, delete events
      - Check in to events
      - Advanced filtering with condition parameter

  - name: Posts
    description: |
      **Posts module endpoints (bx_posts)**

      Social media-style posts with support for text, images, and comments. Posts can be public or
      restricted to specific groups/connections.

      **Key Operations**:
      - Browse public posts
      - Get post details
      - Get post information in API format
      - Update posts
      - Get post comments

  - name: Timeline
    description: |
      **Timeline module endpoints (bx_timeline)**

      Activity feed showing posts, events, and other content from users and groups. Supports filtering,
      pagination, and reposting functionality.

      **Key Operations**:
      - Get timeline posts
      - Browse timeline items
      - Delete timeline events
      - Repost timeline events

  - name: Groups
    description: |
      **Groups module endpoints (bx_groups)**

      Community groups and organizations with membership management. Groups can host events, posts,
      and other content.

      **Key Operations**:
      - Get group details by ID
      - Browse groups (recent, top, featured)
      - Create, update, delete groups
      - Manage group membership

  - name: Notifications
    description: |
      **Notifications module endpoints (bx_notifications)**

      User notification system for activity alerts, mentions, and system messages. Supports filtering
      by type and module.

      **Key Operations**:
      - Get unread notification count
      - Get unread notification count (extended with metadata)
      - Get notifications with filtering
      - Mark notifications as read

      **Note**: Some endpoints may return HTTP 500 if user lacks appropriate permissions.

  - name: Polls
    description: |
      **Polls module endpoints (bx_polls)**

      Polling and survey functionality with multiple choice questions, voting, and results visualization.

      **Key Operations**:
      - Get poll details by ID
      - Browse polls (recent, popular, featured)
      - Get poll results with vote counts
      - Get poll questions and answer options

      **Note**: Some endpoints may return HTTP 500 if user lacks appropriate permissions.

