openapi: 3.1.0
info:
  title: AfterCheck API
  version: 0.1.0
  summary: Pre-release documentation for the implemented AfterCheck API v0.1 endpoints.
  description: |
    AfterCheck API v0.1 gives server-side systems a small feedback-first
    integration surface: list campaigns, create tracked feedback requests, and
    read organization-scoped responses.

    This OpenAPI file documents only endpoints currently implemented in the
    AfterCheck repository. It is the source of truth for the Scalar-rendered
    public reference at /api-docs, but it should not be treated as a stable
    public contract until v0.1.0 is explicitly approved.

    Return to the [AfterCheck marketing site](/) or the [API overview](/#api).
  x-logo:
    url: /brand/aftercheck-logo.svg
    altText: AfterCheck
servers:
  - url: http://localhost:3000
    description: Local development
tags:
  - name: Campaigns
    description: Reusable feedback flows that can be shared through public campaign links.
  - name: Feedback requests
    description: Tracked customer, job, order, appointment, or ticket-specific feedback invitations.
  - name: Responses
    description: Submitted feedback records scoped to the API key organization.
security:
  - bearerApiKey: []
paths:
  /api/v1/campaigns:
    get:
      operationId: listCampaigns
      summary: List campaigns
      description: List campaigns for the API key organization.
      tags:
        - Campaigns
      security:
        - bearerApiKey: []
      responses:
        "200":
          description: Campaign list
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Campaign"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /api/v1/feedback-requests:
    post:
      operationId: createFeedbackRequest
      summary: Create feedback request
      description: Create a tracked feedback request and public request-token link for the API key organization.
      tags:
        - Feedback requests
      security:
        - bearerApiKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateFeedbackRequest"
      responses:
        "201":
          description: Feedback request created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FeedbackRequestCreated"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          description: Duplicate external reference
        "500":
          $ref: "#/components/responses/ServerError"
  /api/v1/responses:
    get:
      operationId: listResponses
      summary: List responses
      description: List feedback responses for the API key organization.
      tags:
        - Responses
      security:
        - bearerApiKey: []
      parameters:
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            default: 50
            maximum: 100
            minimum: 0
        - name: offset
          in: query
          required: false
          schema:
            type: integer
            default: 0
            minimum: 0
      responses:
        "200":
          description: Response list
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                  - total
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/FeedbackResponse"
                  total:
                    type: integer
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
components:
  securitySchemes:
    bearerApiKey:
      type: http
      scheme: bearer
      description: Dashboard-created AfterCheck API key.
  responses:
    BadRequest:
      description: Invalid request input
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    Unauthorized:
      description: Missing, invalid, or revoked API key
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    Forbidden:
      description: Missing required scope
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    NotFound:
      description: Resource not found or not accessible to the organization
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    ServerError:
      description: Unexpected server-side failure
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
  schemas:
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: string
    Campaign:
      type: object
      required:
        - id
        - name
        - slug
        - status
        - type
        - headline
        - created_at
        - updated_at
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        slug:
          type: string
        status:
          type: string
        type:
          type: string
        headline:
          type:
            - string
            - "null"
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    CreateFeedbackRequest:
      type: object
      required:
        - campaign_id
      properties:
        campaign_id:
          type: string
          format: uuid
        customer_name:
          type: string
          maxLength: 200
        customer_email:
          type: string
          format: email
          maxLength: 320
        external_ref:
          type: string
          maxLength: 500
        source:
          type: string
          maxLength: 80
          description: Delivery/source label for the request link.
        utm_source:
          type: string
          maxLength: 120
        utm_medium:
          type: string
          maxLength: 120
        utm_campaign:
          type: string
          maxLength: 120
        utm_content:
          type: string
          maxLength: 120
        utm_term:
          type: string
          maxLength: 120
    FeedbackRequestCreated:
      type: object
      required:
        - id
        - campaign_id
        - request_token
        - request_url
        - campaign_slug
        - url
      properties:
        id:
          type: string
          format: uuid
        campaign_id:
          type: string
          format: uuid
        request_token:
          type: string
        request_url:
          type: string
          format: uri
        campaign_slug:
          type: string
        customer_name:
          type:
            - string
            - "null"
        customer_email:
          type:
            - string
            - "null"
          format: email
        external_ref:
          type:
            - string
            - "null"
        source:
          type:
            - string
            - "null"
        utm_source:
          type:
            - string
            - "null"
        utm_medium:
          type:
            - string
            - "null"
        utm_campaign:
          type:
            - string
            - "null"
        utm_content:
          type:
            - string
            - "null"
        utm_term:
          type:
            - string
            - "null"
        created_at:
          type: string
          format: date-time
        url:
          type: string
          format: uri
    FeedbackResponse:
      type: object
      required:
        - id
        - campaign_id
        - sentiment
        - status
        - comment
        - customer_name
        - created_at
      properties:
        id:
          type: string
          format: uuid
        campaign_id:
          type: string
          format: uuid
        sentiment:
          type: string
          enum:
            - positive
            - neutral
            - negative
        status:
          type: string
        comment:
          type:
            - string
            - "null"
        customer_name:
          type:
            - string
            - "null"
        created_at:
          type: string
          format: date-time
