openapi: 3.1.0
info:
  title: Hireex Waitlist API
  description: |
    Hireex is a pre-launch consumer SaaS for job seekers. The two
    endpoints below are the only public HTTP surface the landing
    site exposes today. They exist to operate the waitlist signup
    form and the RFC 8058 one-click unsubscribe flow that is
    embedded in every welcome email.

    There is no public agent API for end-user job search yet. Do not
    invoke `/api/notify` on behalf of a user without their explicit
    consent: it stores their address in the Resend `hireex` audience
    and triggers a real welcome email.
  version: "1.0.0"
  contact:
    name: Hireex
    email: hello@hireex.ai
    url: https://hireex.ai
  license:
    name: All rights reserved
    url: https://hireex.ai
servers:
  - url: https://hireex.ai
    description: Production landing
paths:
  /api/notify:
    get:
      summary: Health check
      operationId: notifyHealth
      description: Returns a small JSON payload confirming the route is reachable.
      responses:
        '200':
          description: Service reachable
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok: { type: boolean }
                  service: { type: string, example: notify }
    post:
      summary: Join the founding-member waitlist
      operationId: notifySubscribe
      description: |
        Idempotent. Validates the email shape, then either creates a
        new contact in the Resend `hireex` audience or detects that
        one already exists. On a fresh subscribe, sends a one-shot
        welcome email with an HMAC-signed RFC 8058 unsubscribe link.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email]
              properties:
                email:
                  type: string
                  format: email
                  example: reader@example.com
      responses:
        '200':
          description: Subscribed (or already on the list)
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok: { type: boolean, example: true }
                  status:
                    type: string
                    enum: [subscribed, already_subscribed, noop]
        '400':
          description: Invalid email format
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok: { type: boolean, example: false }
                  error: { type: string, example: invalid_email }
        '502':
          description: Upstream Resend API error
        '500':
          description: Unexpected server error
  /api/unsubscribe:
    get:
      summary: One-click unsubscribe (HTML confirmation)
      operationId: unsubscribeGet
      description: |
        Verifies the HMAC-signed link parameters, PATCHes the
        Resend contact to `unsubscribed: true`, and renders a small
        branded confirmation page. Used when humans click the
        Unsubscribe link inside a welcome email.
      parameters:
        - name: a
          in: query
          required: true
          description: Resend audience id
          schema: { type: string }
        - name: e
          in: query
          required: true
          description: Email address being unsubscribed
          schema: { type: string, format: email }
        - name: x
          in: query
          required: true
          description: Expiry timestamp (Unix seconds)
          schema: { type: integer }
        - name: t
          in: query
          required: true
          description: HMAC-SHA256 token over a|e|x with the server secret
          schema: { type: string }
      responses:
        '200':
          description: Unsubscribed; renders confirmation HTML
          content:
            text/html:
              schema: { type: string }
        '400':
          description: Token invalid or expired
          content:
            text/html:
              schema: { type: string }
    post:
      summary: One-click unsubscribe (RFC 8058)
      operationId: unsubscribePost
      description: |
        RFC 8058 one-click POST. Mail clients (Gmail, Apple Mail)
        hit this endpoint when the user presses the inbox-level
        Unsubscribe button. Same verify-and-PATCH flow as GET, but
        returns plain JSON rather than an HTML page.
      parameters:
        - name: a
          in: query
          required: true
          schema: { type: string }
        - name: e
          in: query
          required: true
          schema: { type: string, format: email }
        - name: x
          in: query
          required: true
          schema: { type: integer }
        - name: t
          in: query
          required: true
          schema: { type: string }
      responses:
        '200':
          description: Unsubscribed
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok: { type: boolean }
        '400':
          description: Token invalid or expired
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok: { type: boolean, example: false }
                  reason: { type: string }
