openapi: 3.1.0
info:
  title: FairLinks API
  version: 1.0.0
  description: Pay-per-use short links, QR downloads, analytics, domains, bio pages, campaigns, and webhooks.
    This inventory is generated from FairLinks' Fastify registrations.
servers:
  - url: https://api.faircompany.ai
    description: Production
  - url: https://staging.api.faircompany.ai
    description: Staging
security:
  - BearerAuth: []
tags:
  - name: Links
  - name: Analytics
  - name: Campaigns
  - name: Domains
  - name: Tags
  - name: Bio pages
  - name: Webhooks
  - name: Redirects
x-generated-from:
  - apps/api/src/links/routes.ts
x-operation-count: 48
paths:
  /b/{username}:
    get:
      operationId: getBUsername
      summary: Read a public bio page
      tags:
        - Bio pages
      x-source: apps/api/src/links/routes.ts
      responses:
        "429":
          $ref: "#/components/responses/PublicLinkError"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
      security: []
      parameters:
        - name: username
          in: path
          required: true
          schema:
            type: string
  /r/{slug}:
    get:
      operationId: getRSlug
      summary: Resolve a short link and redirect to its destination
      tags:
        - Redirects
      x-source: apps/api/src/links/routes.ts
      responses:
        "301":
          description: Permanent redirect
          headers:
            Location:
              schema:
                type: string
                format: uri
        "302":
          description: Temporary redirect
          headers:
            Location:
              schema:
                type: string
                format: uri
        "404":
          $ref: "#/components/responses/PublicLinkError"
        "410":
          $ref: "#/components/responses/PublicLinkError"
        "429":
          $ref: "#/components/responses/PublicLinkError"
      security: []
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
  /v1/analytics/events:
    get:
      operationId: getAnalyticsEvents
      summary: GET /v1/analytics/events
      tags:
        - Analytics
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
  /v1/analytics/overview:
    get:
      operationId: getAnalyticsOverview
      summary: GET /v1/analytics/overview
      tags:
        - Analytics
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
  /v1/bio:
    post:
      operationId: postBio
      summary: POST /v1/bio
      tags:
        - Bio pages
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/bio/{id}:
    delete:
      operationId: deleteBioId
      summary: DELETE /v1/bio/{id}
      tags:
        - Bio pages
      x-source: apps/api/src/links/routes.ts
      responses:
        "204":
          description: Deleted
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
    get:
      operationId: getBioId
      summary: GET /v1/bio/{id}
      tags:
        - Bio pages
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
    patch:
      operationId: patchBioId
      summary: PATCH /v1/bio/{id}
      tags:
        - Bio pages
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/bio/{id}/links:
    post:
      operationId: postBioIdLinks
      summary: POST /v1/bio/{id}/links
      tags:
        - Bio pages
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/bio/{id}/links/{linkId}:
    delete:
      operationId: deleteBioIdLinksLinkId
      summary: DELETE /v1/bio/{id}/links/{linkId}
      tags:
        - Bio pages
      x-source: apps/api/src/links/routes.ts
      responses:
        "204":
          description: Deleted
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
        - name: linkId
          in: path
          required: true
          schema:
            type: string
    patch:
      operationId: patchBioIdLinksLinkId
      summary: PATCH /v1/bio/{id}/links/{linkId}
      tags:
        - Bio pages
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
        - name: linkId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/campaigns:
    get:
      operationId: getCampaigns
      summary: GET /v1/campaigns
      tags:
        - Campaigns
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
  /v1/campaigns/{name}:
    get:
      operationId: getCampaignsName
      summary: GET /v1/campaigns/{name}
      tags:
        - Campaigns
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: name
          in: path
          required: true
          schema:
            type: string
  /v1/campaigns/{name}/export:
    get:
      operationId: getCampaignsNameExport
      summary: Export a campaign as CSV
      tags:
        - Campaigns
      x-source: apps/api/src/links/routes.ts
      responses:
        "200":
          description: Campaign CSV export
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
          content:
            text/csv:
              schema:
                type: string
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
      security:
        - BearerAuth: []
      parameters:
        - name: name
          in: path
          required: true
          schema:
            type: string
  /v1/domains:
    get:
      operationId: getDomains
      summary: GET /v1/domains
      tags:
        - Domains
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
    post:
      operationId: postDomains
      summary: POST /v1/domains
      tags:
        - Domains
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/domains/{id}:
    delete:
      operationId: deleteDomainsId
      summary: DELETE /v1/domains/{id}
      tags:
        - Domains
      x-source: apps/api/src/links/routes.ts
      responses:
        "204":
          description: Deleted
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/domains/{id}/verify:
    get:
      operationId: getDomainsIdVerify
      summary: GET /v1/domains/{id}/verify
      tags:
        - Domains
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/links:
    get:
      operationId: getLinks
      summary: List links in the authenticated workspace
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "200":
          description: Paginated links
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/LinkListResponse"
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
      security:
        - BearerAuth: []
      parameters:
        - name: tag
          in: query
          schema:
            type: string
        - name: domain
          in: query
          schema:
            type: string
        - name: status
          in: query
          schema:
            type: string
            enum:
              - active
              - expired
              - archived
        - name: search
          in: query
          schema:
            type: string
        - name: sort
          in: query
          schema:
            type: string
            enum:
              - created_at
              - total_clicks
              - unique_clicks
        - name: from
          in: query
          schema:
            type: string
        - name: to
          in: query
          schema:
            type: string
        - name: cursor
          in: query
          schema:
            type: string
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
    post:
      operationId: postLinks
      summary: Create a short link
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "201":
          description: Created link
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
      security:
        - BearerAuth: []
      parameters:
        - name: tag
          in: query
          schema:
            type: string
        - name: domain
          in: query
          schema:
            type: string
        - name: status
          in: query
          schema:
            type: string
            enum:
              - active
              - expired
              - archived
        - name: search
          in: query
          schema:
            type: string
        - name: sort
          in: query
          schema:
            type: string
            enum:
              - created_at
              - total_clicks
              - unique_clicks
        - name: from
          in: query
          schema:
            type: string
        - name: to
          in: query
          schema:
            type: string
        - name: cursor
          in: query
          schema:
            type: string
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/LinkCreateRequest"
  /v1/links/{id}:
    delete:
      operationId: deleteLinksId
      summary: Delete a link
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "204":
          description: Deleted
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
    get:
      operationId: getLinksId
      summary: GET /v1/links/{id}
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
    patch:
      operationId: patchLinksId
      summary: PATCH /v1/links/{id}
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/links/{id}/analytics:
    get:
      operationId: getLinksIdAnalytics
      summary: GET /v1/links/{id}/analytics
      tags:
        - Analytics
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/links/{id}/archive:
    post:
      operationId: postLinksIdArchive
      summary: POST /v1/links/{id}/archive
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/links/{id}/clicks:
    get:
      operationId: getLinksIdClicks
      summary: GET /v1/links/{id}/clicks
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/links/{id}/qr:
    get:
      operationId: getLinksIdQr
      summary: Download a PNG or SVG QR code
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "200":
          description: QR image
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
          content:
            image/png:
              schema:
                type: string
                contentEncoding: binary
            image/svg+xml:
              schema:
                type: string
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/links/{id}/qr/styled:
    post:
      operationId: postLinksIdQrStyled
      summary: POST /v1/links/{id}/qr/styled
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/links/{id}/unarchive:
    post:
      operationId: postLinksIdUnarchive
      summary: POST /v1/links/{id}/unarchive
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/links/analytics:
    get:
      operationId: getLinksAnalytics
      summary: GET /v1/links/analytics
      tags:
        - Analytics
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
  /v1/links/batch:
    post:
      operationId: postLinksBatch
      summary: POST /v1/links/batch
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/links/bulk:
    post:
      operationId: postLinksBulk
      summary: POST /v1/links/bulk
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/links/contact-hash:
    post:
      operationId: postLinksContactHash
      summary: POST /v1/links/contact-hash
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/links/domains:
    get:
      operationId: getLinksDomains
      summary: GET /v1/links/domains
      tags:
        - Domains
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
    post:
      operationId: postLinksDomains
      summary: POST /v1/links/domains
      tags:
        - Domains
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/links/domains/{id}:
    delete:
      operationId: deleteLinksDomainsId
      summary: DELETE /v1/links/domains/{id}
      tags:
        - Domains
      x-source: apps/api/src/links/routes.ts
      responses:
        "204":
          description: Deleted
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/links/domains/{id}/verify:
    get:
      operationId: getLinksDomainsIdVerify
      summary: GET /v1/links/domains/{id}/verify
      tags:
        - Domains
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/links/health:
    get:
      operationId: getLinksHealth
      summary: Read the public FairLinks health status
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "200":
          description: FairLinks is healthy
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Health"
      security: []
  /v1/links/posts/{postId}/analytics:
    get:
      operationId: getLinksPostsPostIdAnalytics
      summary: GET /v1/links/posts/{postId}/analytics
      tags:
        - Analytics
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: postId
          in: path
          required: true
          schema:
            type: string
  /v1/links/workspaces:
    get:
      operationId: getLinksWorkspaces
      summary: GET /v1/links/workspaces
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
    post:
      operationId: postLinksWorkspaces
      summary: POST /v1/links/workspaces
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/links/workspaces/{id}:
    get:
      operationId: getLinksWorkspacesId
      summary: GET /v1/links/workspaces/{id}
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
    patch:
      operationId: patchLinksWorkspacesId
      summary: PATCH /v1/links/workspaces/{id}
      tags:
        - Links
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/tags:
    get:
      operationId: getTags
      summary: GET /v1/tags
      tags:
        - Tags
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
  /v1/tags/{name}/links:
    get:
      operationId: getTagsNameLinks
      summary: GET /v1/tags/{name}/links
      tags:
        - Tags
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      parameters:
        - name: name
          in: path
          required: true
          schema:
            type: string
  /v1/webhooks:
    get:
      operationId: getWebhooks
      summary: GET /v1/webhooks
      tags:
        - Webhooks
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
    post:
      operationId: postWebhooks
      summary: POST /v1/webhooks
      tags:
        - Webhooks
      x-source: apps/api/src/links/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/webhooks/{id}:
    delete:
      operationId: deleteWebhooksId
      summary: DELETE /v1/webhooks/{id}
      tags:
        - Webhooks
      x-source: apps/api/src/links/routes.ts
      responses:
        "204":
          description: Deleted
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "409":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Fair API key (fc_…)
  headers:
    RateLimitLimit:
      description: Requests allowed in the current window
      schema:
        type: integer
    RateLimitRemaining:
      description: Requests remaining in the current window
      schema:
        type: integer
    RateLimitReset:
      description: Unix timestamp when the current window resets
      schema:
        type: integer
  responses:
    Problem:
      description: RFC 9457 problem detail for authenticated Fair API operations
      headers:
        X-RateLimit-Limit:
          $ref: "#/components/headers/RateLimitLimit"
        X-RateLimit-Remaining:
          $ref: "#/components/headers/RateLimitRemaining"
        X-RateLimit-Reset:
          $ref: "#/components/headers/RateLimitReset"
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/Problem"
    RateLimited:
      description: Authenticated API rate limit exceeded
      headers:
        X-RateLimit-Limit:
          $ref: "#/components/headers/RateLimitLimit"
        X-RateLimit-Remaining:
          $ref: "#/components/headers/RateLimitRemaining"
        X-RateLimit-Reset:
          $ref: "#/components/headers/RateLimitReset"
        Retry-After:
          schema:
            type: integer
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/Problem"
    PublicLinkError:
      description: Current public redirect/bio error body; not the shared RFC 9457 contract
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/PublicLinkError"
  schemas:
    Problem:
      type: object
      required:
        - type
        - title
        - status
        - code
        - detail
      properties:
        type:
          type: string
          format: uri
        title:
          type: string
        status:
          type: integer
        code:
          type: string
        detail:
          type: string
        requestId:
          type: string
    PublicLinkError:
      type: object
      required:
        - error
      properties:
        error:
          type: string
    Health:
      type: object
      required:
        - status
        - product
        - uptime_seconds
      properties:
        status:
          type: string
        product:
          type: string
        uptime_seconds:
          type: number
    LinkCreateRequest:
      type: object
      required:
        - url
      additionalProperties: false
      properties:
        url:
          type: string
          format: uri
        slug:
          type: string
        domainId:
          type: string
        workspaceId:
          type: string
        tags:
          type: array
          items:
            type: string
        utm:
          type: object
          additionalProperties:
            type: string
        expiresAt:
          type: string
        notes:
          type: string
        ogTitle:
          type: string
        ogDescription:
          type: string
        ogImage:
          type: string
          format: uri
        meta:
          type: object
          additionalProperties: true
        contactId:
          type: string
        postId:
          type: string
        metadata:
          type: object
          additionalProperties: true
        idempotencyKey:
          type: string
    LinkListResponse:
      type: object
      required:
        - data
        - pagination
      properties:
        data:
          type: array
          items:
            type: object
            additionalProperties: true
        pagination:
          type: object
          required:
            - hasMore
          properties:
            cursor:
              type: string
            hasMore:
              type: boolean
