{
  "openapi": "3.1.0",
  "info": {
    "title": "kLog Ingest API",
    "version": "0.1.0",
    "description": "Contrato REST exclusivo para ingesta de eventos. Un evento por POST."
  },
  "paths": {
    "/v1/ingest/{tenantId}/events": {
      "post": {
        "operationId": "ingestEvent",
        "summary": "Ingiere un evento en el tenant",
        "security": [
          {
            "userJWT": []
          },
          {
            "userCookie": []
          },
          {
            "apiToken": []
          }
        ],
        "parameters": [
          {
            "name": "tenantId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "description": "UUIDv7 público; nunca corresponde al ID incremental interno."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IngestEventInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Evento persistido",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Event"
                }
              }
            }
          },
          "202": {
            "description": "Evento descartado por un transform de tipo filter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IngestDropped"
                }
              }
            }
          },
          "400": {
            "description": "Entrada inválida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIError"
                }
              }
            }
          },
          "401": {
            "description": "No autenticado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIError"
                }
              }
            }
          },
          "402": {
            "description": "Cuota del plan superada (BILLING_MODE=cloud)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIError"
                }
              }
            }
          },
          "403": {
            "description": "Sin permiso events.write o fuera del scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIError"
                }
              }
            }
          },
          "429": {
            "description": "Cuota de ingesta superada",
            "headers": {
              "Retry-After": {
                "description": "Segundos hasta poder reintentar",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer",
                  "description": "Epoch Unix del fin de la ventana"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "userJWT": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Access JWT de usuario; sub contiene su UUIDv7 y su sesión debe seguir activa."
      },
      "userCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "klog_access"
      },
      "apiToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "klog_api_token",
        "description": "Token opaco ligado a un proyecto y al rol device."
      }
    },
    "schemas": {
      "IngestEventInput": {
        "type": "object",
        "required": [
          "message"
        ],
        "additionalProperties": false,
        "properties": {
          "applicationId": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
            "description": "Obligatorio con API token; la aplicación debe pertenecer a su proyecto."
          },
          "level": {
            "type": "string",
            "description": "Severidad. Vacío → info. Alias warning→warn, err/fatal/critical→error, trace→debug.",
            "enum": [
              "debug",
              "info",
              "warn",
              "error",
              "warning",
              "err",
              "fatal",
              "critical",
              "trace"
            ]
          },
          "traceId": {
            "type": "string",
            "maxLength": 128,
            "description": "Identificador de traza opcional."
          },
          "message": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32768
          },
          "payload": {
            "description": "Objeto JSON. Si falta, el servidor usa {}.",
            "default": {}
          },
          "tags": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          }
        }
      },
      "Event": {
        "type": "object",
        "required": [
          "id",
          "message",
          "payload",
          "tags",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
          },
          "applicationId": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
          },
          "level": {
            "type": "string",
            "enum": [
              "debug",
              "info",
              "warn",
              "error"
            ]
          },
          "message": {
            "type": "string"
          },
          "payload": {},
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "IngestDropped": {
        "type": "object",
        "required": [
          "dropped",
          "id"
        ],
        "additionalProperties": false,
        "properties": {
          "dropped": {
            "type": "boolean",
            "const": true
          },
          "id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "APIError": {
        "type": "object",
        "required": [
          "error"
        ],
        "additionalProperties": false,
        "properties": {
          "error": {
            "type": "string"
          }
        }
      }
    }
  }
}
