{
    "openapi": "3.1.0",
    "info": {
        "title": "API v1 do Cuidaro",
        "version": "2026-10-26",
        "summary": "API pública v1 para integradores (clientes, ordens de serviço, catálogo e webhooks).",
        "description": "Contrato máquina-legível da API v1 (ECO-API-OPENAPI-1). Documentação para desenvolvedores, com guias e exemplos: https://cuidaro.com.br/desenvolvedores. Em divergência, o comportamento do código prevalece e este arquivo o descreve.\n\n- Cada credencial pertence a uma única empresa; tudo o que a API devolve ou altera é dessa empresa. Recurso de outra empresa responde 404.\n- Erros em `application/problem+json` (RFC 7807) com `code` estável (`components.schemas.ApiErrorCode`).\n- Limites: emissão de token 10/min por IP; leitura (GET) 120/min e escrita (POST/PATCH/DELETE) 60/min por integração — ajustáveis por integração pelo suporte. Corpo até 512 KB. `x-cuidaro-rate-limit` indica o balde de cada operação.\n- `x-cuidaro-idempotency` marca as operações com `Idempotency-Key` obrigatória: `standard` ou `strict`.\n- Mantido à mão; `tests/Feature/Api/V1/OpenApiContractTest.php` confere rotas, métodos, escopos, idempotência, códigos de erro e eventos contra o código."
    },
    "servers": [
        {
            "url": "https://{dominio}/api/v1",
            "variables": {
                "dominio": {
                    "default": "cuidaro.com.br",
                    "description": "Domínio do Cuidaro."
                }
            }
        }
    ],
    "tags": [
        {
            "name": "Autenticação"
        },
        {
            "name": "Clientes"
        },
        {
            "name": "Ordens de serviço"
        },
        {
            "name": "Catálogo"
        },
        {
            "name": "Webhooks",
            "description": "Cadastro e histórico dos endpoints que recebem avisos."
        },
        {
            "name": "Webhooks (envios do Cuidaro)",
            "description": "Requisições que o Cuidaro faz ao seu endpoint (seção `webhooks`)."
        }
    ],
    "security": [
        {
            "oauth2": []
        }
    ],
    "paths": {
        "/oauth/token": {
            "post": {
                "operationId": "issueAccessToken",
                "tags": [
                    "Autenticação"
                ],
                "summary": "Emite access token (OAuth 2.0 client_credentials)",
                "description": "Credenciais no corpo (JSON ou formulário); HTTP Basic do cliente não é aceito. Credencial inexistente, segredo errado e integração revogada respondem o mesmo 401. A resposta tem `Cache-Control: no-store`.",
                "security": [],
                "x-cuidaro-rate-limit": "oauth-token",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/OAuthTokenRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/OAuthTokenRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Token emitido (válido por 1 hora; não há refresh token).",
                        "headers": {
                            "Cache-Control": {
                                "schema": {
                                    "type": "string"
                                },
                                "description": "`no-store`"
                            },
                            "Pragma": {
                                "schema": {
                                    "type": "string"
                                },
                                "description": "`no-cache`"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/OAuthTokenResponse"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Credenciais inválidas ou integração revogada. Códigos possíveis: `AUTH_CREDENTIALS_INVALID`.",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Escopo pedido fora do liberado à integração, ou empresa sem acesso. Códigos possíveis: `AUTH_SCOPE_INSUFFICIENT`, `AUTH_TENANT_SUSPENDED`, `AUTH_TENANT_PLAN_WITHOUT_API`.",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "description": "Mais de 10 emissões por minuto do mesmo IP. Código: `RATE_LIMIT_EXCEEDED`.",
                        "headers": {
                            "Retry-After": {
                                "$ref": "#/components/headers/Retry-After"
                            }
                        },
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            }
        },
        "/me": {
            "get": {
                "operationId": "getMe",
                "tags": [
                    "Autenticação"
                ],
                "summary": "Diagnóstico da credencial",
                "security": [
                    {
                        "oauth2": [
                            "services:read"
                        ]
                    }
                ],
                "x-cuidaro-rate-limit": "read",
                "responses": {
                    "200": {
                        "description": "Integração, token e empresa do token.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Me"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            }
        },
        "/contacts": {
            "post": {
                "operationId": "upsertContact",
                "tags": [
                    "Clientes"
                ],
                "summary": "Cadastra ou reaproveita cliente pelo CPF/CNPJ",
                "description": "Documento novo → cria (201). Documento já cadastrado → 200 `matched`, preenchendo só campos vazios no Cuidaro. Cadastro excluído com o documento → reativado, 200 `restored`.",
                "security": [
                    {
                        "oauth2": [
                            "services:write"
                        ]
                    }
                ],
                "x-cuidaro-rate-limit": "write",
                "x-cuidaro-idempotency": "standard",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ContactUpsertRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Cliente existente reaproveitado (`matched`) ou reativado (`restored`).",
                        "headers": {
                            "Idempotent-Replayed": {
                                "$ref": "#/components/headers/Idempotent-Replayed"
                            },
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data",
                                        "meta"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Contact"
                                        },
                                        "meta": {
                                            "type": "object",
                                            "required": [
                                                "operation"
                                            ],
                                            "properties": {
                                                "operation": {
                                                    "type": "string",
                                                    "enum": [
                                                        "created",
                                                        "matched",
                                                        "restored"
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "201": {
                        "description": "Cliente criado (`created`).",
                        "headers": {
                            "Idempotent-Replayed": {
                                "$ref": "#/components/headers/Idempotent-Replayed"
                            },
                            "Location": {
                                "$ref": "#/components/headers/Location"
                            },
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data",
                                        "meta"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Contact"
                                        },
                                        "meta": {
                                            "type": "object",
                                            "required": [
                                                "operation"
                                            ],
                                            "properties": {
                                                "operation": {
                                                    "type": "string",
                                                    "enum": [
                                                        "created",
                                                        "matched",
                                                        "restored"
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Limite do plano (traz `metric` e `limit`), mais de um cadastro excluído com o documento, ou conflito de idempotência. Códigos possíveis: `PLAN_QUOTA_EXCEEDED`, `RESOURCE_STATE_CONFLICT`, `IDEMPOTENCY_KEY_CONFLICT`, `IDEMPOTENCY_KEY_IN_PROGRESS`.",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Documento ausente/inválido, IBGE inválido ou de outra UF, ou `Idempotency-Key` ausente/inválida. Também: `IDEMPOTENCY_KEY_MISSING`, `IDEMPOTENCY_KEY_INVALID`.",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ValidationProblem"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            }
        },
        "/contacts/{contact}": {
            "parameters": [
                {
                    "$ref": "#/components/parameters/ContactId"
                }
            ],
            "get": {
                "operationId": "getContact",
                "tags": [
                    "Clientes"
                ],
                "summary": "Consulta cliente",
                "security": [
                    {
                        "oauth2": [
                            "services:read"
                        ]
                    }
                ],
                "x-cuidaro-rate-limit": "read",
                "responses": {
                    "200": {
                        "description": "Cliente.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Contact"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            }
        },
        "/service-orders": {
            "post": {
                "operationId": "createServiceOrder",
                "tags": [
                    "Ordens de serviço"
                ],
                "summary": "Cria OS",
                "description": "A OS nasce em `awaiting_invoice`. Idempotência comum: a `external_reference` única já impede OS duplicada.",
                "security": [
                    {
                        "oauth2": [
                            "services:write"
                        ]
                    }
                ],
                "x-cuidaro-rate-limit": "write",
                "x-cuidaro-idempotency": "standard",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ServiceOrderCreateRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "OS criada.",
                        "headers": {
                            "Idempotent-Replayed": {
                                "$ref": "#/components/headers/Idempotent-Replayed"
                            },
                            "Location": {
                                "$ref": "#/components/headers/Location"
                            },
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/ServiceOrder"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "`external_reference` já usada (traz `existing_resource_id`), limite do plano (traz `metric` e `limit`) ou conflito de idempotência. Códigos possíveis: `RESOURCE_ALREADY_EXISTS`, `PLAN_QUOTA_EXCEEDED`, `IDEMPOTENCY_KEY_CONFLICT`, `IDEMPOTENCY_KEY_IN_PROGRESS`.",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Dados inválidos, ou `Idempotency-Key` ausente/inválida. Também: `IDEMPOTENCY_KEY_MISSING`, `IDEMPOTENCY_KEY_INVALID`.",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ValidationProblem"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            }
        },
        "/service-orders/{serviceOrder}": {
            "parameters": [
                {
                    "$ref": "#/components/parameters/ServiceOrderId"
                }
            ],
            "get": {
                "operationId": "getServiceOrder",
                "tags": [
                    "Ordens de serviço"
                ],
                "summary": "Consulta OS",
                "security": [
                    {
                        "oauth2": [
                            "services:read"
                        ]
                    }
                ],
                "x-cuidaro-rate-limit": "read",
                "responses": {
                    "200": {
                        "description": "OS.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/ServiceOrder"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            }
        },
        "/service-orders/{serviceOrder}/invoice": {
            "parameters": [
                {
                    "$ref": "#/components/parameters/ServiceOrderId"
                }
            ],
            "post": {
                "operationId": "invoiceServiceOrder",
                "tags": [
                    "Ordens de serviço"
                ],
                "summary": "Fatura OS com pagamento já recebido fora do Cuidaro (operação estrita)",
                "description": "Registra o recebível já pago na conta escolhida pela empresa e pede a NFS-e (assíncrona). Se a nota não puder sair, a OS continua faturada e o motivo vem em `meta.warnings`. Quando a OS emite NFS-e integrada, o endereço completo do cliente e o `city_ibge_code` coerente com a UF são exigidos antes de faturar (422 com `error_codes` em `contact.address.<campo>`). Ordem das conferências: primeiro o estado da OS (já faturada, encerrada ou cancelada → 409 `RESOURCE_STATE_CONFLICT`, mesmo que a liberação de liquidação externa tenha sido retirada), depois a liberação da integração (422 `EXTERNAL_SETTLEMENT_NOT_ALLOWED`) e a conta de recebimento (422 `EXTERNAL_SETTLEMENT_ACCOUNT_MISSING`), depois o valor e o cadastro do cliente.",
                "security": [
                    {
                        "oauth2": [
                            "services:write"
                        ]
                    }
                ],
                "x-cuidaro-rate-limit": "write",
                "x-cuidaro-idempotency": "strict",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/IdempotencyKeyStrict"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ServiceOrderInvoiceRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OS faturada (`status: invoiced`).",
                        "headers": {
                            "Idempotent-Replayed": {
                                "$ref": "#/components/headers/Idempotent-Replayed"
                            },
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data",
                                        "meta"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/ServiceOrder"
                                        },
                                        "meta": {
                                            "type": "object",
                                            "required": [
                                                "operation",
                                                "warnings"
                                            ],
                                            "properties": {
                                                "operation": {
                                                    "type": "string",
                                                    "const": "invoiced"
                                                },
                                                "warnings": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "Avisos em pt-BR (ex.: NFS-e não pôde ser iniciada)."
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "description": "OS fora de `in_progress`/`awaiting_invoice` ou sem valor (traz `service_order_status` quando aplicável), pagamento já usado em outra OS (traz `existing_resource_id`) ou conflito de idempotência. Códigos possíveis: `RESOURCE_STATE_CONFLICT`, `RESOURCE_ALREADY_EXISTS`, `IDEMPOTENCY_KEY_CONFLICT`, `IDEMPOTENCY_KEY_IN_PROGRESS`.",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Dados inválidos, valor diferente do total (traz `expected_amount`/`received_amount`), integração sem permissão ou sem conta de recebimento, cadastro do cliente incompleto para a NFS-e, ou `Idempotency-Key` ausente/inválida. Também: `SETTLEMENT_AMOUNT_MISMATCH`, `EXTERNAL_SETTLEMENT_NOT_ALLOWED`, `EXTERNAL_SETTLEMENT_ACCOUNT_MISSING`, `IDEMPOTENCY_KEY_MISSING`, `IDEMPOTENCY_KEY_INVALID`.",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ValidationProblem"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            }
        },
        "/service-orders/{serviceOrder}/cancel": {
            "parameters": [
                {
                    "$ref": "#/components/parameters/ServiceOrderId"
                }
            ],
            "post": {
                "operationId": "cancelServiceOrder",
                "tags": [
                    "Ordens de serviço"
                ],
                "summary": "Cancela OS criada pela API, faturada ou ainda não faturada (operação estrita)",
                "description": "OS faturada pela API: estorna o recebimento informado no faturamento (uma única vez), cancela recebível e OS e pede o cancelamento da NFS-e. Repetir (com chave nova) só repete o passo fiscal. OS ainda não faturada (como a OS recém-criada pela API, em `awaiting_invoice`, sem nota): é cancelada e responde 202 com `meta.fiscal_cancellation = cancelled` e `data.fiscal = null` (contrato garantido; útil quando o estorno chega antes do faturamento). OS faturada pela tela do Cuidaro → 409 `RESOURCE_STATE_CONFLICT`.",
                "security": [
                    {
                        "oauth2": [
                            "services:write"
                        ]
                    }
                ],
                "x-cuidaro-rate-limit": "write",
                "x-cuidaro-idempotency": "strict",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/IdempotencyKeyStrict"
                    }
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ServiceOrderCancelRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "OS cancelada (`status: cancelled`); cancelamento fiscal em `meta.fiscal_cancellation`.",
                        "headers": {
                            "Idempotent-Replayed": {
                                "$ref": "#/components/headers/Idempotent-Replayed"
                            },
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data",
                                        "meta"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/ServiceOrder"
                                        },
                                        "meta": {
                                            "type": "object",
                                            "required": [
                                                "operation",
                                                "fiscal_cancellation"
                                            ],
                                            "properties": {
                                                "operation": {
                                                    "type": "string",
                                                    "const": "cancel"
                                                },
                                                "fiscal_cancellation": {
                                                    "type": "string",
                                                    "enum": [
                                                        "cancellation_pending",
                                                        "cancelled",
                                                        "cancellation_request_failed"
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "description": "OS faturada pela tela (sem pagamento informado pela API) ou em estado que não permite cancelar, ou conflito de idempotência. Códigos possíveis: `RESOURCE_STATE_CONFLICT`, `IDEMPOTENCY_KEY_CONFLICT`, `IDEMPOTENCY_KEY_IN_PROGRESS`.",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Dados inválidos, ou `Idempotency-Key` ausente/inválida. Também: `IDEMPOTENCY_KEY_MISSING`, `IDEMPOTENCY_KEY_INVALID`.",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ValidationProblem"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            }
        },
        "/services": {
            "get": {
                "operationId": "listServices",
                "tags": [
                    "Catálogo"
                ],
                "summary": "Lista o catálogo ativo de serviços (paginado)",
                "security": [
                    {
                        "oauth2": [
                            "services:read"
                        ]
                    }
                ],
                "x-cuidaro-rate-limit": "read",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/Page"
                    },
                    {
                        "$ref": "#/components/parameters/PerPage"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Página do catálogo, ordenado por nome.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data",
                                        "meta",
                                        "links"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/ServiceCatalogItem"
                                            }
                                        },
                                        "meta": {
                                            "$ref": "#/components/schemas/PaginationMeta"
                                        },
                                        "links": {
                                            "$ref": "#/components/schemas/PaginationLinks"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            }
        },
        "/webhook-endpoints": {
            "get": {
                "operationId": "listWebhookEndpoints",
                "tags": [
                    "Webhooks"
                ],
                "summary": "Lista os endpoints desta integração",
                "security": [
                    {
                        "oauth2": [
                            "webhooks:manage"
                        ]
                    }
                ],
                "x-cuidaro-rate-limit": "read",
                "responses": {
                    "200": {
                        "description": "Endpoints (sem o segredo), ordenados por id. Sem paginação.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/WebhookEndpoint"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            },
            "post": {
                "operationId": "createWebhookEndpoint",
                "tags": [
                    "Webhooks"
                ],
                "summary": "Cadastra endpoint de webhook",
                "description": "Não usa `Idempotency-Key`: a resposta traz o segredo, que não pode ser guardado nem repetido. Até 10 endpoints por integração.",
                "security": [
                    {
                        "oauth2": [
                            "webhooks:manage"
                        ]
                    }
                ],
                "x-cuidaro-rate-limit": "write",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/WebhookEndpointCreateRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Endpoint criado, com `secret`.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/WebhookEndpointWithSecret"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Teto de 10 endpoints por integração atingido. Códigos possíveis: `RESOURCE_STATE_CONFLICT`.",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Dados inválidos ou URL recusada. Também: `WEBHOOK_URL_NOT_ALLOWED`.",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ValidationProblem"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            }
        },
        "/webhook-endpoints/{endpoint}": {
            "parameters": [
                {
                    "$ref": "#/components/parameters/EndpointId"
                }
            ],
            "get": {
                "operationId": "getWebhookEndpoint",
                "tags": [
                    "Webhooks"
                ],
                "summary": "Detalhe do endpoint (sem o segredo)",
                "security": [
                    {
                        "oauth2": [
                            "webhooks:manage"
                        ]
                    }
                ],
                "x-cuidaro-rate-limit": "read",
                "responses": {
                    "200": {
                        "description": "Endpoint.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/WebhookEndpoint"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            },
            "patch": {
                "operationId": "updateWebhookEndpoint",
                "tags": [
                    "Webhooks"
                ],
                "summary": "Altera os campos enviados",
                "security": [
                    {
                        "oauth2": [
                            "webhooks:manage"
                        ]
                    }
                ],
                "x-cuidaro-rate-limit": "write",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/WebhookEndpointUpdateRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Endpoint alterado.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/WebhookEndpoint"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "description": "Dados inválidos ou URL recusada. Também: `WEBHOOK_URL_NOT_ALLOWED`.",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ValidationProblem"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            },
            "delete": {
                "operationId": "deleteWebhookEndpoint",
                "tags": [
                    "Webhooks"
                ],
                "summary": "Remove o endpoint e o histórico de entregas dele",
                "security": [
                    {
                        "oauth2": [
                            "webhooks:manage"
                        ]
                    }
                ],
                "x-cuidaro-rate-limit": "write",
                "responses": {
                    "204": {
                        "description": "Removido.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            }
        },
        "/webhook-endpoints/{endpoint}/rotate-secret": {
            "parameters": [
                {
                    "$ref": "#/components/parameters/EndpointId"
                }
            ],
            "post": {
                "operationId": "rotateWebhookEndpointSecret",
                "tags": [
                    "Webhooks"
                ],
                "summary": "Gera segredo novo (o antigo para de valer na hora)",
                "security": [
                    {
                        "oauth2": [
                            "webhooks:manage"
                        ]
                    }
                ],
                "x-cuidaro-rate-limit": "write",
                "responses": {
                    "200": {
                        "description": "Segredo novo.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "id",
                                                "secret"
                                            ],
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "secret": {
                                                    "type": "string",
                                                    "description": "`whsec_...`"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            }
        },
        "/webhook-endpoints/{endpoint}/ping": {
            "parameters": [
                {
                    "$ref": "#/components/parameters/EndpointId"
                }
            ],
            "post": {
                "operationId": "pingWebhookEndpoint",
                "tags": [
                    "Webhooks"
                ],
                "summary": "Enfileira um evento `ping` para este endpoint",
                "security": [
                    {
                        "oauth2": [
                            "webhooks:manage"
                        ]
                    }
                ],
                "x-cuidaro-rate-limit": "write",
                "responses": {
                    "202": {
                        "description": "Entrega criada.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/WebhookDelivery"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "description": "Endpoint desativado. Códigos possíveis: `RESOURCE_STATE_CONFLICT`.",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            }
        },
        "/webhook-endpoints/{endpoint}/deliveries": {
            "parameters": [
                {
                    "$ref": "#/components/parameters/EndpointId"
                }
            ],
            "get": {
                "operationId": "listWebhookDeliveries",
                "tags": [
                    "Webhooks"
                ],
                "summary": "Histórico de entregas do endpoint (paginado, mais recentes primeiro)",
                "security": [
                    {
                        "oauth2": [
                            "webhooks:manage"
                        ]
                    }
                ],
                "x-cuidaro-rate-limit": "read",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/Page"
                    },
                    {
                        "$ref": "#/components/parameters/PerPage"
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "$ref": "#/components/schemas/WebhookDeliveryStatus"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Página do histórico.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data",
                                        "meta",
                                        "links"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/WebhookDelivery"
                                            }
                                        },
                                        "meta": {
                                            "$ref": "#/components/schemas/PaginationMeta"
                                        },
                                        "links": {
                                            "$ref": "#/components/schemas/PaginationLinks"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            }
        },
        "/webhook-endpoints/{endpoint}/deliveries/{delivery}/redeliver": {
            "parameters": [
                {
                    "$ref": "#/components/parameters/EndpointId"
                },
                {
                    "$ref": "#/components/parameters/DeliveryId"
                }
            ],
            "post": {
                "operationId": "redeliverWebhookDelivery",
                "tags": [
                    "Webhooks"
                ],
                "summary": "Reenvia o mesmo evento (mesmo `id`)",
                "security": [
                    {
                        "oauth2": [
                            "webhooks:manage"
                        ]
                    }
                ],
                "x-cuidaro-rate-limit": "write",
                "responses": {
                    "202": {
                        "description": "Nova entrega criada para o mesmo evento.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/WebhookDelivery"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "description": "Endpoint desativado. Códigos possíveis: `RESOURCE_STATE_CONFLICT`.",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "413": {
                        "$ref": "#/components/responses/PayloadTooLarge"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/InternalError"
                    }
                }
            }
        }
    },
    "webhooks": {
        "ping": {
            "post": {
                "operationId": "webhook_ping",
                "tags": [
                    "Webhooks (envios do Cuidaro)"
                ],
                "summary": "Ping de teste",
                "description": "Enviado só quando você chama `POST /webhook-endpoints/{endpoint}/ping`, só para esse endpoint. Não precisa (nem pode) ser assinado em `events`.",
                "x-cuidaro-emitted": true,
                "parameters": [
                    {
                        "name": "Cuidaro-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix>,v1=<hex>` — `v1` = HMAC-SHA256 com o segredo do endpoint sobre `\"<t>.<corpo bruto>\"` (esquema do Stripe). Compare em tempo constante e recuse `t` com mais de 300 s de diferença.",
                        "schema": {
                            "type": "string",
                            "pattern": "^t=\\d+,v1=[0-9a-f]{64}$"
                        }
                    },
                    {
                        "name": "Cuidaro-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "Igual a `id` do corpo; não muda entre tentativas nem no reenvio. Use para deduplicar.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "Cuidaro-Event-Type",
                        "in": "header",
                        "required": true,
                        "description": "Igual a `type` do corpo.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "const": "Cuidaro-Webhooks/1.0"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WebhookEnvelope"
                                    },
                                    {
                                        "type": "object",
                                        "properties": {
                                            "type": {
                                                "const": "ping"
                                            },
                                            "data": {
                                                "type": "object",
                                                "required": [
                                                    "webhook_endpoint_id",
                                                    "message"
                                                ],
                                                "properties": {
                                                    "webhook_endpoint_id": {
                                                        "type": "integer"
                                                    },
                                                    "message": {
                                                        "type": "string"
                                                    }
                                                }
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Recebido. Responda em até 10 s (conexão: 5 s); o corpo é ignorado (até 2.000 caracteres guardados no histórico)."
                    },
                    "default": {
                        "description": "Qualquer outra resposta, redirecionamento (3xx não é seguido), timeout ou erro de conexão é falha: nova tentativa em 1 min, 5 min, 30 min, 2 h, 6 h, 12 h, 24 h, 24 h (9 tentativas); depois `exhausted`."
                    }
                }
            }
        },
        "fiscal_invoice.issued": {
            "post": {
                "operationId": "webhook_fiscal_invoice_issued",
                "tags": [
                    "Webhooks (envios do Cuidaro)"
                ],
                "summary": "NFS-e autorizada",
                "description": "NFS-e da OS autorizada pela prefeitura. Só para OS criadas pela API e só para os endpoints da integração que criou a OS (outra integração da mesma empresa não recebe); endpoint ativo e inscrito no evento. Emitido desde o ECO-API-4b (27/10/2026), depois de a mudança estar gravada, uma vez por transição (deduplique por `Cuidaro-Event-Id`). Sem dado pessoal do cliente.",
                "x-cuidaro-emitted": true,
                "parameters": [
                    {
                        "name": "Cuidaro-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix>,v1=<hex>` — `v1` = HMAC-SHA256 com o segredo do endpoint sobre `\"<t>.<corpo bruto>\"` (esquema do Stripe). Compare em tempo constante e recuse `t` com mais de 300 s de diferença.",
                        "schema": {
                            "type": "string",
                            "pattern": "^t=\\d+,v1=[0-9a-f]{64}$"
                        }
                    },
                    {
                        "name": "Cuidaro-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "Igual a `id` do corpo; não muda entre tentativas nem no reenvio. Use para deduplicar.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "Cuidaro-Event-Type",
                        "in": "header",
                        "required": true,
                        "description": "Igual a `type` do corpo.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "const": "Cuidaro-Webhooks/1.0"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WebhookEnvelope"
                                    },
                                    {
                                        "type": "object",
                                        "properties": {
                                            "type": {
                                                "const": "fiscal_invoice.issued"
                                            },
                                            "data": {
                                                "type": "object",
                                                "required": [
                                                    "service_order_id",
                                                    "external_reference",
                                                    "fiscal_invoice_id",
                                                    "type",
                                                    "number",
                                                    "issued_at",
                                                    "pdf_url",
                                                    "xml_url"
                                                ],
                                                "additionalProperties": false,
                                                "properties": {
                                                    "service_order_id": {
                                                        "type": "integer",
                                                        "description": "Id da OS no Cuidaro."
                                                    },
                                                    "external_reference": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Referência que o seu sistema informou ao criar a OS."
                                                    },
                                                    "fiscal_invoice_id": {
                                                        "type": "integer",
                                                        "description": "Id da nota no Cuidaro."
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "const": "nfse"
                                                    },
                                                    "number": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Número da NFS-e devolvido pela prefeitura (`numeroNfse`; nunca o número do RPS). `null` quando a prefeitura não informa."
                                                    },
                                                    "issued_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Data da autorização.",
                                                        "format": "date-time"
                                                    },
                                                    "pdf_url": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Link ASSINADO e temporário (72 h, cobre a janela de retentativas) do PDF servido pelo Cuidaro. Vencido, use `GET /service-orders/{id}`. `null` se o documento ainda não foi liberado.",
                                                        "format": "uri"
                                                    },
                                                    "xml_url": {
                                                        "type": "null",
                                                        "description": "Sempre `null` nesta versão."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Recebido. Responda em até 10 s (conexão: 5 s); o corpo é ignorado (até 2.000 caracteres guardados no histórico)."
                    },
                    "default": {
                        "description": "Qualquer outra resposta, redirecionamento (3xx não é seguido), timeout ou erro de conexão é falha: nova tentativa em 1 min, 5 min, 30 min, 2 h, 6 h, 12 h, 24 h, 24 h (9 tentativas); depois `exhausted`."
                    }
                }
            }
        },
        "fiscal_invoice.cancelled": {
            "post": {
                "operationId": "webhook_fiscal_invoice_cancelled",
                "tags": [
                    "Webhooks (envios do Cuidaro)"
                ],
                "summary": "Cancelamento da NFS-e aceito pelo município",
                "description": "Cancelamento confirmado pelo município, ou local quando a nota ainda não tinha saído (aí `number` é `null`). Só para OS criadas pela API e só para os endpoints da integração que criou a OS (outra integração da mesma empresa não recebe); endpoint ativo e inscrito no evento. Emitido desde o ECO-API-4b (27/10/2026), depois de a mudança estar gravada, uma vez por transição (deduplique por `Cuidaro-Event-Id`). Sem dado pessoal do cliente.",
                "x-cuidaro-emitted": true,
                "parameters": [
                    {
                        "name": "Cuidaro-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix>,v1=<hex>` — `v1` = HMAC-SHA256 com o segredo do endpoint sobre `\"<t>.<corpo bruto>\"` (esquema do Stripe). Compare em tempo constante e recuse `t` com mais de 300 s de diferença.",
                        "schema": {
                            "type": "string",
                            "pattern": "^t=\\d+,v1=[0-9a-f]{64}$"
                        }
                    },
                    {
                        "name": "Cuidaro-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "Igual a `id` do corpo; não muda entre tentativas nem no reenvio. Use para deduplicar.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "Cuidaro-Event-Type",
                        "in": "header",
                        "required": true,
                        "description": "Igual a `type` do corpo.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "const": "Cuidaro-Webhooks/1.0"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WebhookEnvelope"
                                    },
                                    {
                                        "type": "object",
                                        "properties": {
                                            "type": {
                                                "const": "fiscal_invoice.cancelled"
                                            },
                                            "data": {
                                                "type": "object",
                                                "required": [
                                                    "service_order_id",
                                                    "external_reference",
                                                    "fiscal_invoice_id",
                                                    "type",
                                                    "number",
                                                    "cancelled_at"
                                                ],
                                                "additionalProperties": false,
                                                "properties": {
                                                    "service_order_id": {
                                                        "type": "integer",
                                                        "description": "Id da OS no Cuidaro."
                                                    },
                                                    "external_reference": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Referência que o seu sistema informou ao criar a OS."
                                                    },
                                                    "fiscal_invoice_id": {
                                                        "type": "integer",
                                                        "description": "Id da nota no Cuidaro."
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "const": "nfse"
                                                    },
                                                    "number": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Número da NFS-e devolvido pela prefeitura (`numeroNfse`; nunca o número do RPS). `null` quando a prefeitura não informa."
                                                    },
                                                    "cancelled_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Data da confirmação do cancelamento.",
                                                        "format": "date-time"
                                                    }
                                                }
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Recebido. Responda em até 10 s (conexão: 5 s); o corpo é ignorado (até 2.000 caracteres guardados no histórico)."
                    },
                    "default": {
                        "description": "Qualquer outra resposta, redirecionamento (3xx não é seguido), timeout ou erro de conexão é falha: nova tentativa em 1 min, 5 min, 30 min, 2 h, 6 h, 12 h, 24 h, 24 h (9 tentativas); depois `exhausted`."
                    }
                }
            }
        },
        "fiscal_invoice.cancellation_rejected": {
            "post": {
                "operationId": "webhook_fiscal_invoice_cancellation_rejected",
                "tags": [
                    "Webhooks (envios do Cuidaro)"
                ],
                "summary": "Município recusou o cancelamento (a nota segue ativa)",
                "description": "O município recusou o cancelamento: a nota CONTINUA ATIVA. O `cancel` pode ser repetido; cada novo pedido recusado gera um novo evento. Só para OS criadas pela API e só para os endpoints da integração que criou a OS (outra integração da mesma empresa não recebe); endpoint ativo e inscrito no evento. Emitido desde o ECO-API-4b (27/10/2026), depois de a mudança estar gravada, uma vez por transição (deduplique por `Cuidaro-Event-Id`). Sem dado pessoal do cliente.",
                "x-cuidaro-emitted": true,
                "parameters": [
                    {
                        "name": "Cuidaro-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix>,v1=<hex>` — `v1` = HMAC-SHA256 com o segredo do endpoint sobre `\"<t>.<corpo bruto>\"` (esquema do Stripe). Compare em tempo constante e recuse `t` com mais de 300 s de diferença.",
                        "schema": {
                            "type": "string",
                            "pattern": "^t=\\d+,v1=[0-9a-f]{64}$"
                        }
                    },
                    {
                        "name": "Cuidaro-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "Igual a `id` do corpo; não muda entre tentativas nem no reenvio. Use para deduplicar.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "Cuidaro-Event-Type",
                        "in": "header",
                        "required": true,
                        "description": "Igual a `type` do corpo.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "const": "Cuidaro-Webhooks/1.0"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WebhookEnvelope"
                                    },
                                    {
                                        "type": "object",
                                        "properties": {
                                            "type": {
                                                "const": "fiscal_invoice.cancellation_rejected"
                                            },
                                            "data": {
                                                "type": "object",
                                                "required": [
                                                    "service_order_id",
                                                    "external_reference",
                                                    "fiscal_invoice_id",
                                                    "type",
                                                    "number",
                                                    "cancellation_requested_at",
                                                    "reason"
                                                ],
                                                "additionalProperties": false,
                                                "properties": {
                                                    "service_order_id": {
                                                        "type": "integer",
                                                        "description": "Id da OS no Cuidaro."
                                                    },
                                                    "external_reference": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Referência que o seu sistema informou ao criar a OS."
                                                    },
                                                    "fiscal_invoice_id": {
                                                        "type": "integer",
                                                        "description": "Id da nota no Cuidaro."
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "const": "nfse"
                                                    },
                                                    "number": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Número da NFS-e devolvido pela prefeitura (`numeroNfse`; nunca o número do RPS). `null` quando a prefeitura não informa."
                                                    },
                                                    "cancellation_requested_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Momento do pedido de cancelamento recusado.",
                                                        "format": "date-time"
                                                    },
                                                    "reason": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Motivo informado pelo município (até 500 caracteres).",
                                                        "maxLength": 500
                                                    }
                                                }
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Recebido. Responda em até 10 s (conexão: 5 s); o corpo é ignorado (até 2.000 caracteres guardados no histórico)."
                    },
                    "default": {
                        "description": "Qualquer outra resposta, redirecionamento (3xx não é seguido), timeout ou erro de conexão é falha: nova tentativa em 1 min, 5 min, 30 min, 2 h, 6 h, 12 h, 24 h, 24 h (9 tentativas); depois `exhausted`."
                    }
                }
            }
        },
        "service_order.invoiced": {
            "post": {
                "operationId": "webhook_service_order_invoiced",
                "tags": [
                    "Webhooks (envios do Cuidaro)"
                ],
                "summary": "OS faturada",
                "description": "A API faturou a OS (`POST /service-orders/{id}/invoice`). Só para OS criadas pela API e só para os endpoints da integração que criou a OS (outra integração da mesma empresa não recebe); endpoint ativo e inscrito no evento. Emitido desde o ECO-API-4b (27/10/2026), depois de a mudança estar gravada, uma vez por transição (deduplique por `Cuidaro-Event-Id`). Sem dado pessoal do cliente.",
                "x-cuidaro-emitted": true,
                "parameters": [
                    {
                        "name": "Cuidaro-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix>,v1=<hex>` — `v1` = HMAC-SHA256 com o segredo do endpoint sobre `\"<t>.<corpo bruto>\"` (esquema do Stripe). Compare em tempo constante e recuse `t` com mais de 300 s de diferença.",
                        "schema": {
                            "type": "string",
                            "pattern": "^t=\\d+,v1=[0-9a-f]{64}$"
                        }
                    },
                    {
                        "name": "Cuidaro-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "Igual a `id` do corpo; não muda entre tentativas nem no reenvio. Use para deduplicar.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "Cuidaro-Event-Type",
                        "in": "header",
                        "required": true,
                        "description": "Igual a `type` do corpo.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "const": "Cuidaro-Webhooks/1.0"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WebhookEnvelope"
                                    },
                                    {
                                        "type": "object",
                                        "properties": {
                                            "type": {
                                                "const": "service_order.invoiced"
                                            },
                                            "data": {
                                                "type": "object",
                                                "required": [
                                                    "service_order_id",
                                                    "external_reference",
                                                    "status",
                                                    "amount",
                                                    "billed_at"
                                                ],
                                                "additionalProperties": false,
                                                "properties": {
                                                    "service_order_id": {
                                                        "type": "integer",
                                                        "description": "Id da OS no Cuidaro."
                                                    },
                                                    "external_reference": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Referência que o seu sistema informou ao criar a OS."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "const": "invoiced"
                                                    },
                                                    "amount": {
                                                        "type": "string",
                                                        "description": "Valor faturado, decimal com 2 casas.",
                                                        "pattern": "^\\d+\\.\\d{2}$"
                                                    },
                                                    "billed_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Data do faturamento.",
                                                        "format": "date-time"
                                                    }
                                                }
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Recebido. Responda em até 10 s (conexão: 5 s); o corpo é ignorado (até 2.000 caracteres guardados no histórico)."
                    },
                    "default": {
                        "description": "Qualquer outra resposta, redirecionamento (3xx não é seguido), timeout ou erro de conexão é falha: nova tentativa em 1 min, 5 min, 30 min, 2 h, 6 h, 12 h, 24 h, 24 h (9 tentativas); depois `exhausted`."
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "oauth2": {
                "type": "oauth2",
                "description": "OAuth 2.0 `client_credentials`. O access token (opaco, 1 h) vai em `Authorization: Bearer <token>`. Token sem o escopo exigido pela operação → 403 `AUTH_SCOPE_INSUFFICIENT`.",
                "flows": {
                    "clientCredentials": {
                        "tokenUrl": "/api/v1/oauth/token",
                        "scopes": {
                            "services:read": "Leitura de serviços, clientes e ordens de serviço",
                            "services:write": "Criação e alteração de clientes e ordens de serviço",
                            "webhooks:manage": "Gerenciar avisos automáticos (webhooks)"
                        }
                    }
                }
            }
        },
        "parameters": {
            "IdempotencyKey": {
                "name": "Idempotency-Key",
                "in": "header",
                "required": true,
                "description": "Chave de idempotência gerada por você para a operação (válida por 24 h, por integração). Operação **comum**: chave \"executando\" há mais de 60 s é considerada abandonada e o reenvio executa de novo. Mesma chave + mesmo corpo → resposta original com `Idempotent-Replayed: true`; corpo diferente → 409 `IDEMPOTENCY_KEY_CONFLICT`. Ausente → 422 `IDEMPOTENCY_KEY_MISSING`; fora do formato → 422 `IDEMPOTENCY_KEY_INVALID`.",
                "schema": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255,
                    "pattern": "^[\\x21-\\x7E]{1,255}$"
                },
                "x-cuidaro-idempotency": "standard"
            },
            "IdempotencyKeyStrict": {
                "name": "Idempotency-Key",
                "in": "header",
                "required": true,
                "description": "Chave de idempotência — operação **estrita** (`api.idempotent:strict`): a chave \"executando\" nunca é retomada antes de vencer (24 h); todo reenvio com ela recebe 409 `IDEMPOTENCY_KEY_IN_PROGRESS`. Consulte o recurso pelo `GET` e, se a operação não aconteceu, reenvie com chave nova. Demais regras iguais às da operação comum.",
                "schema": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255,
                    "pattern": "^[\\x21-\\x7E]{1,255}$"
                },
                "x-cuidaro-idempotency": "strict"
            },
            "Page": {
                "name": "page",
                "in": "query",
                "required": false,
                "schema": {
                    "type": "integer",
                    "minimum": 1,
                    "default": 1
                }
            },
            "PerPage": {
                "name": "per_page",
                "in": "query",
                "required": false,
                "schema": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100,
                    "default": 25
                }
            },
            "ContactId": {
                "name": "contact",
                "in": "path",
                "required": true,
                "description": "Id do cliente.",
                "schema": {
                    "type": "integer"
                }
            },
            "ServiceOrderId": {
                "name": "serviceOrder",
                "in": "path",
                "required": true,
                "description": "Id da ordem de serviço.",
                "schema": {
                    "type": "integer"
                }
            },
            "EndpointId": {
                "name": "endpoint",
                "in": "path",
                "required": true,
                "description": "Id do endpoint de webhook (da integração do token).",
                "schema": {
                    "type": "integer"
                }
            },
            "DeliveryId": {
                "name": "delivery",
                "in": "path",
                "required": true,
                "description": "Id da entrega.",
                "schema": {
                    "type": "integer"
                }
            }
        },
        "headers": {
            "X-RateLimit-Limit": {
                "description": "Limite por minuto em vigor para a integração (leitura 120, escrita 60, ajustáveis pelo suporte).",
                "schema": {
                    "type": "integer"
                }
            },
            "X-RateLimit-Remaining": {
                "description": "Requisições restantes na janela atual.",
                "schema": {
                    "type": "integer"
                }
            },
            "Retry-After": {
                "description": "Segundos a esperar antes de tentar de novo.",
                "schema": {
                    "type": "integer"
                }
            },
            "Idempotent-Replayed": {
                "description": "`true` quando a resposta é a repetição guardada de uma requisição anterior com a mesma `Idempotency-Key`.",
                "schema": {
                    "type": "string",
                    "enum": [
                        "true"
                    ]
                }
            },
            "Location": {
                "description": "URL do recurso criado.",
                "schema": {
                    "type": "string",
                    "format": "uri"
                }
            },
            "WWW-Authenticate": {
                "description": "RFC 6750 §3: `Bearer realm=\"cuidaro-api\"`.",
                "schema": {
                    "type": "string"
                }
            }
        },
        "responses": {
            "Unauthorized": {
                "description": "Token ausente, inválido, revogado ou expirado. Códigos: `AUTH_TOKEN_MISSING`, `AUTH_TOKEN_INVALID`, `AUTH_TOKEN_EXPIRED`.",
                "headers": {
                    "WWW-Authenticate": {
                        "$ref": "#/components/headers/WWW-Authenticate"
                    }
                },
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        }
                    }
                }
            },
            "Forbidden": {
                "description": "Escopo insuficiente ou empresa sem acesso à API. Códigos possíveis: `AUTH_SCOPE_INSUFFICIENT`, `AUTH_TENANT_SUSPENDED`, `AUTH_TENANT_PLAN_WITHOUT_API`, `ACCESS_DENIED`.",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        }
                    }
                }
            },
            "NotFound": {
                "description": "Recurso inexistente, excluído ou de outra empresa/integração. Códigos possíveis: `RESOURCE_NOT_FOUND`.",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        }
                    }
                }
            },
            "PayloadTooLarge": {
                "description": "Corpo acima de 512 KB. Códigos possíveis: `PAYLOAD_TOO_LARGE`.",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        }
                    }
                }
            },
            "TooManyRequests": {
                "description": "Limite de requisições excedido. Código: `RATE_LIMIT_EXCEEDED`.",
                "headers": {
                    "Retry-After": {
                        "$ref": "#/components/headers/Retry-After"
                    },
                    "X-RateLimit-Limit": {
                        "$ref": "#/components/headers/X-RateLimit-Limit"
                    },
                    "X-RateLimit-Remaining": {
                        "$ref": "#/components/headers/X-RateLimit-Remaining"
                    }
                },
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        }
                    }
                }
            },
            "InternalError": {
                "description": "Erro interno, sem mensagem interna nem stack trace. Códigos possíveis: `INTERNAL_ERROR`.",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        }
                    }
                }
            },
            "ValidationFailed": {
                "description": "Dados inválidos — detalhes em `errors`/`error_codes`.",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/ValidationProblem"
                        }
                    }
                }
            }
        },
        "schemas": {
            "ApiErrorCode": {
                "type": "string",
                "description": "Catálogo estável de códigos de erro (`App\\Enums\\ApiErrorCode`). Código publicado nunca é renomeado nem removido; códigos novos podem surgir — trate valor desconhecido como erro genérico do status HTTP. O status, o título e o `type` de cada código estão em `x-cuidaro-error-catalog`.",
                "enum": [
                    "AUTH_CREDENTIALS_INVALID",
                    "AUTH_TOKEN_EXPIRED",
                    "AUTH_TOKEN_MISSING",
                    "AUTH_TOKEN_INVALID",
                    "AUTH_SCOPE_INSUFFICIENT",
                    "AUTH_TENANT_SUSPENDED",
                    "AUTH_TENANT_PLAN_WITHOUT_API",
                    "ACCESS_DENIED",
                    "BAD_REQUEST",
                    "VALIDATION_FAILED",
                    "FIELD_REQUIRED",
                    "FIELD_TYPE_INVALID",
                    "FIELD_MAX_LENGTH",
                    "FIELD_ENUM_INVALID",
                    "FIELD_INVALID",
                    "IDEMPOTENCY_KEY_MISSING",
                    "IDEMPOTENCY_KEY_INVALID",
                    "IDEMPOTENCY_KEY_CONFLICT",
                    "IDEMPOTENCY_KEY_IN_PROGRESS",
                    "RESOURCE_NOT_FOUND",
                    "METHOD_NOT_ALLOWED",
                    "RESOURCE_STATE_CONFLICT",
                    "PLAN_QUOTA_EXCEEDED",
                    "PAYLOAD_TOO_LARGE",
                    "RATE_LIMIT_EXCEEDED",
                    "HTTP_ERROR",
                    "INTERNAL_ERROR",
                    "SERVICE_UNAVAILABLE",
                    "WEBHOOK_URL_NOT_ALLOWED",
                    "RESOURCE_ALREADY_EXISTS",
                    "SETTLEMENT_AMOUNT_MISMATCH",
                    "EXTERNAL_SETTLEMENT_NOT_ALLOWED",
                    "EXTERNAL_SETTLEMENT_ACCOUNT_MISSING"
                ],
                "x-cuidaro-error-catalog": [
                    {
                        "code": "AUTH_CREDENTIALS_INVALID",
                        "status": 401,
                        "title": "Invalid Client Credentials",
                        "type": "https://cuidaro.com.br/errors/auth-credentials-invalid"
                    },
                    {
                        "code": "AUTH_TOKEN_EXPIRED",
                        "status": 401,
                        "title": "Access Token Expired",
                        "type": "https://cuidaro.com.br/errors/auth-token-expired"
                    },
                    {
                        "code": "AUTH_TOKEN_MISSING",
                        "status": 401,
                        "title": "Access Token Missing",
                        "type": "https://cuidaro.com.br/errors/auth-token-missing"
                    },
                    {
                        "code": "AUTH_TOKEN_INVALID",
                        "status": 401,
                        "title": "Invalid Access Token",
                        "type": "https://cuidaro.com.br/errors/auth-token-invalid"
                    },
                    {
                        "code": "AUTH_SCOPE_INSUFFICIENT",
                        "status": 403,
                        "title": "Insufficient Scope",
                        "type": "https://cuidaro.com.br/errors/auth-scope-insufficient"
                    },
                    {
                        "code": "AUTH_TENANT_SUSPENDED",
                        "status": 403,
                        "title": "Tenant Suspended",
                        "type": "https://cuidaro.com.br/errors/auth-tenant-suspended"
                    },
                    {
                        "code": "AUTH_TENANT_PLAN_WITHOUT_API",
                        "status": 403,
                        "title": "Plan Without API Access",
                        "type": "https://cuidaro.com.br/errors/auth-tenant-plan-without-api"
                    },
                    {
                        "code": "ACCESS_DENIED",
                        "status": 403,
                        "title": "Access Denied",
                        "type": "https://cuidaro.com.br/errors/access-denied"
                    },
                    {
                        "code": "BAD_REQUEST",
                        "status": 400,
                        "title": "Bad Request",
                        "type": "https://cuidaro.com.br/errors/bad-request"
                    },
                    {
                        "code": "VALIDATION_FAILED",
                        "status": 422,
                        "title": "Validation Failed",
                        "type": "https://cuidaro.com.br/errors/validation-failed"
                    },
                    {
                        "code": "FIELD_REQUIRED",
                        "status": 422,
                        "title": "Field Required",
                        "type": "https://cuidaro.com.br/errors/field-required"
                    },
                    {
                        "code": "FIELD_TYPE_INVALID",
                        "status": 422,
                        "title": "Field Type Invalid",
                        "type": "https://cuidaro.com.br/errors/field-type-invalid"
                    },
                    {
                        "code": "FIELD_MAX_LENGTH",
                        "status": 422,
                        "title": "Field Too Long",
                        "type": "https://cuidaro.com.br/errors/field-max-length"
                    },
                    {
                        "code": "FIELD_ENUM_INVALID",
                        "status": 422,
                        "title": "Field Value Not Allowed",
                        "type": "https://cuidaro.com.br/errors/field-enum-invalid"
                    },
                    {
                        "code": "FIELD_INVALID",
                        "status": 422,
                        "title": "Field Invalid",
                        "type": "https://cuidaro.com.br/errors/field-invalid"
                    },
                    {
                        "code": "IDEMPOTENCY_KEY_MISSING",
                        "status": 422,
                        "title": "Idempotency Key Missing",
                        "type": "https://cuidaro.com.br/errors/idempotency-key-missing"
                    },
                    {
                        "code": "IDEMPOTENCY_KEY_INVALID",
                        "status": 422,
                        "title": "Idempotency Key Invalid",
                        "type": "https://cuidaro.com.br/errors/idempotency-key-invalid"
                    },
                    {
                        "code": "IDEMPOTENCY_KEY_CONFLICT",
                        "status": 409,
                        "title": "Idempotency Key Conflict",
                        "type": "https://cuidaro.com.br/errors/idempotency-key-conflict"
                    },
                    {
                        "code": "IDEMPOTENCY_KEY_IN_PROGRESS",
                        "status": 409,
                        "title": "Idempotency Key In Progress",
                        "type": "https://cuidaro.com.br/errors/idempotency-key-in-progress"
                    },
                    {
                        "code": "RESOURCE_NOT_FOUND",
                        "status": 404,
                        "title": "Resource Not Found",
                        "type": "https://cuidaro.com.br/errors/resource-not-found"
                    },
                    {
                        "code": "METHOD_NOT_ALLOWED",
                        "status": 405,
                        "title": "Method Not Allowed",
                        "type": "https://cuidaro.com.br/errors/method-not-allowed"
                    },
                    {
                        "code": "RESOURCE_STATE_CONFLICT",
                        "status": 409,
                        "title": "Resource State Conflict",
                        "type": "https://cuidaro.com.br/errors/resource-state-conflict"
                    },
                    {
                        "code": "PLAN_QUOTA_EXCEEDED",
                        "status": 409,
                        "title": "Plan Quota Exceeded",
                        "type": "https://cuidaro.com.br/errors/plan-quota-exceeded"
                    },
                    {
                        "code": "PAYLOAD_TOO_LARGE",
                        "status": 413,
                        "title": "Payload Too Large",
                        "type": "https://cuidaro.com.br/errors/payload-too-large"
                    },
                    {
                        "code": "RATE_LIMIT_EXCEEDED",
                        "status": 429,
                        "title": "Rate Limit Exceeded",
                        "type": "https://cuidaro.com.br/errors/rate-limit-exceeded"
                    },
                    {
                        "code": "HTTP_ERROR",
                        "status": 400,
                        "title": "HTTP Error",
                        "type": "https://cuidaro.com.br/errors/http-error"
                    },
                    {
                        "code": "INTERNAL_ERROR",
                        "status": 500,
                        "title": "Internal Server Error",
                        "type": "https://cuidaro.com.br/errors/internal-error"
                    },
                    {
                        "code": "SERVICE_UNAVAILABLE",
                        "status": 503,
                        "title": "Service Unavailable",
                        "type": "https://cuidaro.com.br/errors/service-unavailable"
                    },
                    {
                        "code": "WEBHOOK_URL_NOT_ALLOWED",
                        "status": 422,
                        "title": "Webhook URL Not Allowed",
                        "type": "https://cuidaro.com.br/errors/webhook-url-not-allowed"
                    },
                    {
                        "code": "RESOURCE_ALREADY_EXISTS",
                        "status": 409,
                        "title": "Resource Already Exists",
                        "type": "https://cuidaro.com.br/errors/resource-already-exists"
                    },
                    {
                        "code": "SETTLEMENT_AMOUNT_MISMATCH",
                        "status": 422,
                        "title": "Settlement Amount Mismatch",
                        "type": "https://cuidaro.com.br/errors/settlement-amount-mismatch"
                    },
                    {
                        "code": "EXTERNAL_SETTLEMENT_NOT_ALLOWED",
                        "status": 422,
                        "title": "External Settlement Not Allowed",
                        "type": "https://cuidaro.com.br/errors/external-settlement-not-allowed"
                    },
                    {
                        "code": "EXTERNAL_SETTLEMENT_ACCOUNT_MISSING",
                        "status": 422,
                        "title": "External Settlement Account Missing",
                        "type": "https://cuidaro.com.br/errors/external-settlement-account-missing"
                    }
                ]
            },
            "Problem": {
                "type": "object",
                "description": "RFC 7807 (Problem Details), `Content-Type: application/problem+json`.",
                "required": [
                    "type",
                    "title",
                    "status",
                    "detail",
                    "instance",
                    "code"
                ],
                "properties": {
                    "type": {
                        "type": "string",
                        "format": "uri",
                        "description": "`https://cuidaro.com.br/errors/{slug}` — ainda não é endereço navegável."
                    },
                    "title": {
                        "type": "string",
                        "description": "Título curto e estável por código (inglês)."
                    },
                    "status": {
                        "type": "integer"
                    },
                    "detail": {
                        "type": "string",
                        "description": "Texto para pessoas, em pt-BR. Pode mudar; não use para lógica."
                    },
                    "instance": {
                        "type": "string",
                        "description": "Caminho da requisição (ex.: `/api/v1/me`)."
                    },
                    "code": {
                        "$ref": "#/components/schemas/ApiErrorCode"
                    },
                    "metric": {
                        "type": "string",
                        "description": "Só em `PLAN_QUOTA_EXCEEDED`: métrica do plano atingida."
                    },
                    "limit": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Só em `PLAN_QUOTA_EXCEEDED`: limite do plano."
                    },
                    "existing_resource_id": {
                        "type": "integer",
                        "description": "Só em `RESOURCE_ALREADY_EXISTS`: id do recurso que já existe."
                    },
                    "expected_amount": {
                        "type": "string",
                        "pattern": "^-?\\d+\\.\\d{2}$",
                        "description": "Só em `SETTLEMENT_AMOUNT_MISMATCH`: total da OS.",
                        "examples": [
                            "149.90"
                        ]
                    },
                    "received_amount": {
                        "type": "string",
                        "pattern": "^-?\\d+\\.\\d{2}$",
                        "description": "Só em `SETTLEMENT_AMOUNT_MISMATCH`: valor recebido em `settlement.amount`.",
                        "examples": [
                            "149.90"
                        ]
                    },
                    "service_order_status": {
                        "type": "string",
                        "description": "Só no `RESOURCE_STATE_CONFLICT` do faturamento: status público atual da OS."
                    }
                }
            },
            "ValidationProblem": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/Problem"
                    },
                    {
                        "type": "object",
                        "description": "Erro 422. `code` é `VALIDATION_FAILED` (validação de campos) ou um código de idempotência/regra (`IDEMPOTENCY_KEY_MISSING`, `IDEMPOTENCY_KEY_INVALID`, `SETTLEMENT_AMOUNT_MISMATCH`, `EXTERNAL_SETTLEMENT_NOT_ALLOWED`, `EXTERNAL_SETTLEMENT_ACCOUNT_MISSING`) — nesses últimos `errors`/`error_codes` não vêm.",
                        "properties": {
                            "errors": {
                                "type": "object",
                                "description": "Mensagens por campo (pt-BR).",
                                "additionalProperties": {
                                    "type": "array",
                                    "items": {
                                        "type": "string"
                                    }
                                }
                            },
                            "error_codes": {
                                "type": "object",
                                "description": "Códigos estáveis por campo: `FIELD_REQUIRED`, `FIELD_TYPE_INVALID`, `FIELD_MAX_LENGTH`, `FIELD_ENUM_INVALID`, `FIELD_INVALID`, `WEBHOOK_URL_NOT_ALLOWED`.",
                                "additionalProperties": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/ApiErrorCode"
                                    }
                                }
                            }
                        }
                    }
                ]
            },
            "OAuthTokenRequest": {
                "type": "object",
                "required": [
                    "grant_type",
                    "client_id",
                    "client_secret"
                ],
                "properties": {
                    "grant_type": {
                        "type": "string",
                        "enum": [
                            "client_credentials"
                        ]
                    },
                    "client_id": {
                        "type": "string",
                        "maxLength": 64,
                        "description": "Identificador público (`cli_...`)."
                    },
                    "client_secret": {
                        "type": "string",
                        "maxLength": 255,
                        "description": "Segredo (`cs_...`), exibido só na criação/troca."
                    },
                    "scope": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 500,
                        "description": "Escopos separados por espaço, contidos nos da integração. Ausente/vazio = todos os escopos da integração. Escopo desconhecido → 422 `FIELD_ENUM_INVALID`."
                    }
                }
            },
            "OAuthTokenResponse": {
                "type": "object",
                "required": [
                    "access_token",
                    "token_type",
                    "expires_in",
                    "scope"
                ],
                "properties": {
                    "access_token": {
                        "type": "string",
                        "description": "Token opaco (`cat_...`)."
                    },
                    "token_type": {
                        "type": "string",
                        "const": "Bearer"
                    },
                    "expires_in": {
                        "type": "integer",
                        "description": "Validade em segundos (3600).",
                        "examples": [
                            3600
                        ]
                    },
                    "scope": {
                        "type": "string",
                        "description": "Escopos concedidos, separados por espaço."
                    }
                }
            },
            "Me": {
                "type": "object",
                "required": [
                    "integrator",
                    "token",
                    "company"
                ],
                "properties": {
                    "integrator": {
                        "type": "object",
                        "required": [
                            "name",
                            "client_id",
                            "scopes"
                        ],
                        "properties": {
                            "name": {
                                "type": "string"
                            },
                            "client_id": {
                                "type": "string"
                            },
                            "scopes": {
                                "type": "array",
                                "items": {
                                    "$ref": "#/components/schemas/Scope"
                                }
                            }
                        }
                    },
                    "token": {
                        "type": "object",
                        "required": [
                            "scopes",
                            "expires_at"
                        ],
                        "properties": {
                            "scopes": {
                                "type": "array",
                                "items": {
                                    "$ref": "#/components/schemas/Scope"
                                }
                            },
                            "expires_at": {
                                "type": "string",
                                "format": "date-time"
                            }
                        }
                    },
                    "company": {
                        "type": "object",
                        "required": [
                            "id",
                            "name"
                        ],
                        "properties": {
                            "id": {
                                "type": "integer"
                            },
                            "name": {
                                "type": "string"
                            }
                        }
                    }
                }
            },
            "Scope": {
                "type": "string",
                "enum": [
                    "services:read",
                    "services:write",
                    "webhooks:manage"
                ]
            },
            "ContactAddressInput": {
                "type": [
                    "object",
                    "null"
                ],
                "properties": {
                    "zip_code": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 10
                    },
                    "street": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 255
                    },
                    "number": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 20
                    },
                    "complement": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 100
                    },
                    "neighborhood": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 100
                    },
                    "city": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 100
                    },
                    "state": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "pattern": "^[A-Za-z]{2}$",
                        "description": "UF com 2 letras (normalizada para maiúsculas). Obrigatória quando vier `city_ibge_code`."
                    },
                    "city_ibge_code": {
                        "oneOf": [
                            {
                                "type": "string",
                                "pattern": "^\\d{7}$"
                            },
                            {
                                "type": "integer"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "Código IBGE do município (7 dígitos; número também é aceito). Precisa pertencer à UF informada — senão 422."
                    }
                }
            },
            "ContactUpsertRequest": {
                "type": "object",
                "required": [
                    "document",
                    "name"
                ],
                "description": "Campos desconhecidos são ignorados.",
                "properties": {
                    "document": {
                        "type": "string",
                        "maxLength": 20,
                        "description": "CPF ou CNPJ válido, com ou sem pontuação. Chave do upsert."
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "trading_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 255
                    },
                    "email": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "email",
                        "maxLength": 255
                    },
                    "nfe_email": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "email",
                        "maxLength": 255
                    },
                    "phone": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 20
                    },
                    "mobile": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 20
                    },
                    "state_registration": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 50
                    },
                    "address": {
                        "$ref": "#/components/schemas/ContactAddressInput"
                    }
                }
            },
            "Contact": {
                "type": "object",
                "required": [
                    "id",
                    "types",
                    "status",
                    "person_type",
                    "name",
                    "trading_name",
                    "document",
                    "email",
                    "nfe_email",
                    "phone",
                    "mobile",
                    "state_registration",
                    "address",
                    "created_at",
                    "updated_at"
                ],
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "types": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Valores conhecidos: `customer`, `supplier`, `employee`."
                    },
                    "status": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Valores conhecidos: `active`, `inactive`, `blocked`."
                    },
                    "person_type": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "`individual` (CPF) ou `company` (CNPJ)."
                    },
                    "name": {
                        "type": "string"
                    },
                    "trading_name": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "document": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Só dígitos (e letras, no CNPJ alfanumérico)."
                    },
                    "email": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "nfe_email": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "phone": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "mobile": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "state_registration": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "address": {
                        "type": "object",
                        "required": [
                            "zip_code",
                            "street",
                            "number",
                            "complement",
                            "neighborhood",
                            "city",
                            "state",
                            "city_ibge_code"
                        ],
                        "properties": {
                            "zip_code": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            },
                            "street": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            },
                            "number": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            },
                            "complement": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            },
                            "neighborhood": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            },
                            "city": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            },
                            "state": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            },
                            "city_ibge_code": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            }
                        }
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    }
                }
            },
            "ServiceOrderItemInput": {
                "type": "object",
                "required": [
                    "service_id",
                    "quantity",
                    "unit_price"
                ],
                "properties": {
                    "service_id": {
                        "type": "integer",
                        "description": "Serviço ativo do catálogo da empresa (`GET /services`). Inexistente, inativo ou de outra empresa → 422 `FIELD_INVALID`."
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 300,
                        "description": "Padrão: nome do serviço."
                    },
                    "quantity": {
                        "oneOf": [
                            {
                                "type": "number",
                                "minimum": 0.001,
                                "maximum": 9999999.999
                            },
                            {
                                "type": "string",
                                "pattern": "^\\d+(\\.\\d{1,3})?$"
                            }
                        ],
                        "description": "Até 3 casas decimais, de 0.001 a 9999999.999."
                    },
                    "unit_price": {
                        "oneOf": [
                            {
                                "type": "number",
                                "minimum": 0.01,
                                "maximum": 99999999.99
                            },
                            {
                                "type": "string",
                                "pattern": "^\\d+(\\.\\d{1,2})?$"
                            }
                        ],
                        "description": "Número ou string decimal com até 2 casas, de 0.01 a 99999999.99."
                    }
                }
            },
            "ServiceOrderCreateRequest": {
                "type": "object",
                "required": [
                    "contact_id",
                    "external_reference",
                    "items"
                ],
                "properties": {
                    "contact_id": {
                        "type": "integer",
                        "description": "Contato do tipo cliente, não excluído, da empresa do token. Senão 422 `FIELD_INVALID`."
                    },
                    "external_reference": {
                        "type": "string",
                        "maxLength": 120,
                        "pattern": "^[\\x21-\\x7E]+$",
                        "description": "Referência do pedido no seu sistema — única por empresa (repetir → 409 `RESOURCE_ALREADY_EXISTS`)."
                    },
                    "notes": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 2000
                    },
                    "items": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 50,
                        "items": {
                            "$ref": "#/components/schemas/ServiceOrderItemInput"
                        }
                    }
                }
            },
            "ServiceOrderInvoiceRequest": {
                "type": "object",
                "required": [
                    "settlement"
                ],
                "properties": {
                    "settlement": {
                        "type": "object",
                        "required": [
                            "type",
                            "paid_at",
                            "method",
                            "gateway",
                            "gateway_reference",
                            "amount"
                        ],
                        "properties": {
                            "type": {
                                "type": "string",
                                "enum": [
                                    "external"
                                ],
                                "description": "Só `external` nesta versão (pagamento já recebido fora do Cuidaro)."
                            },
                            "paid_at": {
                                "type": "string",
                                "format": "date",
                                "description": "`Y-m-d`, não futura."
                            },
                            "method": {
                                "type": "string",
                                "enum": [
                                    "pix",
                                    "boleto",
                                    "credit_card",
                                    "debit_card",
                                    "bank_transfer"
                                ]
                            },
                            "gateway": {
                                "type": "string",
                                "maxLength": 40,
                                "pattern": "^[a-z0-9_-]+$",
                                "examples": [
                                    "asaas"
                                ]
                            },
                            "gateway_reference": {
                                "type": "string",
                                "maxLength": 120,
                                "pattern": "^[\\x21-\\x7E]+$",
                                "description": "Id do pagamento no gateway. `gateway` + `gateway_reference` quitam uma única OS."
                            },
                            "amount": {
                                "oneOf": [
                                    {
                                        "type": "number",
                                        "minimum": 0.01,
                                        "maximum": 99999999.99
                                    },
                                    {
                                        "type": "string",
                                        "pattern": "^\\d+(\\.\\d{1,2})?$"
                                    }
                                ],
                                "description": "Igual ao centavo ao `total` da OS — senão 422 `SETTLEMENT_AMOUNT_MISMATCH`."
                            }
                        }
                    }
                }
            },
            "ServiceOrderCancelRequest": {
                "type": "object",
                "properties": {
                    "reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 500
                    }
                }
            },
            "ServiceOrderStatus": {
                "type": "string",
                "description": "Vocabulário público da OS. `unknown` quando o estado interno não tem correspondência.",
                "enum": [
                    "open",
                    "in_progress",
                    "awaiting_invoice",
                    "invoiced",
                    "closed",
                    "cancelled",
                    "unknown"
                ]
            },
            "ServiceOrder": {
                "type": "object",
                "required": [
                    "id",
                    "number",
                    "status",
                    "external_reference",
                    "contact_id",
                    "items",
                    "total",
                    "receivables",
                    "settlement",
                    "fiscal",
                    "created_at",
                    "billed_at",
                    "updated_at"
                ],
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "number": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "status": {
                        "$ref": "#/components/schemas/ServiceOrderStatus"
                    },
                    "external_reference": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "contact_id": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Sem dado pessoal na OS — use `GET /contacts/{contact}`."
                    },
                    "items": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "required": [
                                "id",
                                "service_id",
                                "description",
                                "quantity",
                                "unit_price",
                                "total"
                            ],
                            "properties": {
                                "id": {
                                    "type": "integer"
                                },
                                "service_id": {
                                    "type": [
                                        "integer",
                                        "null"
                                    ]
                                },
                                "description": {
                                    "type": [
                                        "string",
                                        "null"
                                    ]
                                },
                                "quantity": {
                                    "type": "string",
                                    "pattern": "^\\d+\\.\\d{3}$",
                                    "description": "String decimal com 3 casas."
                                },
                                "unit_price": {
                                    "type": "string",
                                    "pattern": "^-?\\d+\\.\\d{2}$",
                                    "description": "Valor monetário em string decimal com 2 casas.",
                                    "examples": [
                                        "149.90"
                                    ]
                                },
                                "total": {
                                    "type": "string",
                                    "pattern": "^-?\\d+\\.\\d{2}$",
                                    "description": "Valor monetário em string decimal com 2 casas.",
                                    "examples": [
                                        "149.90"
                                    ]
                                }
                            }
                        }
                    },
                    "total": {
                        "type": "string",
                        "pattern": "^-?\\d+\\.\\d{2}$",
                        "description": "Valor monetário em string decimal com 2 casas.",
                        "examples": [
                            "149.90"
                        ]
                    },
                    "receivables": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "required": [
                                "id",
                                "status",
                                "amount",
                                "amount_paid",
                                "due_date",
                                "payment_date"
                            ],
                            "properties": {
                                "id": {
                                    "type": "integer"
                                },
                                "status": {
                                    "type": "string",
                                    "enum": [
                                        "pending",
                                        "overdue",
                                        "paid",
                                        "cancelled",
                                        "unknown"
                                    ]
                                },
                                "amount": {
                                    "type": "string",
                                    "pattern": "^-?\\d+\\.\\d{2}$",
                                    "description": "Valor monetário em string decimal com 2 casas.",
                                    "examples": [
                                        "149.90"
                                    ]
                                },
                                "amount_paid": {
                                    "type": "string",
                                    "pattern": "^-?\\d+\\.\\d{2}$",
                                    "description": "Valor monetário em string decimal com 2 casas.",
                                    "examples": [
                                        "149.90"
                                    ]
                                },
                                "due_date": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "format": "date"
                                },
                                "payment_date": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "format": "date"
                                }
                            }
                        }
                    },
                    "settlement": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "Pagamento externo informado no faturamento pela API, ou `null`.",
                        "required": [
                            "type",
                            "gateway",
                            "gateway_reference",
                            "method",
                            "paid_at",
                            "amount",
                            "reversed_at"
                        ],
                        "properties": {
                            "type": {
                                "type": "string",
                                "const": "external"
                            },
                            "gateway": {
                                "type": "string"
                            },
                            "gateway_reference": {
                                "type": "string"
                            },
                            "method": {
                                "type": "string"
                            },
                            "paid_at": {
                                "type": "string",
                                "format": "date"
                            },
                            "amount": {
                                "type": "string",
                                "pattern": "^-?\\d+\\.\\d{2}$",
                                "description": "Valor monetário em string decimal com 2 casas.",
                                "examples": [
                                    "149.90"
                                ]
                            },
                            "reversed_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "format": "date-time"
                            }
                        }
                    },
                    "fiscal": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "NFS-e mais recente da OS (somente leitura), ou `null`.",
                        "required": [
                            "type",
                            "status",
                            "number",
                            "issued_at",
                            "cancellation_requested_at",
                            "cancelled_at",
                            "pdf_url",
                            "xml_url"
                        ],
                        "properties": {
                            "type": {
                                "type": "string",
                                "const": "nfse"
                            },
                            "status": {
                                "type": "string",
                                "enum": [
                                    "pending",
                                    "processing",
                                    "issued",
                                    "rejected",
                                    "cancelled",
                                    "cancellation_pending",
                                    "cancellation_error"
                                ]
                            },
                            "number": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "`null` até o provedor informar."
                            },
                            "issued_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "format": "date-time"
                            },
                            "cancellation_requested_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "format": "date-time"
                            },
                            "cancelled_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "format": "date-time"
                            },
                            "pdf_url": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "format": "uri",
                                "description": "Link assinado do Cuidaro, válido por 24 h; só para nota emitida ou cancelada."
                            },
                            "xml_url": {
                                "type": "null",
                                "description": "Ainda não oferecido (sempre `null`)."
                            }
                        }
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "billed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    }
                }
            },
            "ServiceCatalogItem": {
                "type": "object",
                "required": [
                    "id",
                    "name",
                    "description",
                    "unit",
                    "unit_price",
                    "service_code_lc116",
                    "nfse_ready"
                ],
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "unit": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "unit_price": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "pattern": "^-?\\d+\\.\\d{2}$",
                        "description": "Valor monetário em string decimal com 2 casas.",
                        "examples": [
                            "149.90"
                        ]
                    },
                    "service_code_lc116": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "nfse_ready": {
                        "type": "boolean",
                        "description": "O serviço tem os dados fiscais mínimos (código municipal) para a NFS-e integrada."
                    }
                }
            },
            "PaginationMeta": {
                "type": "object",
                "required": [
                    "current_page",
                    "per_page",
                    "total",
                    "last_page"
                ],
                "properties": {
                    "current_page": {
                        "type": "integer"
                    },
                    "per_page": {
                        "type": "integer"
                    },
                    "total": {
                        "type": "integer"
                    },
                    "last_page": {
                        "type": "integer"
                    }
                }
            },
            "PaginationLinks": {
                "type": "object",
                "required": [
                    "first",
                    "last",
                    "prev",
                    "next"
                ],
                "properties": {
                    "first": {
                        "type": "string",
                        "format": "uri"
                    },
                    "last": {
                        "type": "string",
                        "format": "uri"
                    },
                    "prev": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "uri"
                    },
                    "next": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "uri"
                    }
                }
            },
            "WebhookSubscribableEvent": {
                "type": "string",
                "description": "Eventos aceitos em `events` (o `ping` fica de fora — é enviado só quando pedido).",
                "enum": [
                    "fiscal_invoice.issued",
                    "fiscal_invoice.cancelled",
                    "fiscal_invoice.cancellation_rejected",
                    "service_order.invoiced"
                ]
            },
            "WebhookEndpoint": {
                "type": "object",
                "required": [
                    "id",
                    "url",
                    "events",
                    "description",
                    "is_active",
                    "created_at",
                    "updated_at"
                ],
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "url": {
                        "type": "string",
                        "format": "uri"
                    },
                    "events": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/WebhookSubscribableEvent"
                        }
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    }
                }
            },
            "WebhookEndpointWithSecret": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/WebhookEndpoint"
                    },
                    {
                        "type": "object",
                        "required": [
                            "secret"
                        ],
                        "properties": {
                            "secret": {
                                "type": "string",
                                "description": "Segredo de assinatura (`whsec_...`). Exibido só aqui e na troca de segredo."
                            }
                        }
                    }
                ]
            },
            "WebhookEndpointCreateRequest": {
                "type": "object",
                "required": [
                    "url",
                    "events"
                ],
                "properties": {
                    "url": {
                        "type": "string",
                        "maxLength": 2048,
                        "format": "uri",
                        "description": "Só `https://`, sem usuário/senha, resolvendo apenas para IPs públicos. Recusa → 422 com `error_codes.url = [\"WEBHOOK_URL_NOT_ALLOWED\"]`."
                    },
                    "events": {
                        "type": "array",
                        "minItems": 1,
                        "uniqueItems": true,
                        "items": {
                            "$ref": "#/components/schemas/WebhookSubscribableEvent"
                        }
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 255
                    },
                    "is_active": {
                        "type": "boolean",
                        "default": true
                    }
                }
            },
            "WebhookEndpointUpdateRequest": {
                "type": "object",
                "description": "Só os campos enviados são alterados.",
                "properties": {
                    "url": {
                        "type": "string",
                        "maxLength": 2048,
                        "format": "uri",
                        "description": "Mesmas regras do cadastro."
                    },
                    "events": {
                        "type": "array",
                        "minItems": 1,
                        "uniqueItems": true,
                        "items": {
                            "$ref": "#/components/schemas/WebhookSubscribableEvent"
                        }
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 255
                    },
                    "is_active": {
                        "type": "boolean"
                    }
                }
            },
            "WebhookDeliveryStatus": {
                "type": "string",
                "description": "`pending` aguardando tentativa; `failed` com nova tentativa em `next_attempt_at`; `succeeded` (terminal); `exhausted` sem mais tentativas (terminal).",
                "enum": [
                    "pending",
                    "failed",
                    "succeeded",
                    "exhausted"
                ]
            },
            "WebhookDelivery": {
                "type": "object",
                "required": [
                    "id",
                    "webhook_endpoint_id",
                    "event_id",
                    "event_type",
                    "status",
                    "attempt",
                    "response_status",
                    "response_body",
                    "duration_ms",
                    "error",
                    "next_attempt_at",
                    "last_attempted_at",
                    "delivered_at",
                    "created_at",
                    "payload"
                ],
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "webhook_endpoint_id": {
                        "type": "integer"
                    },
                    "event_id": {
                        "type": "string",
                        "description": "`evt_...` — igual ao `Cuidaro-Event-Id`; não muda entre tentativas nem no reenvio."
                    },
                    "event_type": {
                        "type": "string"
                    },
                    "status": {
                        "$ref": "#/components/schemas/WebhookDeliveryStatus"
                    },
                    "attempt": {
                        "type": "integer"
                    },
                    "response_status": {
                        "type": [
                            "integer",
                            "null"
                        ]
                    },
                    "response_body": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Até 2.000 caracteres da resposta do seu endpoint."
                    },
                    "duration_ms": {
                        "type": [
                            "integer",
                            "null"
                        ]
                    },
                    "error": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "next_attempt_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "`null` em status terminal."
                    },
                    "last_attempted_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "delivered_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "payload": {
                        "$ref": "#/components/schemas/WebhookEnvelope"
                    }
                }
            },
            "WebhookEnvelope": {
                "type": "object",
                "description": "Corpo de todo envio de webhook (`App\\Services\\Api\\Webhooks\\ApiWebhookEnvelope`).",
                "required": [
                    "id",
                    "api_version",
                    "schema_version",
                    "type",
                    "created_at",
                    "data"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "pattern": "^evt_[0-9a-z]{26}$",
                        "description": "`evt_` + ULID em minúsculas. Chave de deduplicação: igual ao cabeçalho `Cuidaro-Event-Id`."
                    },
                    "api_version": {
                        "type": "string",
                        "const": "2026-10-26"
                    },
                    "schema_version": {
                        "type": "string",
                        "const": "1"
                    },
                    "type": {
                        "type": "string",
                        "enum": [
                            "ping",
                            "fiscal_invoice.issued",
                            "fiscal_invoice.cancelled",
                            "fiscal_invoice.cancellation_rejected",
                            "service_order.invoiced"
                        ]
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "UTC, sufixo `Z`."
                    },
                    "data": {
                        "type": "object",
                        "description": "Conteúdo específico do evento (ver `webhooks`)."
                    }
                }
            }
        }
    }
}
