{
  "openapi": "3.1.0",
  "info": {
    "title": "Hojas de Ruta API",
    "version": "1.0.0",
    "description": "API de organización para conectar ERP y programas de oficina con Hojas de Ruta. Las respuestas HTTP son autoritativas y permiten operar sin webhooks. Todas las fechas son RFC 3339 y los errores usan application/problem+json."
  },
  "servers": [
    {
      "url": "https://hojasderuta.com/api/v1",
      "description": "Producción"
    }
  ],
  "security": [
    {
      "ApiKey": []
    }
  ],
  "tags": [
    {
      "name": "Cuenta"
    },
    {
      "name": "Datos maestros"
    },
    {
      "name": "Documentos"
    },
    {
      "name": "Webhooks",
      "description": "Automatización opcional para recibir cambios realizados fuera del ERP. Ninguna operación necesita un webhook."
    }
  ],
  "paths": {
    "/account": {
      "get": {
        "tags": ["Cuenta"],
        "summary": "Consultar organización y plan",
        "operationId": "getAccount",
        "responses": {
          "200": {
            "description": "Cuenta efectiva",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/usage": {
      "get": {
        "tags": ["Cuenta"],
        "summary": "Consultar cuotas y consumo",
        "operationId": "getUsage",
        "responses": {
          "200": {
            "description": "Uso efectivo del plan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/capabilities": {
      "get": {
        "tags": ["Cuenta"],
        "summary": "Consultar permisos efectivos",
        "operationId": "getCapabilities",
        "responses": {
          "200": {
            "description": "Scopes y capacidades",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CapabilitiesResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/drivers": {
      "get": {
        "tags": ["Datos maestros"],
        "summary": "Listar conductores",
        "description": "Devuelve una página ordenada por actualización. updatedAfter permite recuperar altas y cambios, pero no representa eliminaciones mediante tombstones.",
        "operationId": "listDrivers",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/UpdatedAfter"
          },
          {
            "$ref": "#/components/parameters/ExternalId"
          },
          {
            "name": "email",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "email"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Página de conductores",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DriverListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          }
        }
      },
      "post": {
        "tags": ["Datos maestros"],
        "summary": "Crear conductor",
        "description": "Crea una cuenta activa de conductor. Consume una plaza del plan, requiere una clave de idempotencia y devuelve el recurso confirmado con ETag. No necesita webhook.",
        "operationId": "createDriver",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DriverInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/DriverRecord"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          }
        }
      }
    },
    "/drivers/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ResourceId"
        }
      ],
      "get": {
        "tags": ["Datos maestros"],
        "summary": "Consultar conductor",
        "operationId": "getDriver",
        "responses": {
          "200": {
            "$ref": "#/components/responses/DriverRecord"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": ["Datos maestros"],
        "summary": "Actualizar conductor",
        "description": "Actualiza los campos enviados y devuelve el conductor confirmado con un ETag nuevo.",
        "operationId": "updateDriver",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DriverPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/DriverRecord"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/VersionMismatch"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          }
        }
      },
      "delete": {
        "tags": ["Datos maestros"],
        "summary": "Eliminar conductor",
        "description": "Elimina la cuenta y revoca sus sesiones. La cuenta administradora nunca puede eliminarse por API. Las listas incrementales no generan tombstones para esta baja.",
        "operationId": "deleteDriver",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "204": {
            "description": "Conductor eliminado"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "412": {
            "$ref": "#/components/responses/VersionMismatch"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          }
        }
      }
    },
    "/drivers/{id}/password": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ResourceId"
        }
      ],
      "post": {
        "tags": ["Datos maestros"],
        "summary": "Cambiar contraseña del conductor",
        "description": "Establece una contraseña nueva, revoca todas las sesiones del conductor y devuelve el recurso con un ETag nuevo. La contraseña nunca se devuelve.",
        "operationId": "updateDriverPassword",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DriverPasswordInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/DriverRecord"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "412": {
            "$ref": "#/components/responses/VersionMismatch"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          }
        }
      }
    },
    "/companies": {
      "get": {
        "tags": ["Datos maestros"],
        "summary": "Listar empresas",
        "operationId": "listCompanies",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/UpdatedAfter"
          },
          {
            "$ref": "#/components/parameters/ExternalId"
          }
        ],
        "responses": {
          "200": {
            "description": "Página de empresas",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          }
        }
      },
      "post": {
        "tags": ["Datos maestros"],
        "summary": "Crear empresa",
        "operationId": "createCompany",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompanyInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/CompanyRecord"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          }
        }
      }
    },
    "/companies/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ResourceId"
        }
      ],
      "get": {
        "tags": ["Datos maestros"],
        "summary": "Consultar empresa",
        "operationId": "getCompany",
        "responses": {
          "200": {
            "$ref": "#/components/responses/CompanyRecord"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": ["Datos maestros"],
        "summary": "Actualizar empresa",
        "operationId": "updateCompany",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompanyPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/CompanyRecord"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/VersionMismatch"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          }
        }
      },
      "delete": {
        "tags": ["Datos maestros"],
        "summary": "Eliminar empresa",
        "operationId": "deleteCompany",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "204": {
            "description": "Empresa eliminada"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "412": {
            "$ref": "#/components/responses/VersionMismatch"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          }
        }
      }
    },
    "/vehicles": {
      "get": {
        "tags": ["Datos maestros"],
        "summary": "Listar vehículos",
        "operationId": "listVehicles",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/UpdatedAfter"
          },
          {
            "$ref": "#/components/parameters/ExternalId"
          }
        ],
        "responses": {
          "200": {
            "description": "Página de vehículos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VehicleListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          }
        }
      },
      "post": {
        "tags": ["Datos maestros"],
        "summary": "Crear vehículo",
        "operationId": "createVehicle",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VehicleInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/VehicleRecord"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          }
        }
      }
    },
    "/vehicles/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ResourceId"
        }
      ],
      "get": {
        "tags": ["Datos maestros"],
        "summary": "Consultar vehículo",
        "operationId": "getVehicle",
        "responses": {
          "200": {
            "$ref": "#/components/responses/VehicleRecord"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": ["Datos maestros"],
        "summary": "Actualizar vehículo",
        "operationId": "updateVehicle",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VehiclePatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/VehicleRecord"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/VersionMismatch"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          }
        }
      },
      "delete": {
        "tags": ["Datos maestros"],
        "summary": "Eliminar vehículo",
        "operationId": "deleteVehicle",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "204": {
            "description": "Vehículo eliminado"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "412": {
            "$ref": "#/components/responses/VersionMismatch"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          }
        }
      }
    },
    "/route-sheets": {
      "get": {
        "tags": ["Documentos"],
        "summary": "Listar hojas de ruta",
        "operationId": "listRouteSheets",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/UpdatedAfter"
          },
          {
            "$ref": "#/components/parameters/ExternalId"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/RouteSheetStatus"
            }
          },
          {
            "name": "driverId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "serviceDateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "serviceDateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Página de hojas",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RouteSheetListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          }
        }
      },
      "post": {
        "tags": ["Documentos"],
        "summary": "Emitir hoja de ruta y PDF",
        "operationId": "createRouteSheet",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RouteSheetInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/RouteSheetRecord"
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "403": {
            "description": "Scope insuficiente o cuota del plan agotada",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          }
        }
      }
    },
    "/route-sheets/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ResourceId"
        }
      ],
      "get": {
        "tags": ["Documentos"],
        "summary": "Consultar hoja de ruta",
        "operationId": "getRouteSheet",
        "responses": {
          "200": {
            "$ref": "#/components/responses/RouteSheetRecord"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": ["Documentos"],
        "summary": "Cambiar estado o firma",
        "operationId": "updateRouteSheet",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RouteSheetPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/RouteSheetRecord"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/VersionMismatch"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          }
        }
      },
      "delete": {
        "tags": ["Documentos"],
        "summary": "Borrar durante la ventana de diez minutos",
        "operationId": "deleteRouteSheet",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "204": {
            "description": "Hoja eliminada"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/VersionMismatch"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          }
        }
      }
    },
    "/route-sheets/{id}/revisions": {
      "post": {
        "tags": ["Documentos"],
        "summary": "Crear revisión inmutable",
        "operationId": "reviseRouteSheet",
        "parameters": [
          {
            "$ref": "#/components/parameters/ResourceId"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RouteSheetRevisionInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/RouteSheetRecord"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/VersionMismatch"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          }
        }
      }
    },
    "/route-sheets/{id}/pdf": {
      "get": {
        "tags": ["Documentos"],
        "summary": "Descargar PDF vigente",
        "operationId": "downloadRouteSheetPdf",
        "parameters": [
          {
            "$ref": "#/components/parameters/ResourceId"
          }
        ],
        "responses": {
          "200": {
            "description": "PDF íntegro",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "contentEncoding": "binary"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "tags": ["Webhooks"],
        "summary": "Listar destinos",
        "operationId": "listWebhooks",
        "responses": {
          "200": {
            "description": "Destinos configurados",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookListResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Webhooks"],
        "summary": "Crear destino y revelar secreto una vez",
        "operationId": "createWebhook",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/WebhookSecretRecord"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          }
        }
      }
    },
    "/webhooks/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ResourceId"
        }
      ],
      "get": {
        "tags": ["Webhooks"],
        "summary": "Consultar destino",
        "operationId": "getWebhook",
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookRecord"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": ["Webhooks"],
        "summary": "Actualizar o pausar destino",
        "operationId": "updateWebhook",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookRecord"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/VersionMismatch"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          }
        }
      },
      "delete": {
        "tags": ["Webhooks"],
        "summary": "Eliminar destino",
        "operationId": "deleteWebhook",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "204": {
            "description": "Webhook eliminado"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "412": {
            "$ref": "#/components/responses/VersionMismatch"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          }
        }
      }
    },
    "/webhooks/{id}/rotate-secret": {
      "post": {
        "tags": ["Webhooks"],
        "summary": "Rotar secreto de firma",
        "operationId": "rotateWebhookSecret",
        "parameters": [
          {
            "$ref": "#/components/parameters/ResourceId"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookSecretRecord"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/webhooks/{id}/test": {
      "post": {
        "tags": ["Webhooks"],
        "summary": "Enviar evento de prueba",
        "operationId": "testWebhook",
        "parameters": [
          {
            "$ref": "#/components/parameters/ResourceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Prueba entregada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryResponse"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "502": {
            "description": "El destino no confirmó la entrega",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/webhook-deliveries": {
      "get": {
        "tags": ["Webhooks"],
        "summary": "Listar entregas",
        "operationId": "listWebhookDeliveries",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/UpdatedAfter"
          },
          {
            "name": "endpointId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Historial de entregas",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "hdr_live_..."
      }
    },
    "parameters": {
      "ResourceId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "example": "resource_01K..."
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "description": "Tamaño de página entre 1 y 100.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 50
        }
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "description": "Cursor opaco devuelto por meta.nextCursor.",
        "schema": {
          "type": "string"
        },
        "example": "eyJ1cGRhdGVkQXQiOiIyMDI2LTA3LTI5VDA5OjIwOjAwLjAwMFoifQ"
      },
      "UpdatedAfter": {
        "name": "updatedAfter",
        "in": "query",
        "description": "Polling incremental: devuelve altas y modificaciones posteriores a la fecha. No devuelve tombstones de recursos eliminados.",
        "schema": {
          "type": "string",
          "format": "date-time",
          "example": "2026-07-28T10:00:00.000Z"
        }
      },
      "ExternalId": {
        "name": "externalId",
        "in": "query",
        "schema": {
          "type": "string",
          "maxLength": 160,
          "example": "ERP-1042"
        }
      },
      "IfMatch": {
        "name": "If-Match",
        "in": "header",
        "required": true,
        "description": "ETag devuelto por GET o por la escritura anterior.",
        "schema": {
          "type": "string",
          "example": "\"V8y4hX2mQ0cR7fP1kL9sAw\""
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "Identificador estable del intento, retenido siete días.",
        "schema": {
          "type": "string",
          "minLength": 8,
          "maxLength": 200,
          "example": "driver-ERP-1042-v1"
        }
      }
    },
    "responses": {
      "InvalidApiKey": {
        "description": "Clave inexistente, caducada o revocada",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "InsufficientScope": {
        "description": "La clave no tiene el scope necesario",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Scope insuficiente, límite del plan o cuenta protegida",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "InvalidRequest": {
        "description": "Solicitud o paginación no válida",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "NotFound": {
        "description": "El recurso no existe en la organización",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "Conflict": {
        "description": "Duplicado, idempotencia incompatible o transición no válida",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "VersionMismatch": {
        "description": "If-Match no coincide con la versión actual",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "ValidationFailed": {
        "description": "El payload no cumple el contrato",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "PreconditionRequired": {
        "description": "Falta If-Match",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Límite técnico superado",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "InternalError": {
        "description": "Error de almacenamiento o integridad",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "CompanyRecord": {
        "description": "Empresa",
        "headers": {
          "ETag": {
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/CompanyResponse"
            }
          }
        }
      },
      "VehicleRecord": {
        "description": "Vehículo",
        "headers": {
          "ETag": {
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/VehicleResponse"
            }
          }
        }
      },
      "DriverRecord": {
        "description": "Conductor",
        "headers": {
          "ETag": {
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/DriverResponse"
            }
          }
        }
      },
      "RouteSheetRecord": {
        "description": "Hoja de ruta",
        "headers": {
          "ETag": {
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/RouteSheetResponse"
            }
          }
        }
      },
      "WebhookRecord": {
        "description": "Destino webhook",
        "headers": {
          "ETag": {
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/WebhookResponse"
            }
          }
        }
      },
      "WebhookSecretRecord": {
        "description": "Destino y secreto visible una vez",
        "headers": {
          "ETag": {
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/WebhookSecretResponse"
            }
          }
        }
      }
    },
    "schemas": {
      "Meta": {
        "type": "object",
        "required": ["requestId"],
        "properties": {
          "requestId": {
            "type": "string",
            "pattern": "^req_"
          },
          "count": {
            "type": "integer",
            "minimum": 0
          },
          "hasMore": {
            "type": "boolean"
          },
          "nextCursor": {
            "type": "string"
          }
        },
        "example": {
          "requestId": "req_01K...",
          "count": 1,
          "hasMore": false
        }
      },
      "Problem": {
        "type": "object",
        "required": ["type", "title", "status", "code", "detail", "requestId"],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "code": {
            "type": "string"
          },
          "detail": {
            "type": "string"
          },
          "requestId": {
            "type": "string"
          }
        },
        "example": {
          "type": "https://hojasderuta.com/problems/validation-failed",
          "title": "Datos no válidos",
          "status": 422,
          "code": "validation_failed",
          "detail": "Uno o más campos no cumplen el contrato.",
          "requestId": "req_01K..."
        },
        "additionalProperties": true
      },
      "Account": {
        "type": "object",
        "required": ["organizationId", "organizationName", "planId", "credential"],
        "properties": {
          "organizationId": {
            "type": "string"
          },
          "organizationName": {
            "type": "string"
          },
          "planId": {
            "type": "string",
            "enum": ["free", "starter", "fleet", "unlimited"]
          },
          "credential": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "example": {
          "organizationId": "org_01K...",
          "organizationName": "Autocares Sierra Norte",
          "planId": "starter",
          "credential": {
            "id": "api_key_01K...",
            "name": "ERP producción",
            "scopes": ["account:read", "usage:read", "route_sheets:write"]
          }
        }
      },
      "Usage": {
        "type": "object",
        "required": ["planId", "drivers", "routeSheets", "credentials"],
        "properties": {
          "planId": {
            "type": "string",
            "enum": ["free", "starter", "fleet", "unlimited"]
          },
          "drivers": {
            "type": "object",
            "required": ["active", "pendingInvitations", "used", "limit", "remaining"],
            "properties": {
              "active": {
                "type": "integer",
                "minimum": 0
              },
              "pendingInvitations": {
                "type": "integer",
                "minimum": 0
              },
              "used": {
                "type": "integer",
                "minimum": 0
              },
              "limit": {
                "type": ["integer", "null"],
                "minimum": 0
              },
              "remaining": {
                "type": ["integer", "null"],
                "minimum": 0
              }
            }
          },
          "routeSheets": {
            "type": "object",
            "required": ["used", "limit", "remaining", "resetsAt"],
            "properties": {
              "used": {
                "type": "integer",
                "minimum": 0
              },
              "limit": {
                "type": ["integer", "null"],
                "minimum": 0
              },
              "remaining": {
                "type": ["integer", "null"],
                "minimum": 0
              },
              "resetsAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "credentials": {
            "type": "object",
            "required": ["planId", "activeCount", "limit", "canCreate"],
            "properties": {
              "planId": {
                "type": "string"
              },
              "activeCount": {
                "type": "integer"
              },
              "limit": {
                "type": "integer"
              },
              "canCreate": {
                "type": "boolean"
              }
            }
          }
        },
        "example": {
          "planId": "starter",
          "drivers": {
            "active": 3,
            "pendingInvitations": 1,
            "used": 4,
            "limit": 5,
            "remaining": 1
          },
          "routeSheets": {
            "used": 17,
            "limit": 40,
            "remaining": 23,
            "resetsAt": "2026-08-01T00:00:00.000Z"
          },
          "credentials": {
            "planId": "starter",
            "activeCount": 1,
            "limit": 2,
            "canCreate": true
          }
        }
      },
      "Capabilities": {
        "type": "object",
        "required": ["credentialId", "scopes", "capabilities"],
        "properties": {
          "credentialId": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "capabilities": {
            "type": "object",
            "additionalProperties": {
              "type": "boolean"
            }
          }
        },
        "example": {
          "credentialId": "api_key_01K...",
          "scopes": ["account:read", "route_sheets:read", "route_sheets:write"],
          "capabilities": {
            "account:read": true,
            "usage:read": false,
            "route_sheets:read": true,
            "route_sheets:write": true
          }
        }
      },
      "CompanyInput": {
        "type": "object",
        "required": ["name", "nif"],
        "properties": {
          "externalId": {
            "type": "string",
            "maxLength": 160
          },
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 160
          },
          "nif": {
            "type": "string",
            "maxLength": 32
          }
        },
        "example": {
          "externalId": "ERP-COMPANY-204",
          "name": "Autocares Sierra Norte",
          "nif": "B12345678"
        }
      },
      "CompanyPatch": {
        "type": "object",
        "minProperties": 1,
        "properties": {
          "externalId": {
            "type": "string",
            "maxLength": 160
          },
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 160
          },
          "nif": {
            "type": "string",
            "maxLength": 32
          }
        },
        "example": {
          "name": "Autocares Sierra Norte SL",
          "nif": "B12345678"
        },
        "additionalProperties": false
      },
      "Company": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CompanyInput"
          },
          {
            "type": "object",
            "required": ["id", "createdAt", "updatedAt"],
            "properties": {
              "id": {
                "type": "string"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        ],
        "example": {
          "id": "company_01K...",
          "externalId": "ERP-COMPANY-204",
          "name": "Autocares Sierra Norte",
          "nif": "B12345678",
          "createdAt": "2026-07-29T09:15:00.000Z",
          "updatedAt": "2026-07-29T09:15:00.000Z"
        }
      },
      "VehicleInput": {
        "type": "object",
        "required": ["plate"],
        "properties": {
          "externalId": {
            "type": "string",
            "maxLength": 160
          },
          "plate": {
            "type": "string",
            "maxLength": 24
          },
          "label": {
            "type": "string",
            "maxLength": 160
          }
        },
        "example": {
          "externalId": "ERP-BUS-82",
          "plate": "8246LRV",
          "label": "Autobús 82"
        }
      },
      "VehiclePatch": {
        "type": "object",
        "minProperties": 1,
        "properties": {
          "externalId": {
            "type": "string",
            "maxLength": 160
          },
          "plate": {
            "type": "string",
            "maxLength": 24
          },
          "label": {
            "type": "string",
            "maxLength": 160
          }
        },
        "example": {
          "plate": "8246LRV",
          "label": "Autobús principal"
        },
        "additionalProperties": false
      },
      "Vehicle": {
        "allOf": [
          {
            "$ref": "#/components/schemas/VehicleInput"
          },
          {
            "type": "object",
            "required": ["id", "createdAt", "updatedAt"],
            "properties": {
              "id": {
                "type": "string"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        ],
        "example": {
          "id": "vehicle_01K...",
          "externalId": "ERP-BUS-82",
          "plate": "8246LRV",
          "label": "Autobús 82",
          "createdAt": "2026-07-29T09:18:00.000Z",
          "updatedAt": "2026-07-29T09:18:00.000Z"
        }
      },
      "DriverPermissions": {
        "type": "object",
        "properties": {
          "manageCompanies": {
            "type": "boolean",
            "default": false
          },
          "manageDrivers": {
            "type": "boolean",
            "default": false
          },
          "manageVehicles": {
            "type": "boolean",
            "default": false
          }
        },
        "additionalProperties": false
      },
      "DriverInput": {
        "type": "object",
        "required": ["name", "email", "driverNif", "password"],
        "properties": {
          "externalId": {
            "type": "string",
            "maxLength": 160
          },
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 160
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          },
          "driverNif": {
            "type": "string",
            "minLength": 2,
            "maxLength": 32
          },
          "phone": {
            "type": "string",
            "description": "Teléfono E.164 o número español de nueve dígitos."
          },
          "password": {
            "type": "string",
            "format": "password",
            "minLength": 6,
            "maxLength": 200,
            "writeOnly": true
          },
          "permissions": {
            "$ref": "#/components/schemas/DriverPermissions"
          }
        },
        "example": {
          "externalId": "ERP-DRIVER-1042",
          "name": "Ana García López",
          "email": "ana.garcia@example.com",
          "driverNif": "12345678Z",
          "phone": "600 123 456",
          "password": "contraseña-inicial-segura",
          "permissions": {
            "manageCompanies": false,
            "manageDrivers": false,
            "manageVehicles": false
          }
        },
        "additionalProperties": false
      },
      "DriverPatch": {
        "type": "object",
        "minProperties": 1,
        "properties": {
          "externalId": {
            "type": "string",
            "maxLength": 160
          },
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 160
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          },
          "driverNif": {
            "type": "string",
            "minLength": 2,
            "maxLength": 32
          },
          "phone": {
            "type": "string"
          },
          "permissions": {
            "$ref": "#/components/schemas/DriverPermissions"
          }
        },
        "example": {
          "phone": "+34611222333",
          "permissions": {
            "manageCompanies": true,
            "manageDrivers": false,
            "manageVehicles": true
          }
        },
        "additionalProperties": false
      },
      "DriverPasswordInput": {
        "type": "object",
        "required": ["password"],
        "properties": {
          "password": {
            "type": "string",
            "format": "password",
            "minLength": 6,
            "maxLength": 200,
            "writeOnly": true
          }
        },
        "example": {
          "password": "nueva-contraseña-segura"
        },
        "additionalProperties": false
      },
      "Driver": {
        "type": "object",
        "required": [
          "id",
          "externalId",
          "name",
          "hasAccount",
          "driverNif",
          "permissions",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "externalId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "hasAccount": {
            "type": "boolean",
            "description": "Indica si el conductor dispone de credenciales para iniciar sesión. Los perfiles creados manualmente sin cuenta devuelven false."
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Sólo se incluye cuando hasAccount es true."
          },
          "driverNif": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "permissions": {
            "$ref": "#/components/schemas/DriverPermissions"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "user_01K...",
          "externalId": "ERP-DRIVER-1042",
          "name": "Ana García López",
          "hasAccount": true,
          "email": "ana.garcia@example.com",
          "driverNif": "12345678Z",
          "phone": "+34600123456",
          "permissions": {
            "manageCompanies": false,
            "manageDrivers": false,
            "manageVehicles": false
          },
          "createdAt": "2026-07-29T09:20:00.000Z",
          "updatedAt": "2026-07-29T09:20:00.000Z"
        }
      },
      "RouteSheetStatus": {
        "type": "string",
        "enum": ["draft", "ready", "in_service", "completed", "archived"]
      },
      "RouteSheetInput": {
        "type": "object",
        "required": [
          "externalId",
          "companyName",
          "companyNif",
          "contractorName",
          "contractorNif",
          "origin",
          "destination",
          "serviceDate",
          "serviceStartTime",
          "busPlate",
          "driverId"
        ],
        "properties": {
          "externalId": {
            "type": "string",
            "maxLength": 160
          },
          "companyName": {
            "type": "string"
          },
          "companyNif": {
            "type": "string",
            "maxLength": 32
          },
          "contractorName": {
            "type": "string"
          },
          "contractorNif": {
            "type": "string",
            "maxLength": 32
          },
          "origin": {
            "type": "string"
          },
          "destination": {
            "type": "string"
          },
          "serviceDate": {
            "type": "string",
            "format": "date"
          },
          "serviceStartTime": {
            "type": "string",
            "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
          },
          "serviceEndTime": {
            "type": "string",
            "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
          },
          "intermediateStops": {
            "type": "array",
            "items": {
              "type": "object",
              "required": ["name"],
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "order": {
                  "type": "integer"
                }
              }
            }
          },
          "busPlate": {
            "type": "string",
            "maxLength": 24
          },
          "driverId": {
            "type": "string"
          },
          "secondaryDriverId": {
            "type": "string"
          },
          "serviceNature": {
            "type": "string",
            "enum": [
              "discretionary",
              "regular_reinforcement",
              "special_regular_collaboration",
              "tourist"
            ],
            "default": "discretionary"
          },
          "regularServiceReference": {
            "type": "string"
          },
          "serviceNatureDetail": {
            "type": "string"
          }
        },
        "example": {
          "externalId": "ERP-2026-184",
          "companyName": "Autocares Sierra Norte",
          "companyNif": "B12345678",
          "contractorName": "Asociación Cultural Norte",
          "contractorNif": "G87654321",
          "origin": "Madrid",
          "destination": "Toledo",
          "serviceDate": "2026-10-05",
          "serviceStartTime": "08:30",
          "serviceEndTime": "12:15",
          "busPlate": "8246LRV",
          "driverId": "user_01K...",
          "serviceNature": "discretionary"
        }
      },
      "RouteSheet": {
        "allOf": [
          {
            "$ref": "#/components/schemas/RouteSheetInput"
          },
          {
            "type": "object",
            "required": [
              "id",
              "status",
              "pdfVersion",
              "pdfUrl",
              "qrUrl",
              "createdAt",
              "updatedAt"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "status": {
                "$ref": "#/components/schemas/RouteSheetStatus"
              },
              "driverName": {
                "type": "string"
              },
              "driverNif": {
                "type": "string"
              },
              "secondaryDriverName": {
                "type": "string"
              },
              "secondaryDriverNif": {
                "type": "string"
              },
              "pdfVersion": {
                "type": "integer",
                "minimum": 1
              },
              "pdfUrl": {
                "type": "string"
              },
              "qrUrl": {
                "type": "string",
                "format": "uri"
              },
              "signature": {
                "$ref": "#/components/schemas/Signature"
              },
              "revisions": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": true
                }
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        ],
        "example": {
          "id": "hr_01K...",
          "externalId": "ERP-2026-184",
          "companyName": "Autocares Sierra Norte",
          "companyNif": "B12345678",
          "contractorName": "Asociación Cultural Norte",
          "contractorNif": "G87654321",
          "origin": "Madrid",
          "destination": "Toledo",
          "serviceDate": "2026-10-05",
          "serviceStartTime": "08:30",
          "serviceEndTime": "12:15",
          "busPlate": "8246LRV",
          "driverId": "user_01K...",
          "driverName": "Ana García López",
          "driverNif": "12345678Z",
          "serviceNature": "discretionary",
          "status": "ready",
          "pdfVersion": 1,
          "pdfUrl": "/api/v1/route-sheets/hr_01K.../pdf",
          "qrUrl": "https://hojasderuta.com/deca/token_01K...",
          "createdAt": "2026-10-05T06:12:44.000Z",
          "updatedAt": "2026-10-05T06:12:44.000Z"
        }
      },
      "Signature": {
        "type": "object",
        "required": ["signerName", "signerDni", "strokes"],
        "properties": {
          "signerName": {
            "type": "string"
          },
          "signerDni": {
            "type": "string"
          },
          "strokes": {
            "type": "array",
            "minItems": 1,
            "maxItems": 200,
            "items": {
              "type": "string"
            }
          },
          "width": {
            "type": "number",
            "minimum": 1,
            "maximum": 4096
          },
          "height": {
            "type": "number",
            "minimum": 1,
            "maximum": 4096
          },
          "signedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "signerName": "Ana García López",
          "signerDni": "12345678Z",
          "strokes": ["12,44;18,39;27,52", "31,50;42,37;55,48"],
          "width": 320,
          "height": 120,
          "signedAt": "2026-10-05T08:28:00.000Z"
        }
      },
      "RouteSheetPatch": {
        "type": "object",
        "minProperties": 1,
        "properties": {
          "status": {
            "$ref": "#/components/schemas/RouteSheetStatus"
          },
          "signature": {
            "$ref": "#/components/schemas/Signature"
          }
        },
        "example": {
          "status": "in_service"
        },
        "additionalProperties": false
      },
      "RouteSheetRevisionInput": {
        "type": "object",
        "required": ["reason", "draft"],
        "properties": {
          "reason": {
            "type": "string",
            "minLength": 5,
            "maxLength": 500
          },
          "draft": {
            "type": "object",
            "minProperties": 1,
            "additionalProperties": true
          }
        },
        "example": {
          "reason": "Corrección de la hora de finalización comunicada por la oficina.",
          "draft": {
            "serviceEndTime": "12:45",
            "destination": "Talavera de la Reina"
          }
        }
      },
      "WebhookEventType": {
        "type": "string",
        "enum": [
          "route_sheet.created",
          "route_sheet.updated",
          "route_sheet.revised",
          "route_sheet.deleted",
          "driver.created",
          "driver.updated",
          "driver.deleted",
          "company.created",
          "company.updated",
          "company.deleted",
          "vehicle.created",
          "vehicle.updated",
          "vehicle.deleted",
          "subscription.changed",
          "usage.threshold_reached",
          "webhook.test"
        ]
      },
      "WebhookInput": {
        "type": "object",
        "required": ["name", "url", "events"],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 3,
            "maxLength": 80
          },
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            }
          }
        },
        "example": {
          "name": "ERP producción",
          "url": "https://erp.example.com/webhooks/hojas-de-ruta",
          "events": ["route_sheet.created", "route_sheet.revised"]
        }
      },
      "WebhookPatch": {
        "type": "object",
        "minProperties": 1,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 3,
            "maxLength": 80
          },
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            }
          },
          "status": {
            "type": "string",
            "enum": ["active", "disabled"]
          }
        },
        "example": {
          "status": "disabled",
          "events": [
            "route_sheet.created",
            "route_sheet.updated",
            "route_sheet.revised"
          ]
        },
        "additionalProperties": false
      },
      "Webhook": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookInput"
          },
          {
            "type": "object",
            "required": ["id", "status", "createdAt", "updatedAt"],
            "properties": {
              "id": {
                "type": "string"
              },
              "status": {
                "type": "string",
                "enum": ["active", "disabled"]
              },
              "lastDeliveryAt": {
                "type": "string",
                "format": "date-time"
              },
              "lastDeliveryStatus": {
                "type": "string",
                "enum": ["delivered", "failed"]
              },
              "secretRotatedAt": {
                "type": "string",
                "format": "date-time"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        ],
        "example": {
          "id": "webhook_01K...",
          "name": "ERP producción",
          "url": "https://erp.example.com/webhooks/hojas-de-ruta",
          "events": ["route_sheet.created", "route_sheet.revised"],
          "status": "active",
          "createdAt": "2026-10-05T06:10:00.000Z",
          "updatedAt": "2026-10-05T06:10:00.000Z"
        }
      },
      "WebhookSecret": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Webhook"
          },
          {
            "type": "object",
            "required": ["secret"],
            "properties": {
              "secret": {
                "type": "string",
                "pattern": "^whsec_"
              }
            }
          }
        ],
        "example": {
          "id": "webhook_01K...",
          "name": "ERP producción",
          "url": "https://erp.example.com/webhooks/hojas-de-ruta",
          "events": ["route_sheet.created", "route_sheet.revised"],
          "status": "active",
          "secret": "whsec_01K_REPLACE_WITH_THE_RETURNED_SECRET",
          "createdAt": "2026-10-05T06:10:00.000Z",
          "updatedAt": "2026-10-05T06:10:00.000Z"
        }
      },
      "WebhookDelivery": {
        "type": "object",
        "required": [
          "id",
          "endpointId",
          "eventId",
          "eventType",
          "status",
          "attempts",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "endpointId": {
            "type": "string"
          },
          "endpointName": {
            "type": "string"
          },
          "eventId": {
            "type": "string"
          },
          "eventType": {
            "$ref": "#/components/schemas/WebhookEventType"
          },
          "status": {
            "type": "string",
            "enum": ["delivered", "failed"]
          },
          "attempts": {
            "type": "integer",
            "minimum": 0,
            "maximum": 3
          },
          "responseStatus": {
            "type": "integer"
          },
          "lastError": {
            "type": "string"
          },
          "deliveredAt": {
            "type": "string",
            "format": "date-time"
          },
          "failedAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "event": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "example": {
          "id": "delivery_01K...",
          "endpointId": "webhook_01K...",
          "endpointName": "ERP producción",
          "eventId": "evt_01K...",
          "eventType": "webhook.test",
          "status": "delivered",
          "attempts": 1,
          "responseStatus": 204,
          "deliveredAt": "2026-10-05T06:11:04.000Z",
          "createdAt": "2026-10-05T06:11:03.000Z",
          "event": {
            "id": "evt_01K...",
            "type": "webhook.test",
            "createdAt": "2026-10-05T06:11:03.000Z",
            "data": {
              "test": true
            }
          }
        }
      },
      "AccountResponse": {
        "$ref": "#/components/schemas/SingleAccountEnvelope"
      },
      "UsageResponse": {
        "$ref": "#/components/schemas/SingleUsageEnvelope"
      },
      "CapabilitiesResponse": {
        "$ref": "#/components/schemas/SingleCapabilitiesEnvelope"
      },
      "CompanyResponse": {
        "$ref": "#/components/schemas/SingleCompanyEnvelope"
      },
      "VehicleResponse": {
        "$ref": "#/components/schemas/SingleVehicleEnvelope"
      },
      "DriverResponse": {
        "$ref": "#/components/schemas/SingleDriverEnvelope"
      },
      "RouteSheetResponse": {
        "$ref": "#/components/schemas/SingleRouteSheetEnvelope"
      },
      "WebhookResponse": {
        "$ref": "#/components/schemas/SingleWebhookEnvelope"
      },
      "WebhookSecretResponse": {
        "$ref": "#/components/schemas/SingleWebhookSecretEnvelope"
      },
      "WebhookDeliveryResponse": {
        "$ref": "#/components/schemas/SingleWebhookDeliveryEnvelope"
      },
      "SingleAccountEnvelope": {
        "type": "object",
        "required": ["data", "meta"],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Account"
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "SingleUsageEnvelope": {
        "type": "object",
        "required": ["data", "meta"],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Usage"
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "SingleCapabilitiesEnvelope": {
        "type": "object",
        "required": ["data", "meta"],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Capabilities"
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "SingleCompanyEnvelope": {
        "type": "object",
        "required": ["data", "meta"],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Company"
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "SingleVehicleEnvelope": {
        "type": "object",
        "required": ["data", "meta"],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Vehicle"
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "SingleDriverEnvelope": {
        "type": "object",
        "required": ["data", "meta"],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Driver"
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "SingleRouteSheetEnvelope": {
        "type": "object",
        "required": ["data", "meta"],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/RouteSheet"
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "SingleWebhookEnvelope": {
        "type": "object",
        "required": ["data", "meta"],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Webhook"
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "SingleWebhookSecretEnvelope": {
        "type": "object",
        "required": ["data", "meta"],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebhookSecret"
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "SingleWebhookDeliveryEnvelope": {
        "type": "object",
        "required": ["data", "meta"],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebhookDelivery"
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "CompanyListResponse": {
        "$ref": "#/components/schemas/CompanyListEnvelope"
      },
      "VehicleListResponse": {
        "$ref": "#/components/schemas/VehicleListEnvelope"
      },
      "DriverListResponse": {
        "$ref": "#/components/schemas/DriverListEnvelope"
      },
      "RouteSheetListResponse": {
        "$ref": "#/components/schemas/RouteSheetListEnvelope"
      },
      "WebhookListResponse": {
        "$ref": "#/components/schemas/WebhookListEnvelope"
      },
      "WebhookDeliveryListResponse": {
        "$ref": "#/components/schemas/WebhookDeliveryListEnvelope"
      },
      "CompanyListEnvelope": {
        "type": "object",
        "required": ["data", "meta"],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Company"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "VehicleListEnvelope": {
        "type": "object",
        "required": ["data", "meta"],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Vehicle"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "DriverListEnvelope": {
        "type": "object",
        "required": ["data", "meta"],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Driver"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "RouteSheetListEnvelope": {
        "type": "object",
        "required": ["data", "meta"],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RouteSheet"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "WebhookListEnvelope": {
        "type": "object",
        "required": ["data", "meta"],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Webhook"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "WebhookDeliveryListEnvelope": {
        "type": "object",
        "required": ["data", "meta"],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookDelivery"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      }
    }
  }
}
