> ## Documentation Index
> Fetch the complete documentation index at: https://attend.hackclub.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Comment on an incident

> Adds a comment to the incident's timeline, for anyone who can see the incident. A `new_status` sent with the comment is applied only when the caller may update the incident; from a reporter who holds none of its roles it is silently dropped and the comment is still saved. If the incident was posted to Slack, the comment is posted to its thread.



## OpenAPI

````yaml /openapi.yml post /events/{event_id}/incidents/{incident_id}/comments
openapi: 3.0.3
info:
  title: Attend API
  version: v1
  description: >
    REST API for [Attend](https://attend.hackclub.com), Hack Club's event

    management platform. The API is used by the Attend mobile app and by

    trusted server-to-server integrations.


    ## Authentication


    Almost every endpoint requires a bearer token:


    ```

    Authorization: Bearer <token>

    ```


    Four kinds of token are accepted:


    - **Mobile token** — issued to a signed-in user by `POST /session`. Sets the
      current user. May return the response header
      `X-Token-Refresh-Recommended: true` when the token is nearing expiry;
      call `POST /session/refresh` to rotate it.
    - **Global API token** — a superadmin-issued token. Only honoured while its
      owner is still a global admin. Sets the current user. May be **scoped**
      when issued, in which case it reaches only the endpoints that accept
      that scope and returns `403` everywhere else, read-only endpoints
      included. An unscoped token carries its owner's full access. Scopes are
      noted on the endpoints that accept them: `bans:write` and
      `support:read`.
    - **Series API key** — one key for a whole event series, issued from
      **Series → API Keys** in the dashboard by a series owner. Does **not** set
      a current user. It acts as an event API key on *every* event in its
      series, and it is the only credential that can create an event. Scopes do
      not apply — a series key's reach is its series. See the **Series**
      section.
    - **Event API key** — per-event key (`EventApiToken`, or the legacy
      `Event#api_key`). Does **not** set a current user, so it only works on the
      subset of endpoints that don't require one (participant `lookup`,
      `roster`, `create`, `update` and `delete`, event setup, event staff, and
      the travel calendar).

    Missing or invalid credentials return `401 { "error": "Unauthorized" }`.


    ### What an API key cannot do


    Neither key kind sets a current user, so endpoints that must attribute work

    to a person stay closed to both — regardless of how broad the key is. A

    series key is wider in *reach* (more events), never in *depth*:


    | Endpoint | Series key | Event key |

    | --- | --- | --- |

    | `GET/POST /series/…` | ✅ its own series | ❌ `403` |

    | `POST /series/{id}/events` | ✅ its own series | ❌ `403` |

    | Participant `lookup`, `roster`, `create` | ✅ any event in the series | ✅
    its own event |

    | `PATCH`/`DELETE` a participant | ✅ any event in the series | ✅ its own
    event |

    | `/events/{id}/setup/…` and `/events/{id}/staff` | ✅ any event in the
    series | ✅ its own event |

    | `GET /events/{id}/travel` | ✅ any event in the series | ✅ its own event |

    | `GET /events/{id}/participants` (full payload) | ❌ `403` | ❌ `403` |

    | Notes, scans, scan contexts, Slack blasts, NFC badges | ❌ `403` | ❌ `403`
    |

    | `/events/{id}/messages/…` and `/events/{id}/incidents/…` | ❌ `403` | ❌
    `403` |

    | `GET /incident_reports/options` and `POST /incident_reports` | ❌ `403` | ❌
    `403` |

    | `GET /messages` and `GET /messages/{id}` (inbox) | ❌ `403` | ❌ `403` |


    Either key can be revoked without credentials by POSTing its own secret to

    `POST /tokens/revoke`; Attend emails the key's owner (or, if their account

    is gone, the series owners) when that happens.


    ## Conventions


    - All timestamps are ISO 8601 strings and may be `null` where noted.

    - Errors use the envelope `{ "error": "<message>" }`.

    - `:event_id` path segments accept a numeric id or the event slug on the
      participants, setup, and staff endpoints; other endpoints accept the
      numeric id only.
    - A caller that may *write* a field cannot always *read* it back: dates of
      birth, phone numbers, addresses and the details of the people around a
      participant are omitted (not nulled) for API keys and PII-restricted
      roles, in responses to writes just as in responses to reads.

    > **Note:** Inbound webhook receivers (Postmark, Help Scout, DocuSeal,

    > Slack events) also live under `/api/v1` but are called by third parties,

    > not by API consumers, and are not documented here.
servers:
  - url: https://attend.hackclub.com/api/v1
    description: Production
  - url: http://localhost:3000/api/v1
    description: Local development
security:
  - bearerAuth: []
tags:
  - name: Authentication
    description: Obtain, refresh, and revoke mobile bearer tokens.
  - name: Account
    description: The authenticated user's profile and accessible events.
  - name: Series
    description: >-
      Event series, and the events inside one, addressed with a single series
      API key. Creating an event lives here — an event has to belong to a
      series, and only a series key names one unambiguously.
  - name: Event Setup
    description: >-
      The tail of the setup wizard — waiver configuration and taking an event
      out of draft — for events created through the API.
  - name: Event Staff
    description: Who has access to an event, and what they can do there.
  - name: Participants
    description: Participant registrations for an event.
  - name: Notes
    description: Staff notes on a participant's registration.
  - name: Scans
    description: QR / NFC / manual scans and check-in.
  - name: Scan Contexts
    description: The scan stations configured for an event.
  - name: Stays
    description: >-
      An event's stays — during the event, the night before, the night after —
      and the roster of who's staying for each list-only stay. Built for a shop
      that sells the night: add buyers to the roster on purchase, remove them on
      refund. Accepts an event or series API key, or a global token scoped to
      `rooming:write`.
  - name: Travel Calendar
    description: Chronological participant travel and pickup operations.
  - name: Slack Blasts
    description: Broadcast Slack messages to an event's participants.
  - name: Messages
    description: >-
      Compose, preview, schedule and send an organizer broadcast over Slack,
      email, SMS and push, and follow its deliveries.
  - name: Incidents
    description: >-
      An event's incident log — logging, sharing, commenting on and escalating
      incidents to Hack Club HQ.
  - name: NFC Badges
    description: Provision and manage participant NFC badges.
  - name: Push Tokens
    description: Register device push-notification tokens.
  - name: Inbox
    description: The organizer messages delivered to the signed-in participant.
  - name: Incident Reports
    description: File a confidential incident report straight to Hack Club HQ.
  - name: Bans
    description: The app-wide ban list. Global admins only.
  - name: Travel
    description: >-
      Airport and flight lookups. These endpoints authenticate with the web
      session cookie (Devise), not a bearer token.
paths:
  /events/{event_id}/incidents/{incident_id}/comments:
    post:
      tags:
        - Incidents
      summary: Comment on an incident
      description: >-
        Adds a comment to the incident's timeline, for anyone who can see the
        incident. A `new_status` sent with the comment is applied only when the
        caller may update the incident; from a reporter who holds none of its
        roles it is silently dropped and the comment is still saved. If the
        incident was posted to Slack, the comment is posted to its thread.
      parameters:
        - $ref: '#/components/parameters/EventId'
        - name: incident_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: The incident id.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - comment
              properties:
                comment:
                  type: object
                  required:
                    - body
                  properties:
                    body:
                      type: string
                      example: Spoke to both attendees.
                    new_status:
                      allOf:
                        - $ref: '#/components/schemas/IncidentStatus'
                      description: >-
                        Optional. Changes the incident's status along with the
                        comment.
      responses:
        '201':
          description: Comment added.
          content:
            application/json:
              schema:
                type: object
                properties:
                  comment:
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
                      body:
                        type: string
                      new_status:
                        allOf:
                          - $ref: '#/components/schemas/IncidentStatus'
                        nullable: true
                      created_at:
                        type: string
                        format: date-time
                  incident_status:
                    allOf:
                      - $ref: '#/components/schemas/IncidentStatus'
                    description: The incident's status after the comment.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/IncidentsForbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          description: >-
            A blank body, or an unknown `new_status` (refused before anything is
            written; that error carries no `errors` array).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
components:
  parameters:
    EventId:
      name: event_id
      in: path
      required: true
      schema:
        type: string
      description: Event id or slug.
  schemas:
    IncidentStatus:
      type: string
      enum:
        - open
        - in_review
        - closed
    ValidationError:
      type: object
      properties:
        error:
          type: string
          example: Category can't be blank
        errors:
          type: array
          items:
            type: string
          example:
            - Category can't be blank
    Error:
      type: object
      properties:
        error:
          type: string
          example: Unauthorized
  responses:
    Unauthorized:
      description: Missing or invalid credentials.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    IncidentsForbidden:
      description: >-
        The caller's roles on this event don't allow this (see the operation's
        description), or the caller is an API key (`API key is not authorized
        for incidents`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: Event or record not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Mobile token, global API token, series API key, or event API key. See
        Authentication above for which endpoints each one reaches.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.