{
  "openapi": "3.1.0",
  "info": {
    "title": "Onli Ponto API",
    "version": "1.0.0",
    "description": "API pública, gratuita, somente leitura e sem autenticação para consultar planos, cotações e disponibilidade básica do Onli Ponto.",
    "contact": {
      "name": "Suporte Onli Ponto",
      "email": "contato@onliponto.com.br"
    }
  },
  "servers": [
    {
      "url": "https://onliponto.com.br"
    }
  ],
  "tags": [
    {
      "name": "API pública",
      "description": "Informações comerciais públicas do produto."
    }
  ],
  "paths": {
    "/api/v1/plans": {
      "get": {
        "tags": [
          "API pública"
        ],
        "operationId": "getPublicPlans",
        "summary": "Listar planos e faixas de preço",
        "description": "Retorna preços públicos mensais e faixas de colaboradores. Não consulta dados de clientes.",
        "responses": {
          "200": {
            "description": "Planos públicos e preços por volume.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlansResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidParameter"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/api/v1/quote": {
      "get": {
        "tags": [
          "API pública"
        ],
        "operationId": "getPublicQuote",
        "summary": "Calcular cotação mensal",
        "description": "Calcula o preço mensal usando a mesma fonte de preços do site. Aceita de 1 a 1.000 colaboradores.",
        "parameters": [
          {
            "name": "employees",
            "in": "query",
            "required": true,
            "description": "Quantidade de colaboradores, como número inteiro entre 1 e 1.000.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000
            },
            "example": 25
          }
        ],
        "responses": {
          "200": {
            "description": "Cotação mensal calculada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidParameter"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/api/v1/health": {
      "get": {
        "tags": [
          "API pública"
        ],
        "operationId": "getPublicHealth",
        "summary": "Consultar disponibilidade",
        "description": "Confirma a disponibilidade deste endpoint público sem consultar serviços ou dados de clientes.",
        "responses": {
          "200": {
            "description": "Endpoint disponível.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidParameter"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "EmployeeRange": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "min",
          "max"
        ],
        "properties": {
          "min": {
            "type": "integer",
            "minimum": 1
          },
          "max": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000
          }
        }
      },
      "PublicPlan": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "employeeRange",
          "monthlyPriceCents",
          "monthlyPrice",
          "description"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "employeeRange": {
            "$ref": "#/components/schemas/EmployeeRange"
          },
          "monthlyPriceCents": {
            "type": "integer",
            "minimum": 0
          },
          "monthlyPrice": {
            "type": "string",
            "pattern": "^R\\$ [0-9]+,[0-9]{2}$"
          },
          "description": {
            "type": "string"
          }
        }
      },
      "PricePerEmployeeTier": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "minEmployees",
          "maxEmployees",
          "pricePerEmployeeCents",
          "pricePerEmployee"
        ],
        "properties": {
          "minEmployees": {
            "type": "integer",
            "minimum": 21
          },
          "maxEmployees": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 21
          },
          "pricePerEmployeeCents": {
            "type": "integer",
            "minimum": 0
          },
          "pricePerEmployee": {
            "type": "string",
            "pattern": "^R\\$ [0-9]+,[0-9]{2}$"
          }
        }
      },
      "PlansResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "version",
          "currency",
          "billingInterval",
          "plans",
          "volume"
        ],
        "properties": {
          "version": {
            "const": "v1"
          },
          "currency": {
            "const": "BRL"
          },
          "billingInterval": {
            "const": "month"
          },
          "plans": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicPlan"
            }
          },
          "volume": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "minEmployees",
              "maxEmployees",
              "minimumMonthlyPriceCents",
              "minimumMonthlyPrice",
              "pricePerEmployeeTiers"
            ],
            "properties": {
              "minEmployees": {
                "const": 21
              },
              "maxEmployees": {
                "const": 1000
              },
              "minimumMonthlyPriceCents": {
                "type": "integer",
                "minimum": 0
              },
              "minimumMonthlyPrice": {
                "type": "string",
                "pattern": "^R\\$ [0-9]+,[0-9]{2}$"
              },
              "pricePerEmployeeTiers": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PricePerEmployeeTier"
                }
              }
            }
          }
        }
      },
      "QuoteResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "version",
          "employees",
          "currency",
          "billingInterval",
          "planName",
          "monthlyPriceCents",
          "monthlyPrice",
          "pricePerEmployeeCents",
          "pricePerEmployee"
        ],
        "properties": {
          "version": {
            "const": "v1"
          },
          "employees": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000
          },
          "currency": {
            "const": "BRL"
          },
          "billingInterval": {
            "const": "month"
          },
          "planName": {
            "type": "string"
          },
          "monthlyPriceCents": {
            "type": "integer",
            "minimum": 0
          },
          "monthlyPrice": {
            "type": "string",
            "pattern": "^R\\$ [0-9]+,[0-9]{2}$"
          },
          "pricePerEmployeeCents": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "pricePerEmployee": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^R\\$ [0-9]+,[0-9]{2}$"
          }
        }
      },
      "HealthResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "const": "ok"
          }
        }
      },
      "ApiErrorResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "code",
              "message",
              "hint",
              "docs"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "invalid_parameter",
                  "not_found",
                  "method_not_allowed"
                ]
              },
              "message": {
                "type": "string"
              },
              "hint": {
                "type": "string"
              },
              "docs": {
                "type": "string",
                "format": "uri",
                "const": "https://onliponto.com.br/docs"
              }
            }
          }
        }
      }
    },
    "responses": {
      "InvalidParameter": {
        "description": "Parâmetro inválido.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "Endpoint não encontrado.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorResponse"
            }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "Método HTTP não permitido; use GET.",
        "headers": {
          "Allow": {
            "schema": {
              "type": "string",
              "const": "GET"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorResponse"
            }
          }
        }
      }
    }
  }
}
