{
  "components" : {
    "schemas" : {
      "ActualizarEmisorRequest" : {
        "properties" : {
          "direccionMatriz" : {
            "description" : "Nueva dirección de la matriz.",
            "example" : "Av. Amazonas 1234, Quito",
            "type" : "string"
          },
          "nombreComercial" : {
            "description" : "Nuevo nombre comercial.",
            "example" : "El Buen Sabor",
            "type" : "string"
          },
          "obligadoContabilidad" : {
            "description" : "Si pasa a estar obligado a llevar contabilidad.",
            "example" : true,
            "type" : "boolean"
          },
          "razonSocial" : {
            "description" : "Nueva razón social, tal como consta en el RUC.",
            "example" : "ASADERO EL BUEN SABOR S.A.",
            "type" : "string"
          },
          "referenciaExterna" : {
            "description" : "Nueva referencia externa. Tiene que seguir siendo única entre tus recursos.",
            "example" : "negocio-0077",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "ActualizarPuntoEmisionRequest" : {
        "properties" : {
          "activo" : {
            "description" : "Desactivarlo impide emitir desde él y devuelve `422 PUNTO_EMISION_INACTIVO`. La numeración no se puede cambiar por acá: un contador movido a mano es un hueco o un número repetido ante el SRI.",
            "example" : true,
            "type" : "boolean"
          },
          "descripcion" : {
            "description" : "Nueva descripción.",
            "example" : "Caja principal",
            "type" : "string"
          },
          "direccion" : {
            "description" : "Nueva dirección del local.",
            "example" : "Av. Amazonas 1234, local 3",
            "type" : "string"
          },
          "referenciaExterna" : {
            "description" : "Nueva referencia externa.",
            "example" : "caja-principal",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "CambiarAmbienteRequest" : {
        "properties" : {
          "ambiente" : {
            "description" : "Ambiente al que pasa el emisor. El paso a `PRODUCCION` **no tiene vuelta atrás**: volver a `PRUEBAS` responde `409 AMBIENTE_RETROCESO_NO_PERMITIDO`.",
            "enum" : [ "PRUEBAS", "PRODUCCION" ],
            "example" : "PRODUCCION",
            "type" : "string"
          }
        },
        "required" : [ "ambiente" ],
        "type" : "object"
      },
      "CertificadoResponse" : {
        "properties" : {
          "cargadoEn" : {
            "description" : "Cuándo se subió a este servicio.",
            "example" : "2026-10-15T09:12:44-05:00",
            "format" : "date-time",
            "type" : "string"
          },
          "diasParaExpirar" : {
            "description" : "Días que le quedan de vigencia.",
            "example" : 150,
            "format" : "int64",
            "type" : "integer"
          },
          "estado" : {
            "description" : "`NO_CARGADO` si el emisor todavía no tiene certificado, `VALIDO` si está vigente, `POR_EXPIRAR` cuando le quedan 30 días o menos —el mismo umbral del evento `certificado.por_expirar`— y `EXPIRADO` cuando ya venció. Un certificado expirado deja al contribuyente sin poder facturar.",
            "enum" : [ "NO_CARGADO", "VALIDO", "POR_EXPIRAR", "EXPIRADO" ],
            "example" : "VALIDO",
            "type" : "string"
          },
          "expiraEn" : {
            "description" : "Fecha de vencimiento del certificado.",
            "example" : "2027-03-14T23:59:59Z",
            "format" : "date-time",
            "type" : "string"
          },
          "titular" : {
            "description" : "A nombre de quién lo emitió la entidad certificadora.",
            "example" : "JUAN PEREZ MORA",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "CompradorRequest" : {
        "properties" : {
          "direccion" : {
            "description" : "Dirección del comprador, si se tiene.",
            "example" : "Av. Universitaria 123",
            "type" : "string"
          },
          "email" : {
            "description" : "Correo del comprador, si se tiene. Va en el comprobante.",
            "example" : "juan@ejemplo.com",
            "format" : "email",
            "type" : "string"
          },
          "identificacion" : {
            "description" : "El número, sin guiones ni espacios. El SRI valida su estructura según el tipo declarado; un valor que no cuadre devuelve `400 IDENTIFICACION_INVALIDA`.",
            "example" : "1712345678",
            "minLength" : 1,
            "type" : "string"
          },
          "razonSocial" : {
            "description" : "Nombre o razón social del comprador.",
            "example" : "JUAN PEREZ MORA",
            "minLength" : 1,
            "type" : "string"
          },
          "tipoIdentificacion" : {
            "description" : "Tipo de identificación del catálogo del SRI. Determina las reglas de formato que se aplican a `identificacion`.",
            "enum" : [ "RUC", "CEDULA", "PASAPORTE", "CONSUMIDOR_FINAL", "IDENTIFICACION_EXTERIOR" ],
            "example" : "CEDULA",
            "type" : "string"
          }
        },
        "required" : [ "identificacion", "razonSocial", "tipoIdentificacion" ],
        "type" : "object"
      },
      "ComprobanteResponse" : {
        "properties" : {
          "ambiente" : {
            "description" : "Ambiente con el que salió este comprobante, no el que tiene el emisor ahora. Es inmutable: un emisor que pasa a producción no vuelve facturables los que emitió probando.",
            "enum" : [ "PRUEBAS", "PRODUCCION" ],
            "example" : "PRUEBAS",
            "type" : "string"
          },
          "claveAcceso" : {
            "description" : "Los 49 dígitos que identifican al comprobante ante el SRI. Va impresa en el RIDE y es por la que preguntan el contador y el propio SRI.",
            "example" : "1510202601179001234500120010010000000421234567810",
            "type" : "string"
          },
          "comprobanteId" : {
            "description" : "Identificador del comprobante en este servicio.",
            "example" : "3c7e9a52-18d4-4f60-b8e3-7d2a5c91f046",
            "format" : "uuid",
            "type" : "string"
          },
          "estado" : {
            "description" : "En qué acabó. `AUTORIZADO` llega con `201`, `EN_CONTINGENCIA` con `202` y `RECHAZADO` con `200` — los tres son peticiones procesadas correctamente.",
            "enum" : [ "AUTORIZADO", "RECHAZADO", "EN_CONTINGENCIA" ],
            "example" : "AUTORIZADO",
            "type" : "string"
          },
          "fechaAutorizacion" : {
            "description" : "Cuándo autorizó el SRI. `null` si todavía no lo hizo.",
            "example" : "2026-10-15T14:32:05-05:00",
            "format" : "date-time",
            "type" : "string"
          },
          "motivoRechazo" : {
            "description" : "Motivos del rechazo, en el texto del SRI **sin traducir**. Solo viene si `estado` es `RECHAZADO`.",
            "example" : "IDENTIFICACION DEL COMPRADOR: El dato ingresado no cumple con una estructura valida",
            "type" : "string"
          },
          "numeroAutorizacion" : {
            "description" : "Número de autorización del SRI. Coincide con la clave de acceso. `null` mientras no esté autorizado.",
            "example" : "1510202601179001234500120010010000000421234567810",
            "type" : "string"
          },
          "numeroComprobante" : {
            "description" : "Establecimiento, punto de emisión y secuencial.",
            "example" : "001-001-000000042",
            "type" : "string"
          },
          "primerIntento" : {
            "description" : "Cuándo se intentó transmitir por primera vez. En contingencia es el inicio de la ventana de 24 horas.",
            "example" : "2026-10-15T14:32:01-05:00",
            "format" : "date-time",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "ComprobanteResumen" : {
        "properties" : {
          "ambiente" : {
            "description" : "Ambiente con el que salió. Los de `PRUEBAS` no se cobran, y viaja acá para que puedas cuadrar la liquidación por tu cuenta.",
            "enum" : [ "PRUEBAS", "PRODUCCION" ],
            "example" : "PRUEBAS",
            "type" : "string"
          },
          "claveAcceso" : {
            "description" : "Los 49 dígitos de la clave de acceso.",
            "example" : "1510202601179001234500120010010000000421234567810",
            "type" : "string"
          },
          "comprobanteId" : {
            "description" : "Identificador del comprobante, para consultarlo en detalle.",
            "example" : "3c7e9a52-18d4-4f60-b8e3-7d2a5c91f046",
            "format" : "uuid",
            "type" : "string"
          },
          "creadoEn" : {
            "description" : "Cuándo se transmitió. Distinta de `fechaAutorizacion`: un comprobante que estuvo en contingencia se autoriza horas más tarde, y al conciliar por rango hay que poder ver que su autorización cayó fuera del rango por el que apareció.",
            "example" : "2026-10-15T14:32:01-05:00",
            "format" : "date-time",
            "type" : "string"
          },
          "estado" : {
            "description" : "En qué acabó ante el SRI.",
            "enum" : [ "AUTORIZADO", "RECHAZADO", "EN_CONTINGENCIA" ],
            "example" : "AUTORIZADO",
            "type" : "string"
          },
          "fechaAutorizacion" : {
            "description" : "Cuándo autorizó el SRI.",
            "example" : "2026-10-15T14:32:05-05:00",
            "format" : "date-time",
            "type" : "string"
          },
          "numeroAutorizacion" : {
            "description" : "Número de autorización, o `null` si no está autorizado.",
            "example" : "1510202601179001234500120010010000000421234567810",
            "type" : "string"
          },
          "numeroComprobante" : {
            "description" : "El número completo del comprobante.",
            "example" : "001-001-000000042",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "CrearEmisorRequest" : {
        "properties" : {
          "ambiente" : {
            "description" : "Ambiente con el que nace. En `PRUEBAS` los comprobantes van a la certificación del SRI y no son facturables.",
            "enum" : [ "PRUEBAS", "PRODUCCION" ],
            "example" : "PRUEBAS",
            "type" : "string"
          },
          "direccionMatriz" : {
            "description" : "Dirección de la matriz, la que va impresa en el comprobante.",
            "example" : "Av. Amazonas 1234, Quito",
            "minLength" : 1,
            "type" : "string"
          },
          "nombreComercial" : {
            "description" : "Nombre comercial, si difiere de la razón social.",
            "example" : "El Buen Sabor",
            "type" : "string"
          },
          "obligadoContabilidad" : {
            "description" : "Si el contribuyente está obligado a llevar contabilidad. Va en el XML del comprobante.",
            "example" : false,
            "type" : "boolean"
          },
          "razonSocial" : {
            "description" : "Razón social **tal como consta en el RUC**. El SRI la valida contra su registro; el nombre con el que se conoce al local va en `nombreComercial`.",
            "example" : "ASADERO EL BUEN SABOR S.A.",
            "minLength" : 1,
            "type" : "string"
          },
          "referenciaExterna" : {
            "description" : "Tu identificador para este negocio. Permite resolver el emisor sin guardar nuestros UUID y viaja en cada webhook. Pertenece a tu espacio de nombres: dos integradores pueden usar la misma.",
            "example" : "negocio-0077",
            "type" : "string"
          },
          "ruc" : {
            "description" : "RUC del contribuyente: 13 dígitos terminados en `001`. Es único en todo el servicio, porque un RUC es un contribuyente y dos registros serían dos contadores de numeración para la misma serie ante el SRI.",
            "example" : "1790012345001",
            "minLength" : 1,
            "pattern" : "\\d{10}001",
            "type" : "string"
          }
        },
        "required" : [ "ambiente", "direccionMatriz", "razonSocial", "ruc" ],
        "type" : "object"
      },
      "CrearPuntoEmisionRequest" : {
        "properties" : {
          "descripcion" : {
            "description" : "Para identificarlo en tu panel. No va en el comprobante.",
            "example" : "Caja principal",
            "type" : "string"
          },
          "direccion" : {
            "description" : "Dirección del local, si difiere de la matriz.",
            "example" : "Av. Amazonas 1234, local 3",
            "type" : "string"
          },
          "establecimiento" : {
            "description" : "Código de establecimiento del SRI: 3 dígitos.",
            "example" : "001",
            "minLength" : 1,
            "pattern" : "\\d{3}",
            "type" : "string"
          },
          "puntoEmision" : {
            "description" : "Código de punto de emisión del SRI: 3 dígitos.",
            "example" : "001",
            "minLength" : 1,
            "pattern" : "\\d{3}",
            "type" : "string"
          },
          "referenciaExterna" : {
            "description" : "Tu identificador para esta caja o local.",
            "example" : "caja-principal",
            "type" : "string"
          },
          "secuencialInicial" : {
            "description" : "Número del **próximo** comprobante de esta serie, no el del último emitido. Para una caja nueva, `1`. Si el local ya facturaba con esta serie por otro medio, el siguiente al último que emitió: empezar en `1` repetiría números que ese RUC ya usó ante el SRI.\n\nObligatorio y sin valor por defecto, porque el dato solo existe en tu onboarding.",
            "example" : 42,
            "format" : "int64",
            "maximum" : 999999999,
            "minimum" : 1,
            "type" : "integer"
          }
        },
        "required" : [ "establecimiento", "puntoEmision", "secuencialInicial" ],
        "type" : "object"
      },
      "EmisorResponse" : {
        "properties" : {
          "ambiente" : {
            "description" : "Ambiente en el que opera **ahora**. Los comprobantes conservan el suyo.",
            "enum" : [ "PRUEBAS", "PRODUCCION" ],
            "example" : "PRUEBAS",
            "type" : "string"
          },
          "certificado" : {
            "$ref" : "#/components/schemas/CertificadoResponse",
            "description" : "Estado del certificado de firma. `NO_CARGADO` mientras no se suba ninguno."
          },
          "creadoEn" : {
            "description" : "Cuándo se registró el emisor.",
            "example" : "2026-10-15T09:10:02-05:00",
            "format" : "date-time",
            "type" : "string"
          },
          "direccionMatriz" : {
            "description" : "Dirección de la matriz.",
            "example" : "Av. Amazonas 1234, Quito",
            "type" : "string"
          },
          "emisorId" : {
            "description" : "Identificador del emisor en este servicio. Va en la ruta de todo lo que cuelga de él.",
            "example" : "9f8c2d14-5b3a-4e77-9c21-0a6f4e8b1d33",
            "format" : "uuid",
            "type" : "string"
          },
          "nombreComercial" : {
            "description" : "Nombre comercial, o `null` si no se informó.",
            "example" : "El Buen Sabor",
            "type" : "string"
          },
          "obligadoContabilidad" : {
            "description" : "Si está obligado a llevar contabilidad.",
            "example" : false,
            "type" : "boolean"
          },
          "puedeEmitir" : {
            "description" : "Si el emisor ya puede emitir: tiene al menos un punto de emisión activo y un certificado vigente. Es el campo a mirar durante el alta para saber si falta algún paso.",
            "example" : false,
            "type" : "boolean"
          },
          "puntosEmision" : {
            "description" : "Los puntos de emisión registrados, con el siguiente número de cada serie.",
            "items" : {
              "$ref" : "#/components/schemas/PuntoEmisionResponse"
            },
            "type" : "array"
          },
          "razonSocial" : {
            "description" : "Razón social registrada ante el SRI.",
            "example" : "ASADERO EL BUEN SABOR S.A.",
            "type" : "string"
          },
          "referenciaExterna" : {
            "description" : "Tu identificador para este negocio.",
            "example" : "negocio-0077",
            "type" : "string"
          },
          "ruc" : {
            "description" : "RUC del contribuyente.",
            "example" : "1790012345001",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "EventoCertificado" : {
        "description" : "Payload de los dos eventos de certificado. `certificado.expirado` lleva los mismos campos con `diasRestantes` en `0` y sin `hitoDias`.\n\nEl archivo `.p12` y su contraseña no viajan nunca.",
        "properties" : {
          "certificadoId" : {
            "description" : "Identificador del certificado en este servicio",
            "example" : "9a1c4e72-6b38-4d15-a0f9-2c7e5b418d63",
            "format" : "uuid",
            "type" : "string"
          },
          "diasRestantes" : {
            "description" : "Días que le quedan. `0` en `certificado.expirado`",
            "example" : 15,
            "format" : "int64",
            "type" : "integer"
          },
          "emisorId" : {
            "description" : "El emisor dueño del certificado",
            "example" : "3c7e9a52-18d4-4f60-b8e3-7d2a5c91f046",
            "format" : "uuid",
            "type" : "string"
          },
          "expiraEn" : {
            "description" : "Cuándo vence",
            "example" : "2027-03-14T23:59:59Z",
            "type" : "string"
          },
          "hitoDias" : {
            "description" : "El hito que disparó el aviso: `30`, `15` o `5`. Sale un aviso por hito, el más urgente que corresponda. Solo en `certificado.por_expirar`",
            "enum" : [ 30, 15, 5 ],
            "example" : 15,
            "format" : "int32",
            "type" : "integer"
          },
          "razonSocial" : {
            "description" : "Razón social del contribuyente",
            "example" : "ASADERO EL BUEN SABOR S.A.",
            "type" : "string"
          },
          "referenciaExterna" : {
            "description" : "Tu identificador para este negocio",
            "example" : "negocio-0077",
            "type" : "string"
          },
          "ruc" : {
            "description" : "RUC del contribuyente",
            "example" : "1790012345001",
            "type" : "string"
          },
          "titular" : {
            "description" : "A nombre de quién está emitido el certificado",
            "example" : "JUAN PEREZ MORA",
            "type" : "string"
          }
        }
      },
      "EventoComprobante" : {
        "description" : "Payload de los tres eventos de comprobante. Los campos del punto de emisión y los de la autorización solo viajan cuando aplican: un comprobante en contingencia no tiene número de autorización todavía, y uno rechazado no lo va a tener nunca.",
        "properties" : {
          "ambiente" : {
            "description" : "El ambiente con el que salió, no el que tiene el emisor ahora",
            "enum" : [ "PRUEBAS", "PRODUCCION" ],
            "example" : "PRODUCCION",
            "type" : "string"
          },
          "claveAcceso" : {
            "description" : "Los 49 dígitos de la clave de acceso",
            "example" : "1510202601179001234500120010010000000421234567810",
            "type" : "string"
          },
          "comprobanteId" : {
            "description" : "Identificador del comprobante en este servicio",
            "example" : "9f8c2d14-5b3a-4e77-9c21-0a6f4e8b1d33",
            "format" : "uuid",
            "type" : "string"
          },
          "emisorId" : {
            "description" : "El emisor que lo emitió",
            "example" : "3c7e9a52-18d4-4f60-b8e3-7d2a5c91f046",
            "format" : "uuid",
            "type" : "string"
          },
          "estado" : {
            "description" : "En qué acabó el comprobante",
            "enum" : [ "AUTORIZADO", "RECHAZADO", "EN_CONTINGENCIA" ],
            "example" : "AUTORIZADO",
            "type" : "string"
          },
          "fechaAutorizacion" : {
            "description" : "Solo si el SRI autorizó",
            "example" : "2026-10-15T14:32:05-05:00",
            "type" : "string"
          },
          "motivoRechazo" : {
            "description" : "Solo si el SRI rechazó. Es su texto, sin traducir",
            "example" : "IDENTIFICACION DEL COMPRADOR: El dato ingresado no cumple con una estructura valida",
            "type" : "string"
          },
          "numeroAutorizacion" : {
            "description" : "Solo si el SRI autorizó. Coincide con la clave de acceso",
            "example" : "1510202601179001234500120010010000000421234567810",
            "type" : "string"
          },
          "numeroComprobante" : {
            "description" : "El número completo del comprobante",
            "example" : "001-001-000000042",
            "type" : "string"
          },
          "primerIntento" : {
            "description" : "Cuándo se intentó transmitir por primera vez",
            "example" : "2026-10-15T14:32:01-05:00",
            "type" : "string"
          },
          "puntoEmisionCodigo" : {
            "description" : "Establecimiento y punto, en el formato del SRI",
            "example" : "001-001",
            "type" : "string"
          },
          "puntoEmisionId" : {
            "description" : "El punto de emisión desde el que salió",
            "example" : "b1d60f38-9c45-4a2e-8f71-3e5c8a0b2947",
            "format" : "uuid",
            "type" : "string"
          },
          "puntoEmisionReferenciaExterna" : {
            "description" : "Tu identificador para esa caja o local",
            "example" : "caja-principal",
            "type" : "string"
          },
          "razonSocial" : {
            "description" : "Razón social del contribuyente",
            "example" : "ASADERO EL BUEN SABOR S.A.",
            "type" : "string"
          },
          "referenciaExterna" : {
            "description" : "Tu identificador para este negocio, para que concilies sin mantener una tabla de equivalencias con nuestros UUID",
            "example" : "negocio-0077",
            "type" : "string"
          },
          "ruc" : {
            "description" : "RUC del contribuyente",
            "example" : "1790012345001",
            "type" : "string"
          }
        }
      },
      "ItemRequest" : {
        "properties" : {
          "cantidad" : {
            "description" : "Cantidad. Admite hasta 6 decimales.",
            "example" : 2,
            "exclusiveMinimum" : 0,
            "type" : "number"
          },
          "codigo" : {
            "description" : "Tu código de producto. Máximo 25 caracteres, que es el tope del XSD del SRI; uno más largo se rechaza en vez de recortarse, para que el comprobante se pueda conciliar contra tu catálogo.",
            "example" : "ALM-001",
            "maxLength" : 25,
            "minLength" : 0,
            "type" : "string"
          },
          "descripcion" : {
            "description" : "Descripción de la línea, tal como aparecerá en el comprobante.",
            "example" : "Almuerzo completo",
            "minLength" : 1,
            "type" : "string"
          },
          "descuento" : {
            "description" : "Descuento de la línea. Si no viene, cero.",
            "example" : 0.0,
            "minimum" : 0,
            "type" : "number"
          },
          "precioUnitario" : {
            "description" : "Precio unitario **sin IVA**. Admite hasta 6 decimales.",
            "example" : 5.0,
            "minimum" : 0,
            "type" : "number"
          },
          "tarifaIva" : {
            "description" : "Tarifa de IVA del catálogo del SRI. `GENERAL` es la vigente; `CERO` es tarifa 0%.",
            "enum" : [ "CERO", "DIFERENCIADA", "GENERAL", "REDUCIDA", "NO_OBJETO_DE_IMPUESTO", "EXENTO" ],
            "example" : "GENERAL",
            "type" : "string"
          }
        },
        "required" : [ "cantidad", "codigo", "descripcion", "precioUnitario", "tarifaIva" ],
        "type" : "object"
      },
      "PaginaComprobanteResumen" : {
        "properties" : {
          "datos" : {
            "description" : "Los elementos de esta página, del más reciente al más antiguo.",
            "items" : {
              "$ref" : "#/components/schemas/ComprobanteResumen"
            },
            "type" : "array"
          },
          "paginacion" : {
            "$ref" : "#/components/schemas/Paginacion",
            "description" : "Cómo pedir la página siguiente."
          }
        },
        "type" : "object"
      },
      "PaginaSecuencialResponse" : {
        "properties" : {
          "datos" : {
            "description" : "Los elementos de esta página, del más reciente al más antiguo.",
            "items" : {
              "$ref" : "#/components/schemas/SecuencialResponse"
            },
            "type" : "array"
          },
          "paginacion" : {
            "$ref" : "#/components/schemas/Paginacion",
            "description" : "Cómo pedir la página siguiente."
          }
        },
        "type" : "object"
      },
      "Paginacion" : {
        "properties" : {
          "siguienteCursor" : {
            "description" : "Token opaco para pedir la página siguiente, o `null` si esta es la última. Se reenvía tal cual: su contenido es nuestro y puede cambiar.",
            "example" : "eyJ1IjoiMjAyNi0xMC0xNVQxNDozMjowNVoifQ",
            "type" : "string"
          },
          "tieneMas" : {
            "description" : "Si queda al menos una página más.",
            "example" : true,
            "type" : "boolean"
          }
        },
        "type" : "object"
      },
      "PuntoEmisionResponse" : {
        "properties" : {
          "activo" : {
            "description" : "Si puede emitir. Un punto desactivado devuelve `422 PUNTO_EMISION_INACTIVO`.",
            "example" : true,
            "type" : "boolean"
          },
          "codigo" : {
            "description" : "Los dos anteriores en el formato del SRI.",
            "example" : "001-001",
            "type" : "string"
          },
          "descripcion" : {
            "description" : "Descripción interna.",
            "example" : "Caja principal",
            "type" : "string"
          },
          "direccion" : {
            "description" : "Dirección del local.",
            "example" : "Av. Amazonas 1234, local 3",
            "type" : "string"
          },
          "emisorId" : {
            "description" : "El emisor del que cuelga.",
            "example" : "9f8c2d14-5b3a-4e77-9c21-0a6f4e8b1d33",
            "format" : "uuid",
            "type" : "string"
          },
          "establecimiento" : {
            "description" : "Código de establecimiento.",
            "example" : "001",
            "type" : "string"
          },
          "proximoSecuencial" : {
            "description" : "Número que llevará el próximo comprobante de esta serie. Avanza al emitir y no retrocede.",
            "example" : 42,
            "format" : "int64",
            "type" : "integer"
          },
          "puntoEmision" : {
            "description" : "Código de punto de emisión.",
            "example" : "001",
            "type" : "string"
          },
          "puntoEmisionId" : {
            "description" : "Identificador del punto de emisión. Es el que va en el cuerpo de la emisión.",
            "example" : "b1d60f38-9c45-4a2e-8f71-3e5c8a0b2947",
            "format" : "uuid",
            "type" : "string"
          },
          "referenciaExterna" : {
            "description" : "Tu identificador para esta caja.",
            "example" : "caja-principal",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "RespuestaError" : {
        "description" : "Cuerpo de toda respuesta de error, en formato `application/problem+json` (RFC 9457).\n\nEl campo que se programa es **`codigo`**: es estable y está en el catálogo de errores. El `detail` está escrito para personas y puede cambiar de redacción sin aviso, así que no conviene compararlo ni parsearlo.",
        "properties" : {
          "codigo" : {
            "description" : "El código estable del catálogo de errores. Es el campo contra el que se programa.",
            "example" : "CLAVE_IDEMPOTENCIA_AUSENTE",
            "type" : "string"
          },
          "detail" : {
            "description" : "Qué pasó en este caso concreto. Escrito para personas: **puede cambiar de redacción**, así que no conviene programar contra él",
            "example" : "Falta la cabecera Idempotency-Key",
            "type" : "string"
          },
          "instance" : {
            "description" : "La ruta que produjo el error",
            "example" : "/v1/emisores/9f8c2d14-5b3a-4e77-9c21-0a6f4e8b1d33/comprobantes",
            "format" : "uri",
            "type" : "string"
          },
          "status" : {
            "description" : "El código HTTP, repetido en el cuerpo",
            "example" : 400,
            "format" : "int32",
            "type" : "integer"
          },
          "title" : {
            "description" : "Resumen del error, para personas",
            "example" : "Falta la cabecera Idempotency-Key",
            "type" : "string"
          },
          "type" : {
            "description" : "URI del tipo de error. Resuelve a la página de ese código en el catálogo",
            "example" : "https://facturacion.code218.org/errores/clave-idempotencia-ausente",
            "format" : "uri",
            "type" : "string"
          }
        },
        "required" : [ "codigo" ]
      },
      "SecuencialResponse" : {
        "properties" : {
          "comprobanteId" : {
            "description" : "El comprobante que salió con este número, si lo hubo.",
            "example" : "3c7e9a52-18d4-4f60-b8e3-7d2a5c91f046",
            "format" : "uuid",
            "type" : "string"
          },
          "estado" : {
            "description" : "Qué pasó con el número. `EMITIDO` produjo comprobante, `FALLIDO` se quemó sin producirlo —son los huecos de la serie—, `EN_CONTINGENCIA` sigue sin resolverse y `RESERVADO` está en vuelo.",
            "enum" : [ "RESERVADO", "EMITIDO", "FALLIDO", "EN_CONTINGENCIA" ],
            "example" : "EMITIDO",
            "type" : "string"
          },
          "motivo" : {
            "description" : "Por qué se quemó el número, cuando el estado es `FALLIDO`. Es lo que explica el hueco ante el contador del contribuyente.",
            "example" : "El certificado del emisor está vencido",
            "type" : "string"
          },
          "numeroComprobante" : {
            "description" : "El número completo, con establecimiento y punto de emisión.",
            "example" : "001-001-000000042",
            "type" : "string"
          },
          "reservaId" : {
            "description" : "Identificador de la reserva de este número.",
            "example" : "7d4f1b90-2e63-4c58-9a07-5b1e3f8c62d4",
            "format" : "uuid",
            "type" : "string"
          },
          "reservadoEn" : {
            "description" : "Cuándo se reservó el número.",
            "example" : "2026-10-15T14:32:01-05:00",
            "format" : "date-time",
            "type" : "string"
          },
          "resueltoEn" : {
            "description" : "Cuándo quedó resuelto, o `null` si sigue en vuelo.",
            "example" : "2026-10-15T14:32:05-05:00",
            "format" : "date-time",
            "type" : "string"
          },
          "secuencial" : {
            "description" : "El número de la serie al que se refiere esta fila.",
            "example" : 42,
            "format" : "int64",
            "type" : "integer"
          }
        },
        "type" : "object"
      },
      "SolicitudEmision" : {
        "properties" : {
          "comprador" : {
            "$ref" : "#/components/schemas/CompradorRequest",
            "description" : "A quién se le factura."
          },
          "formaPago" : {
            "description" : "Forma de pago, según el catálogo del SRI. `SIN_UTILIZACION_SISTEMA_FINANCIERO` es el efectivo.",
            "enum" : [ "SIN_UTILIZACION_SISTEMA_FINANCIERO", "COMPENSACION_DEUDAS", "TARJETA_DEBITO", "DINERO_ELECTRONICO", "TARJETA_PREPAGO", "TARJETA_CREDITO", "OTROS_CON_UTILIZACION_SISTEMA_FINANCIERO", "ENDOSO_TITULOS" ],
            "example" : "SIN_UTILIZACION_SISTEMA_FINANCIERO",
            "type" : "string"
          },
          "items" : {
            "description" : "Las líneas del comprobante. Al menos una.",
            "items" : {
              "$ref" : "#/components/schemas/ItemRequest"
            },
            "minItems" : 1,
            "type" : "array"
          },
          "puntoEmisionId" : {
            "description" : "Punto de emisión desde el que sale el comprobante. Va en el cuerpo y no en la ruta porque es un dato del comprobante —de qué caja sale— y no del recurso sobre el que se opera.",
            "example" : "b1d60f38-9c45-4a2e-8f71-3e5c8a0b2947",
            "format" : "uuid",
            "type" : "string"
          }
        },
        "required" : [ "comprador", "formaPago", "items", "puntoEmisionId" ],
        "type" : "object"
      }
    },
    "securitySchemes" : {
      "credencialIntegrador" : {
        "description" : "Credencial del integrador, con el formato `fsri_<prefijo>_<secreto>`.\n\nSe entrega al dar de alta al integrador y existe completa una sola vez: no hay forma de recuperarla después. Si se pierde, se emite otra y se revoca la anterior.\n\nUn integrador puede tener varias credenciales vigentes a la vez, que es el estado normal mientras rota la que está en producción.",
        "scheme" : "bearer",
        "type" : "http"
      }
    }
  },
  "info" : {
    "contact" : {
      "name" : "code218",
      "url" : "https://facturacion.code218.org"
    },
    "description" : "Emisión de comprobantes electrónicos autorizados por el SRI de Ecuador, para integradores que facturan por cuenta de varios contribuyentes.\n\nEl servicio arma el XML, calcula la clave de acceso, firma con el certificado del emisor, transmite al SRI y genera el RIDE. El integrador manda los datos del comprobante; todo lo demás ocurre acá.\n\n**Tres resultados, y dos no son errores.** La emisión responde `201` si el SRI autorizó, `202` si no respondió y el comprobante quedó en contingencia, y `200` si el SRI lo rechazó. Un rechazo es una petición procesada correctamente cuyo resultado fue que no se autorizó: reintentarlo emite el mismo comprobante rechazado otra vez. Lo que corresponde es corregir los datos y emitir uno nuevo.\n\nEl ambiente —certificación o producción— es una propiedad del emisor, no de la URL. Se integra y se prueba contra este mismo servidor, con un emisor de prueba.",
    "title" : "API de Facturación Electrónica SRI",
    "version" : "1.0"
  },
  "openapi" : "3.1.0",
  "paths" : {
    "/v1/emisores" : {
      "get" : {
        "description" : "Resuelve un emisor por el identificador que le diste tú al negocio, para no tener que guardar nuestros UUID en tu base.\n\nLa referencia pertenece a tu espacio de nombres: dos integradores pueden usar la misma sin conflicto, y una que no asignaste tú simplemente no existe para ti.",
        "operationId" : "buscarEmisorPorReferenciaExterna",
        "parameters" : [ {
          "in" : "query",
          "name" : "referenciaExterna",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/EmisorResponse"
                }
              }
            },
            "description" : "El emisor con esa referencia"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`RECURSO_NO_ENCONTRADO` si no asignaste esa referencia a ningún emisor"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Buscar un emisor por tu referencia externa",
        "tags" : [ "Emisores" ]
      },
      "post" : {
        "description" : "Registra un contribuyente por cuya cuenta vas a facturar. Es el primer paso: sin emisor no hay puntos de emisión, ni certificado, ni emisión.\n\nNace en ambiente de **pruebas**. Para emitir le faltan todavía un punto de emisión y un certificado de firma cargado.\n\nUn RUC es un contribuyente y solo puede tener un emisor en todo el servicio: dos serían dos contadores de numeración para la misma serie ante el SRI.",
        "operationId" : "crearEmisor",
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/CrearEmisorRequest"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/EmisorResponse"
                }
              }
            },
            "description" : "Emisor registrado, en ambiente de pruebas"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`IDENTIFICACION_INVALIDA` si el RUC no es válido"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`EMISOR_DUPLICADO` si ese RUC ya tiene emisor, o `REFERENCIA_EXTERNA_DUPLICADA` si ya usaste esa referencia para otro"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Dar de alta un emisor",
        "tags" : [ "Emisores" ]
      }
    },
    "/v1/emisores/{emisorId}" : {
      "get" : {
        "description" : "Datos del emisor, su ambiente actual y el estado de su configuración.",
        "operationId" : "verEmisor",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/EmisorResponse"
                }
              }
            },
            "description" : "OK"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Consultar un emisor",
        "tags" : [ "Emisores" ]
      },
      "patch" : {
        "description" : "Cambia solo los campos que mandes. El RUC no se puede cambiar: un RUC distinto es otro contribuyente, y los comprobantes ya emitidos salieron con el anterior.",
        "operationId" : "actualizarEmisor",
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/ActualizarEmisorRequest"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/EmisorResponse"
                }
              }
            },
            "description" : "OK"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Actualizar un emisor",
        "tags" : [ "Emisores" ]
      }
    },
    "/v1/emisores/{emisorId}/ambiente" : {
      "post" : {
        "description" : "Cambia el ambiente del emisor. A partir de acá sus comprobantes se transmiten al SRI de verdad y el contribuyente responde por ellos.\n\n**No tiene vuelta atrás.** Un emisor en producción no puede volver a pruebas: el servicio seguiría respondiendo igual mientras los comprobantes se van a certificación, y el contribuyente se enteraría cuando el SRI le reclame los que creía haber emitido.\n\nLos comprobantes que emitió probando quedan marcados como de pruebas para siempre, y no se vuelven facturables.",
        "operationId" : "cambiarAmbienteEmisor",
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/CambiarAmbienteRequest"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/EmisorResponse"
                }
              }
            },
            "description" : "El emisor, ya en el ambiente nuevo"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`AMBIENTE_RETROCESO_NO_PERMITIDO` al intentar volver de producción a pruebas"
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`EMISOR_SIN_CONFIGURACION` si le falta algo obligatorio para operar"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Pasar un emisor a producción",
        "tags" : [ "Emisores" ]
      }
    },
    "/v1/emisores/{emisorId}/certificado" : {
      "get" : {
        "description" : "Titular, vencimiento y estado del certificado cargado. El archivo y su contraseña no se devuelven nunca.\n\nEl estado pasa a `POR_EXPIRAR` cuando le quedan 30 días o menos, el mismo umbral con el que se emite el evento `certificado.por_expirar`: no puede haber un certificado por expirar acá del que no hayas recibido aviso.\n\nUn certificado vencido deja al emisor sin poder emitir, así que vale la pena vigilarlo antes de que ocurra.",
        "operationId" : "verCertificado",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/CertificadoResponse"
                }
              }
            },
            "description" : "Estado del certificado"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CERTIFICADO_NO_CARGADO` si el emisor todavía no tiene certificado"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Consultar el certificado del emisor",
        "tags" : [ "Certificados" ]
      },
      "post" : {
        "description" : "Sube el archivo `.p12` del contribuyente y su contraseña. Sin certificado cargado y vigente el emisor no puede emitir, y es correcto que no pueda: la firma es lo que hace válido al comprobante.\n\nEl archivo se cifra en reposo y **no se puede volver a descargar**. La contraseña no aparece nunca en una respuesta ni en un log.\n\n**La trampa que más se confunde con un fallo nuestro:** un `.p12` autofirmado pasa esta validación —que comprueba que el archivo sirva para firmar, no que lo haya emitido una entidad acreditada— y después el SRI rechaza la firma. El emisor «funciona» hasta el último paso. El certificado tiene que ser real y del mismo RUC que emite: el SRI valida la firma contra el certificado, y el certificado contra el emisor.",
        "operationId" : "cargarCertificado",
        "parameters" : [ {
          "description" : "Contraseña con la que se abre el `.p12`",
          "in" : "query",
          "name" : "password",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "properties" : {
                  "archivo" : {
                    "description" : "El archivo `.p12` del contribuyente",
                    "format" : "binary",
                    "type" : "string"
                  }
                },
                "required" : [ "archivo" ],
                "type" : "object"
              }
            }
          }
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/CertificadoResponse"
                }
              }
            },
            "description" : "Certificado cargado. Devuelve titular y vencimiento, nunca el archivo"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`PETICION_MAL_FORMADA` si el archivo llegó vacío o no se pudo leer"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CERTIFICADO_INVALIDO` si el archivo no es un `.p12` legible, `CERTIFICADO_PASSWORD_INCORRECTA` si la contraseña no abre el archivo, `CERTIFICADO_SIN_CLAVE_PRIVADA` si no contiene una clave con la que firmar, o `CERTIFICADO_EXPIRADO` si ya venció"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Cargar el certificado de firma del emisor",
        "tags" : [ "Certificados" ]
      }
    },
    "/v1/emisores/{emisorId}/comprobantes" : {
      "get" : {
        "description" : "Qué se facturó en un rango de fechas. Es la consulta del cuadre, no la del día a día: responde «¿qué emitió esta caja en marzo?», que es lo que el contador cruza contra sus ventas.\n\nPagina por cursor, no por número de página: el recorrido tiene que ser fiable mientras el contribuyente sigue facturando. Se sigue mandando el `siguienteCursor` de la respuesta anterior tal cual.\n\nCada línea trae `creadoEn` —cuándo se transmitió— además de la fecha de autorización, y las dos hacen falta: un comprobante que estuvo en contingencia se autoriza horas más tarde, y al conciliar por rango hay que poder ver que su autorización cayó fuera del rango por el que apareció.\n\nNo incluye el motivo de rechazo: es un bloque de texto por comprobante y volvería ilegible el listado justo donde se lee en bloque. Para eso se consulta el comprobante concreto.",
        "operationId" : "listarComprobantes",
        "parameters" : [ {
          "description" : "Inicio del rango, ISO-8601 **con zona** (`2026-03-01T00:00:00-05:00`). La zona es obligatoria a propósito: sin ella habría que suponer el huso del contribuyente, y un comprobante emitido a las 23:30 caería en el día equivocado. Si no viene, los últimos 30 días",
          "in" : "query",
          "name" : "desde",
          "required" : false,
          "schema" : {
            "format" : "date-time",
            "type" : "string"
          }
        }, {
          "description" : "Fin del rango. Si no viene, ahora",
          "in" : "query",
          "name" : "hasta",
          "required" : false,
          "schema" : {
            "format" : "date-time",
            "type" : "string"
          }
        }, {
          "description" : "Filtra por resultado ante el SRI. El uso real es `?estado=EN_CONTINGENCIA`: lo que todavía no está resuelto",
          "in" : "query",
          "name" : "estado",
          "required" : false,
          "schema" : {
            "enum" : [ "AUTORIZADO", "RECHAZADO", "EN_CONTINGENCIA" ],
            "type" : "string"
          }
        }, {
          "description" : "Tamaño de página. Por defecto 50, tope 200",
          "in" : "query",
          "name" : "limite",
          "required" : false,
          "schema" : {
            "format" : "int32",
            "type" : "integer"
          }
        }, {
          "description" : "El `siguienteCursor` de la respuesta anterior, tal cual",
          "in" : "query",
          "name" : "cursor",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/PaginaComprobanteResumen"
                }
              }
            },
            "description" : "Una página del listado, con su cursor siguiente"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`RANGO_FECHAS_INVALIDO` si el rango está invertido o es más ancho que el tope. La corrección es partirlo en tramos y recorrerlos"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Listado de conciliación",
        "tags" : [ "Comprobantes" ]
      },
      "post" : {
        "description" : "Arma el XML, reserva el secuencial, firma con el certificado del emisor y transmite al SRI. Devuelve el resultado de ese intento.\n\n**Tres resultados, y dos no son errores.** El código HTTP los distingue, pero el cuerpo tiene una sola forma: `estado` dice en qué acabó.\n\n| Código | `estado` | Qué hacer |\n|---|---|---|\n| `201` | `AUTORIZADO` | Nada. Hay RIDE y XML descargables |\n| `202` | `EN_CONTINGENCIA` | Nada. No reenviar: se reintenta solo hasta 24 h |\n| `200` | `RECHAZADO` | Corregir los datos y emitir **otro** comprobante |\n\nReintentar un rechazo vuelve a emitir el mismo comprobante rechazado: lo que el SRI objetó son los datos, y el número ya se gastó. Un comprobante nuevo lleva un número nuevo.\n\nEl ambiente —certificación o producción— sale del emisor, no de esta petición, y viaja en la respuesta.",
        "operationId" : "emitirComprobante",
        "parameters" : [ {
          "description" : "Identificador del pedido en la plataforma del integrador. **Obligatoria**: sin ella la emisión responde 400 `CLAVE_IDEMPOTENCIA_AUSENTE`.\n\nReintentar con la misma clave y el mismo cuerpo devuelve el comprobante de la primera emisión en vez de emitir otro. Es lo que evita que un timeout reintentado produzca dos facturas autorizadas del mismo pedido.\n\nNo se normaliza: se usa tal como viene. Máximo 200 caracteres.",
          "in" : "header",
          "name" : "Idempotency-Key",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/SolicitudEmision"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "examples" : {
                  "Rechazado" : {
                    "description" : "Rechazado",
                    "value" : {
                      "ambiente" : "PRODUCCION",
                      "claveAcceso" : "1510202601179001234500120010010000000441234567811",
                      "comprobanteId" : "b1d60f38-9c45-4a2e-8f71-3e5c8a0b2947",
                      "estado" : "RECHAZADO",
                      "fechaAutorizacion" : null,
                      "motivoRechazo" : "IDENTIFICACION DEL COMPRADOR: El dato ingresado no cumple con una estructura valida",
                      "numeroAutorizacion" : null,
                      "numeroComprobante" : "001-001-000000044",
                      "primerIntento" : "2026-10-15T14:41:58-05:00"
                    }
                  }
                },
                "schema" : {
                  "$ref" : "#/components/schemas/ComprobanteResponse"
                }
              }
            },
            "description" : "El SRI rechazó el comprobante, con sus motivos sin traducir. **No es un error de la petición**: se procesó correctamente y el resultado fue que no se autorizó"
          },
          "201" : {
            "content" : {
              "application/json" : {
                "examples" : {
                  "Autorizado" : {
                    "description" : "Autorizado",
                    "value" : {
                      "ambiente" : "PRODUCCION",
                      "claveAcceso" : "1510202601179001234500120010010000000421234567810",
                      "comprobanteId" : "9f8c2d14-5b3a-4e77-9c21-0a6f4e8b1d33",
                      "estado" : "AUTORIZADO",
                      "fechaAutorizacion" : "2026-10-15T14:32:05-05:00",
                      "motivoRechazo" : null,
                      "numeroAutorizacion" : "1510202601179001234500120010010000000421234567810",
                      "numeroComprobante" : "001-001-000000042",
                      "primerIntento" : "2026-10-15T14:32:01-05:00"
                    }
                  }
                },
                "schema" : {
                  "$ref" : "#/components/schemas/ComprobanteResponse"
                }
              }
            },
            "description" : "El SRI autorizó el comprobante. Hay documentos entregables"
          },
          "202" : {
            "content" : {
              "application/json" : {
                "examples" : {
                  "En contingencia" : {
                    "description" : "En contingencia",
                    "value" : {
                      "ambiente" : "PRODUCCION",
                      "claveAcceso" : "1510202601179001234500120010010000000431234567816",
                      "comprobanteId" : "3c7e9a52-18d4-4f60-b8e3-7d2a5c91f046",
                      "estado" : "EN_CONTINGENCIA",
                      "fechaAutorizacion" : null,
                      "motivoRechazo" : null,
                      "numeroAutorizacion" : null,
                      "numeroComprobante" : "001-001-000000043",
                      "primerIntento" : "2026-10-15T14:35:12-05:00"
                    }
                  }
                },
                "schema" : {
                  "$ref" : "#/components/schemas/ComprobanteResponse"
                }
              }
            },
            "description" : "El SRI no respondió y el comprobante quedó en contingencia. No hay nada que corregir ni que reenviar: se reintenta solo durante 24 horas"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Emitir un comprobante",
        "tags" : [ "Comprobantes" ]
      }
    },
    "/v1/emisores/{emisorId}/comprobantes/por-clave-acceso/{claveAcceso}" : {
      "get" : {
        "description" : "El mismo comprobante, buscado por los 49 dígitos de su clave de acceso.\n\nExiste además de la consulta por identificador porque la clave de acceso es el identificador que circula **fuera** de este sistema: va impresa en el RIDE y es por la que pregunta el contador del contribuyente o el propio SRI. Nuestro identificador es interno y puedes no haberlo guardado.",
        "operationId" : "verComprobantePorClaveAcceso",
        "parameters" : [ {
          "description" : "Los 49 dígitos de la clave de acceso",
          "in" : "path",
          "name" : "claveAcceso",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ComprobanteResponse"
                }
              }
            },
            "description" : "El comprobante con esa clave de acceso"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`PETICION_MAL_FORMADA` si la clave no tiene 49 dígitos"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`RECURSO_NO_ENCONTRADO` si este emisor no emitió ese comprobante"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Consultar un comprobante por su clave de acceso",
        "tags" : [ "Comprobantes" ]
      }
    },
    "/v1/emisores/{emisorId}/comprobantes/{comprobanteId}" : {
      "get" : {
        "description" : "Estado actual del comprobante. **Siempre `200`**: acá el estado es un dato del recurso, no el resultado de una operación que se acaba de intentar.\n\nEs lo que hace útil al `202` de la emisión: un comprobante que quedó en contingencia se autoriza —o se rechaza— horas más tarde, desde el barrido de reintentos, y así se ve en qué acabó sin volver a emitir.",
        "operationId" : "verComprobante",
        "parameters" : [ {
          "in" : "path",
          "name" : "comprobanteId",
          "required" : true,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ComprobanteResponse"
                }
              }
            },
            "description" : "El comprobante, en el estado en que esté ahora"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`RECURSO_NO_ENCONTRADO`"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Consultar un comprobante emitido",
        "tags" : [ "Comprobantes" ]
      }
    },
    "/v1/emisores/{emisorId}/comprobantes/{comprobanteId}/ride" : {
      "get" : {
        "description" : "El RIDE es el documento que el contribuyente le entrega al comprador, con el código de barras de la clave de acceso.\n\nSe descarga aparte y no embebido en el JSON de consulta: un PDF en Base64 dentro de la respuesta de estado haría que toda consulta —incluida la que solo quiere saber si ya se autorizó— moviera medio megabyte.",
        "operationId" : "descargarRide",
        "parameters" : [ {
          "in" : "path",
          "name" : "comprobanteId",
          "required" : true,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/pdf" : {
                "schema" : {
                  "format" : "binary",
                  "type" : "string"
                }
              }
            },
            "description" : "El PDF, como adjunto"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`COMPROBANTE_NO_AUTORIZADO_AUN` si el comprobante todavía no tiene documentos: está en contingencia, o el SRI lo rechazó. No es un 404 —el comprobante existe y se consulta con normalidad— y en contingencia el documento puede existir más tarde sin que hagas nada"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Descargar el RIDE en PDF",
        "tags" : [ "Comprobantes" ]
      }
    },
    "/v1/emisores/{emisorId}/comprobantes/{comprobanteId}/xml" : {
      "get" : {
        "description" : "El XML tal como lo devolvió el SRI. Es el documento que el contribuyente está **obligado a conservar**, y no se puede reconstruir: lo emite el SRI al autorizar.\n\nViene con `charset=UTF-8` explícito, porque los nombres del comprador llevan tildes y eñes.",
        "operationId" : "descargarXmlAutorizado",
        "parameters" : [ {
          "in" : "path",
          "name" : "comprobanteId",
          "required" : true,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/xml" : {
                "schema" : {
                  "format" : "binary",
                  "type" : "string"
                }
              }
            },
            "description" : "El XML autorizado, como adjunto"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`COMPROBANTE_NO_AUTORIZADO_AUN` si el comprobante todavía no tiene documentos"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Descargar el XML autorizado",
        "tags" : [ "Comprobantes" ]
      }
    },
    "/v1/emisores/{emisorId}/puntos-emision" : {
      "get" : {
        "description" : "Todos los puntos de emisión del emisor, activos e inactivos, con el siguiente número de cada serie.",
        "operationId" : "listarPuntosEmision",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "items" : {
                    "$ref" : "#/components/schemas/PuntoEmisionResponse"
                  },
                  "type" : "array"
                }
              }
            },
            "description" : "OK"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Listar los puntos de emisión del emisor",
        "tags" : [ "Puntos de emisión" ]
      },
      "post" : {
        "description" : "Un punto de emisión es una caja o un local desde donde se factura, identificado por establecimiento y punto (`001-001`). Cada uno lleva su **propia serie de numeración**, independiente de las demás.\n\n**El secuencial inicial importa y no se puede corregir después.** Si el contribuyente ya facturaba por otro medio con esa misma serie, hay que arrancar en el número siguiente al último que emitió: empezar en uno repetiría números ya usados ante el SRI, y arrancar más arriba de la cuenta deja un hueco que el SRI le reclama a él.\n\nEl secuencial del SRI son 9 dígitos. Una serie que llega a 999999999 se terminó y hay que registrar otro punto de emisión: el número no puede dar la vuelta.",
        "operationId" : "crearPuntoEmision",
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/CrearPuntoEmisionRequest"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/PuntoEmisionResponse"
                }
              }
            },
            "description" : "Punto de emisión registrado, listo para emitir"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`PUNTO_EMISION_DUPLICADO` si el emisor ya tiene ese establecimiento y punto"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Registrar un punto de emisión",
        "tags" : [ "Puntos de emisión" ]
      }
    },
    "/v1/emisores/{emisorId}/puntos-emision/{puntoEmisionId}" : {
      "get" : {
        "operationId" : "verPuntoEmision",
        "parameters" : [ {
          "in" : "path",
          "name" : "puntoEmisionId",
          "required" : true,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/PuntoEmisionResponse"
                }
              }
            },
            "description" : "El punto de emisión"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`PUNTO_EMISION_FUERA_DEL_EMISOR` si existe pero cuelga de otro emisor"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Consultar un punto de emisión",
        "tags" : [ "Puntos de emisión" ]
      },
      "patch" : {
        "description" : "Permite desactivarlo, con lo que deja de poder emitir. Lo que **no** se puede cambiar es su numeración: un contador movido a mano es un hueco o un número repetido ante el SRI.",
        "operationId" : "actualizarPuntoEmision",
        "parameters" : [ {
          "in" : "path",
          "name" : "puntoEmisionId",
          "required" : true,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/ActualizarPuntoEmisionRequest"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/PuntoEmisionResponse"
                }
              }
            },
            "description" : "OK"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Actualizar un punto de emisión",
        "tags" : [ "Puntos de emisión" ]
      }
    },
    "/v1/emisores/{emisorId}/puntos-emision/{puntoEmisionId}/secuenciales" : {
      "get" : {
        "description" : "Qué pasó con cada número entregado de esta serie. Es para explicar un hueco en la numeración, que es la pregunta que llega cuando al contador del contribuyente le falta un comprobante en el cuadre.\n\nEl uso real es `?estado=FALLIDO`: los números que se quemaron sin producir comprobante. Un envío que no llegó a término gasta su número y **no se reutiliza**, así que no hay comprobante por el cual buscarlo —y por eso esta consulta no se puede derivar de la de comprobantes.\n\nSolo lectura. Los secuenciales se reservan y se resuelven durante la emisión: no hay forma de quemar ni de corregir un número a mano.",
        "operationId" : "listarSecuenciales",
        "parameters" : [ {
          "in" : "path",
          "name" : "puntoEmisionId",
          "required" : true,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        }, {
          "description" : "Filtra por lo que pasó con el número. `FALLIDO` son los huecos de esta serie",
          "in" : "query",
          "name" : "estado",
          "required" : false,
          "schema" : {
            "enum" : [ "RESERVADO", "EMITIDO", "FALLIDO", "EN_CONTINGENCIA" ],
            "type" : "string"
          }
        }, {
          "description" : "Tamaño de página. Por defecto 50, tope 200",
          "in" : "query",
          "name" : "limite",
          "required" : false,
          "schema" : {
            "format" : "int32",
            "type" : "integer"
          }
        }, {
          "description" : "El `siguienteCursor` de la respuesta anterior, tal cual",
          "in" : "query",
          "name" : "cursor",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/PaginaSecuencialResponse"
                }
              }
            },
            "description" : "OK"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Historial de numeración del punto de emisión",
        "tags" : [ "Numeración" ]
      }
    },
    "/v1/emisores/{emisorId}/puntos-emision/{puntoEmisionId}/secuenciales/{secuencial}" : {
      "get" : {
        "description" : "Qué pasó con el número N de este punto de emisión: si produjo un comprobante o si se quemó, y por qué.",
        "operationId" : "verSecuencial",
        "parameters" : [ {
          "in" : "path",
          "name" : "puntoEmisionId",
          "required" : true,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        }, {
          "in" : "path",
          "name" : "secuencial",
          "required" : true,
          "schema" : {
            "format" : "int64",
            "type" : "integer"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/SecuencialResponse"
                }
              }
            },
            "description" : "El estado de ese número"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`CREDENCIAL_INVALIDA`. La cabecera `Authorization` falta o está mal formada, o la credencial no existe, fue revocada, o su integrador está desactivado"
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`RECURSO_NO_ENCONTRADO` si esa serie nunca llegó a entregar ese número"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/RespuestaError"
                }
              }
            },
            "description" : "`LIMITE_EXCEDIDO`. Se excedió un cupo del control de uso. La cabecera `Retry-After` dice cuántos segundos esperar; repetir después la misma petición con la misma clave de idempotencia la completa, porque un 429 no consume número de la serie",
            "headers" : {
              "Retry-After" : {
                "description" : "Segundos que hay que esperar antes de repetir la petición",
                "schema" : {
                  "example" : 30
                }
              }
            }
          }
        },
        "summary" : "Consultar un número concreto de la serie",
        "tags" : [ "Numeración" ]
      }
    }
  },
  "security" : [ {
    "credencialIntegrador" : [ ]
  } ],
  "servers" : [ {
    "description" : "Servicio de facturación electrónica",
    "url" : "https://api.facturacion.code218.org"
  } ],
  "tags" : [ {
    "name" : "Emisores"
  }, {
    "name" : "Puntos de emisión"
  }, {
    "name" : "Certificados"
  }, {
    "name" : "Comprobantes"
  }, {
    "name" : "Numeración"
  } ],
  "webhooks" : {
    "certificado.expirado" : {
      "post" : {
        "description" : "Un certificado venció. El emisor no puede emitir hasta que se cargue uno nuevo.\n\n**Cómo se entrega.** Un `POST` a la URL que nos hayas dado, con estas cabeceras:\n\n| Cabecera | Qué lleva |\n|---|---|\n| `X-Code218-Event-Id` | Identificador del evento, **estable entre reintentos**. Es por donde se descartan duplicados |\n| `X-Code218-Timestamp` | Cuándo se firmó |\n| `X-Code218-Signature` | `HMAC-SHA256` sobre `timestamp + \".\" + cuerpo`, con el secreto compartido |\n\nHay que **rechazar la petición si el timestamp tiene más de 5 minutos**, o una firma capturada sirve para siempre.\n\n**Reintentos** con espera creciente —1 min, 5 min, 30 min, 2 h, 6 h— y se abandona a las 24 horas. Cualquier `2xx` cuenta como entregado.\n\n**El orden de llegada no se garantiza.** Un comprobante que pasó por contingencia genera dos eventos y pueden llegar al revés: el receptor resuelve por `ocurrioEn`, no por el orden en que los recibió.",
        "operationId" : "certificado.expirado",
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/EventoCertificado"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "2XX" : {
            "description" : "Cualquier 2xx cuenta como entregado y no se reintenta. Conviene responder rápido y procesar después: un receptor que tarda provoca reintentos que ya no hacían falta"
          }
        },
        "summary" : "certificado.expirado"
      }
    },
    "certificado.por_expirar" : {
      "post" : {
        "description" : "A un certificado le quedan 30, 15 o 5 días. Sale un aviso por hito, el más urgente que corresponda: uno cargado cuando ya le quedaban 10 días recibe el de 15, no los de 30 y 15 juntos.\n\nUn certificado vencido deja al contribuyente sin poder facturar, así que conviene actuar en el primer aviso.\n\n**Cómo se entrega.** Un `POST` a la URL que nos hayas dado, con estas cabeceras:\n\n| Cabecera | Qué lleva |\n|---|---|\n| `X-Code218-Event-Id` | Identificador del evento, **estable entre reintentos**. Es por donde se descartan duplicados |\n| `X-Code218-Timestamp` | Cuándo se firmó |\n| `X-Code218-Signature` | `HMAC-SHA256` sobre `timestamp + \".\" + cuerpo`, con el secreto compartido |\n\nHay que **rechazar la petición si el timestamp tiene más de 5 minutos**, o una firma capturada sirve para siempre.\n\n**Reintentos** con espera creciente —1 min, 5 min, 30 min, 2 h, 6 h— y se abandona a las 24 horas. Cualquier `2xx` cuenta como entregado.\n\n**El orden de llegada no se garantiza.** Un comprobante que pasó por contingencia genera dos eventos y pueden llegar al revés: el receptor resuelve por `ocurrioEn`, no por el orden en que los recibió.",
        "operationId" : "certificado.por_expirar",
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/EventoCertificado"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "2XX" : {
            "description" : "Cualquier 2xx cuenta como entregado y no se reintenta. Conviene responder rápido y procesar después: un receptor que tarda provoca reintentos que ya no hacían falta"
          }
        },
        "summary" : "certificado.por_expirar"
      }
    },
    "comprobante.autorizado" : {
      "post" : {
        "description" : "El SRI autorizó el comprobante. Hay RIDE y XML descargables.\n\n**Cómo se entrega.** Un `POST` a la URL que nos hayas dado, con estas cabeceras:\n\n| Cabecera | Qué lleva |\n|---|---|\n| `X-Code218-Event-Id` | Identificador del evento, **estable entre reintentos**. Es por donde se descartan duplicados |\n| `X-Code218-Timestamp` | Cuándo se firmó |\n| `X-Code218-Signature` | `HMAC-SHA256` sobre `timestamp + \".\" + cuerpo`, con el secreto compartido |\n\nHay que **rechazar la petición si el timestamp tiene más de 5 minutos**, o una firma capturada sirve para siempre.\n\n**Reintentos** con espera creciente —1 min, 5 min, 30 min, 2 h, 6 h— y se abandona a las 24 horas. Cualquier `2xx` cuenta como entregado.\n\n**El orden de llegada no se garantiza.** Un comprobante que pasó por contingencia genera dos eventos y pueden llegar al revés: el receptor resuelve por `ocurrioEn`, no por el orden en que los recibió.",
        "operationId" : "comprobante.autorizado",
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/EventoComprobante"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "2XX" : {
            "description" : "Cualquier 2xx cuenta como entregado y no se reintenta. Conviene responder rápido y procesar después: un receptor que tarda provoca reintentos que ya no hacían falta"
          }
        },
        "summary" : "comprobante.autorizado"
      }
    },
    "comprobante.en_contingencia" : {
      "post" : {
        "description" : "El SRI no respondió y el comprobante quedó en contingencia. Se reintenta solo durante 24 horas; cuando se resuelva llega un `comprobante.autorizado` o un `comprobante.rechazado` con la misma clave de acceso.\n\n**Cómo se entrega.** Un `POST` a la URL que nos hayas dado, con estas cabeceras:\n\n| Cabecera | Qué lleva |\n|---|---|\n| `X-Code218-Event-Id` | Identificador del evento, **estable entre reintentos**. Es por donde se descartan duplicados |\n| `X-Code218-Timestamp` | Cuándo se firmó |\n| `X-Code218-Signature` | `HMAC-SHA256` sobre `timestamp + \".\" + cuerpo`, con el secreto compartido |\n\nHay que **rechazar la petición si el timestamp tiene más de 5 minutos**, o una firma capturada sirve para siempre.\n\n**Reintentos** con espera creciente —1 min, 5 min, 30 min, 2 h, 6 h— y se abandona a las 24 horas. Cualquier `2xx` cuenta como entregado.\n\n**El orden de llegada no se garantiza.** Un comprobante que pasó por contingencia genera dos eventos y pueden llegar al revés: el receptor resuelve por `ocurrioEn`, no por el orden en que los recibió.",
        "operationId" : "comprobante.en_contingencia",
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/EventoComprobante"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "2XX" : {
            "description" : "Cualquier 2xx cuenta como entregado y no se reintenta. Conviene responder rápido y procesar después: un receptor que tarda provoca reintentos que ya no hacían falta"
          }
        },
        "summary" : "comprobante.en_contingencia"
      }
    },
    "comprobante.rechazado" : {
      "post" : {
        "description" : "El SRI rechazó el comprobante. `motivoRechazo` trae su texto sin traducir. No va a haber documentos: hay que corregir los datos y emitir otro comprobante, con otro número.\n\n**Cómo se entrega.** Un `POST` a la URL que nos hayas dado, con estas cabeceras:\n\n| Cabecera | Qué lleva |\n|---|---|\n| `X-Code218-Event-Id` | Identificador del evento, **estable entre reintentos**. Es por donde se descartan duplicados |\n| `X-Code218-Timestamp` | Cuándo se firmó |\n| `X-Code218-Signature` | `HMAC-SHA256` sobre `timestamp + \".\" + cuerpo`, con el secreto compartido |\n\nHay que **rechazar la petición si el timestamp tiene más de 5 minutos**, o una firma capturada sirve para siempre.\n\n**Reintentos** con espera creciente —1 min, 5 min, 30 min, 2 h, 6 h— y se abandona a las 24 horas. Cualquier `2xx` cuenta como entregado.\n\n**El orden de llegada no se garantiza.** Un comprobante que pasó por contingencia genera dos eventos y pueden llegar al revés: el receptor resuelve por `ocurrioEn`, no por el orden en que los recibió.",
        "operationId" : "comprobante.rechazado",
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/EventoComprobante"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "2XX" : {
            "description" : "Cualquier 2xx cuenta como entregado y no se reintenta. Conviene responder rápido y procesar después: un receptor que tarda provoca reintentos que ya no hacían falta"
          }
        },
        "summary" : "comprobante.rechazado"
      }
    }
  }
}
