openapi: 3.1.0
info:
  title: catchbin Public API
  version: 0.1.0
  description: >-
    

    **Download the OpenAPI spec:** [YAML](/openapi.yaml) · [JSON](/openapi.json)
    — import into Postman/Insomnia/Bruno or run codegen.
servers:
  - url: https://api.catchbin.io
    description: Generated server url
security:
  - bearerAuth: []
paths:
  /v1/endpoints:
    get:
      tags:
        - Operations
      summary: List endpoints
      operationId: list
      responses:
        "200":
          description: OK
          content:
            "*/*":
              schema:
                $ref: "#/components/schemas/EndpointListResponse"
    post:
      tags:
        - Operations
      summary: Create endpoint
      operationId: create
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateEndpointRequest"
        required: true
      responses:
        "201":
          description: Created
          content:
            "*/*":
              schema:
                $ref: "#/components/schemas/EndpointResponse"
  /v1/endpoints/{endpointId}/events:
    get:
      tags:
        - Operations
      summary: List captured events for an endpoint
      operationId: list_1
      parameters:
        - name: endpointId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: before
          in: query
          required: false
          schema:
            type: string
            format: date-time
        - name: beforeId
          in: query
          required: false
          schema:
            type: string
            format: uuid
        - name: after
          in: query
          required: false
          schema:
            type: string
            format: date-time
        - name: afterId
          in: query
          required: false
          schema:
            type: string
            format: uuid
        - name: from
          in: query
          required: false
          schema:
            type: string
            format: date-time
        - name: to
          in: query
          required: false
          schema:
            type: string
            format: date-time
        - name: eventType
          in: query
          required: false
          schema:
            type: string
        - name: provider
          in: query
          required: false
          schema:
            type: string
        - name: responseCode
          in: query
          required: false
          schema:
            type: integer
            format: int32
        - name: status
          in: query
          required: false
          schema:
            type: string
        - name: search
          in: query
          required: false
          schema:
            type: string
        - name: wait
          in: query
          required: false
          schema:
            type: string
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            format: int32
      responses:
        "200":
          description: OK
          content:
            "*/*":
              schema:
                $ref: "#/components/schemas/EventListResponse"
  /v1/endpoints/{endpointId}/events/{eventId}:
    get:
      tags:
        - Operations
      summary: Get one captured event with decrypted body
      operationId: detail
      parameters:
        - name: endpointId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: eventId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: OK
          content:
            "*/*":
              schema:
                $ref: "#/components/schemas/EventDetailResponse"
    delete:
      tags:
        - Operations
      summary: Delete a captured event (idempotent)
      operationId: delete_1
      parameters:
        - name: endpointId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: eventId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "204":
          description: No Content
  /v1/endpoints/{endpointId}/events/{eventId}/curl:
    get:
      tags:
        - Operations
      summary: Export a captured event as a single-line bash cURL command
      operationId: exportCurl
      parameters:
        - name: endpointId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: eventId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: unmasked
          in: query
          required: false
          schema:
            type: boolean
            default: false
      responses:
        "200":
          description: OK
          content:
            "*/*":
              schema:
                $ref: "#/components/schemas/CurlExportResponse"
  /v1/endpoints/{endpointId}/events/{eventId}/replay:
    post:
      tags:
        - Operations
      summary: Replay a captured event against an alternate target
      operationId: replay
      parameters:
        - name: endpointId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: eventId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ReplayRequestDto"
        required: true
      responses:
        "200":
          description: OK
          content:
            "*/*":
              schema:
                $ref: "#/components/schemas/ReplayResponseDto"
        "429":
          description: "Per-account daily replay limit reached (issue #293). The response
            carries a Retry-After header (seconds to the next UTC midnight) and
            RateLimit-Limit / RateLimit-Remaining / RateLimit-Reset headers."
          content:
            "*/*":
              schema:
                $ref: "#/components/schemas/ReplayResponseDto"
  /v1/endpoints/{id}:
    get:
      tags:
        - Operations
      summary: Get endpoint
      operationId: get
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: OK
          content:
            "*/*":
              schema:
                $ref: "#/components/schemas/EndpointResponse"
    delete:
      tags:
        - Operations
      summary: Delete endpoint
      operationId: delete
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "204":
          description: No Content
components:
  schemas:
    ReplayRequestDto:
      type: object
      properties:
        mode:
          type: string
        target_url:
          type: string
          minLength: 1
        target_secret:
          type: string
      required:
        - target_url
    ReplayResponseDto:
      type: object
      properties:
        result:
          type: string
        target_status:
          type: integer
          format: int32
        network_failure_reason:
          type: string
        duration_ms:
          type: integer
          format: int64
        response_excerpt_base64:
          type: string
        excerpt_truncated:
          type: boolean
        source_body_truncated:
          type: boolean
        mode:
          type: string
        target_url:
          type: string
        event_id:
          type: string
          format: uuid
        audit_id:
          type: string
          format: uuid
    CreateEndpointRequest:
      type: object
      properties:
        slug:
          type: string
          pattern: ^[a-z0-9][a-z0-9_-]{0,63}$
        displayName:
          type: string
          maxLength: 100
          minLength: 1
        operatingMode:
          type: string
        status:
          type: string
        replayFromDashboard:
          type: boolean
        replayFromApi:
          type: boolean
        genericSignatureHeader:
          type: string
        genericSignaturePrefix:
          type: string
    EndpointResponse:
      type: object
      properties:
        id:
          type: string
          format: uuid
        slug:
          type: string
        displayName:
          type: string
        webhookUrl:
          type: string
        operatingMode:
          type: string
        status:
          type: string
        replayFromDashboard:
          type: boolean
        replayFromApi:
          type: boolean
        provider:
          type: string
        secretSet:
          type: boolean
        genericSignatureHeader:
          type: string
        genericSignaturePrefix:
          type: string
        source:
          type: string
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        eventCount:
          type: integer
          format: int64
        lastEventAt:
          type: string
          format: date-time
        lastPurgedAt:
          type: string
          format: date-time
        purgedEventCount:
          type: integer
          format: int64
    EventDetailResponse:
      type: object
      properties:
        id:
          type: string
          format: uuid
        endpointId:
          type: string
          format: uuid
        receivedAt:
          type: string
          format: date-time
        method:
          type: string
        canonicalEventType:
          type: string
        provider:
          type: string
        verification:
          type: string
        verificationFailureReason:
          type: string
        responseCode:
          type: integer
          format: int32
        readAt:
          type: string
          format: date-time
        truncated:
          type: boolean
        originalSizeBytes:
          type: integer
          format: int64
        decryption:
          type: string
          enum:
            - ok
            - failed
            - metadata_only
        headers:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
        remoteIp:
          type: string
        body:
          type: string
        bodyEncoding:
          type: string
        diagnostic:
          type: object
          additionalProperties: {}
        forwardedResponse:
          type: object
          additionalProperties: {}
    CurlExportResponse:
      type: object
      properties:
        command:
          type: string
        byteIdentical:
          type: boolean
        bodyOmitted:
          type: boolean
        headersMasked:
          type: boolean
    EventListResponse:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/EventSummary"
        nextBefore:
          type: string
          format: date-time
        nextBeforeId:
          type: string
          format: uuid
        nextAfter:
          type: string
          format: date-time
        nextAfterId:
          type: string
          format: uuid
        searchExcludedMetadataOnlyCount:
          type: integer
          format: int32
    EventSummary:
      type: object
      properties:
        id:
          type: string
          format: uuid
        endpointId:
          type: string
          format: uuid
        receivedAt:
          type: string
          format: date-time
        method:
          type: string
        canonicalEventType:
          type: string
        provider:
          type: string
        verification:
          type: string
        verificationFailureReason:
          type: string
        responseCode:
          type: integer
          format: int32
        readAt:
          type: string
          format: date-time
        truncated:
          type: boolean
        originalSizeBytes:
          type: integer
          format: int64
        decryption:
          type: string
          enum:
            - ok
            - failed
            - metadata_only
        searchMatchedTruncated:
          type: boolean
    EndpointListResponse:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/EndpointResponse"
  securitySchemes:
    bearerAuth:
      type: http
      description: Catchbin API key presented as a Bearer token.
      scheme: bearer
