openapi: 3.1.0
info:
  title: Fluxtail Ingest API
  version: 1.0.0
  description: Public shared HTTP ingest endpoints. OTLP gRPC is documented separately.
servers:
  - url: https://ingest.fluxtail.io
security:
  - bearerAuth: []
paths:
  /v1/receivers/{receiverId}/logs:
    post:
      summary: Send HTTP JSON logs
      parameters:
        - $ref: '#/components/parameters/ReceiverId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - type: object
                  additionalProperties: true
                - type: array
                  minItems: 1
                  items:
                    type: object
                    additionalProperties: true
      responses:
        '202':
          description: Accepted for processing
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Accepted'
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '403': { $ref: '#/components/responses/Forbidden' }
        '413': { $ref: '#/components/responses/TooLarge' }
        '415': { $ref: '#/components/responses/Unsupported' }
        '429': { $ref: '#/components/responses/Limited' }
        '503': { $ref: '#/components/responses/Unavailable' }
  /v1/receivers/{receiverId}/otlp/v1/logs:
    post:
      summary: Export OTLP logs over HTTP
      parameters:
        - $ref: '#/components/parameters/ReceiverId'
      requestBody:
        required: true
        content:
          application/json:
            schema: { type: object, additionalProperties: true }
          application/x-protobuf:
            schema: { type: string, contentEncoding: binary }
      responses:
        '200': { description: Matching OTLP export response }
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '403': { $ref: '#/components/responses/Forbidden' }
        '413': { $ref: '#/components/responses/TooLarge' }
        '415': { $ref: '#/components/responses/Unsupported' }
        '429': { $ref: '#/components/responses/Limited' }
        '503': { $ref: '#/components/responses/Unavailable' }
  /v1/receivers/{receiverId}/prometheus/metrics:
    post:
      summary: Push Prometheus text exposition
      parameters:
        - $ref: '#/components/parameters/ReceiverId'
      requestBody:
        required: true
        content:
          text/plain:
            schema: { type: string }
          application/openmetrics-text:
            schema: { type: string }
      responses:
        '202': { description: Accepted for processing }
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '403': { $ref: '#/components/responses/Forbidden' }
        '413': { $ref: '#/components/responses/TooLarge' }
        '415': { $ref: '#/components/responses/Unsupported' }
        '429': { $ref: '#/components/responses/Limited' }
        '503': { $ref: '#/components/responses/Unavailable' }
  /v1/receivers/{receiverId}/prometheus/api/v1/write:
    post:
      summary: Push Prometheus remote_write v1
      parameters:
        - $ref: '#/components/parameters/ReceiverId'
      requestBody:
        required: true
        content:
          application/x-protobuf:
            schema: { type: string, contentEncoding: binary }
      responses:
        '204': { description: Accepted for processing }
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '403': { $ref: '#/components/responses/Forbidden' }
        '413': { $ref: '#/components/responses/TooLarge' }
        '415': { $ref: '#/components/responses/Unsupported' }
        '429': { $ref: '#/components/responses/Limited' }
        '503': { $ref: '#/components/responses/Unavailable' }
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Fluxtail receiver token
  parameters:
    ReceiverId:
      name: receiverId
      in: path
      required: true
      schema: { type: string, format: uuid }
  schemas:
    Accepted:
      type: object
      required: [accepted]
      properties:
        accepted: { type: integer, minimum: 1 }
  responses:
    BadRequest: { description: Malformed payload }
    Unauthorized: { description: Missing, conflicting, or invalid token }
    Forbidden: { description: Receiver, protocol, or IP policy denied }
    TooLarge: { description: Request body is too large }
    Unsupported: { description: Unsupported content type or encoding }
    Limited: { description: Account or receiver event limit exceeded }
    Unavailable: { description: Required ingest dependency is unavailable }
