{
  "info": {
    "_postman_id": "e1c2d3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
    "name": "Ecuafact API — Comprobantes Electronicos SRI (v1)",
    "description": {
      "content": "# Ecuafact API (v1) — Coleccion para integradores\n\nAPI REST para **emitir, consultar y dar seguimiento** a comprobantes electronicos. Envias JSON y la plataforma valida, firma y transmite al SRI, y genera el RIDE.\n\n## Que incluye\n- **00 · Inicio**: salud, contexto de la credencial y cupo.\n- **01 · Emitir**: factura, liquidacion de compra, nota de credito, nota de debito, guia de remision y retencion.\n- **02 · Seguimiento**: estado de una operacion.\n- **03 · Consultar**: comprobantes emitidos.\n- **04 · Errores**: ejemplos del contrato de error (401, 400, 409, 422, 429, 501).\n\n## Como empezar\n1. Importa esta coleccion y el environment `Ecuafact API — Plantilla`.\n2. Configura `baseUrl` (por defecto el API local `http://127.0.0.1:5197`; el equipo de Ecuafact te entrega la URL de pruebas).\n3. Pega tu `apiKey` en el environment. La credencial tiene el formato `lookup.secret`.\n4. Ajusta `identificacion` (10 primeros digitos del RUC), `ruc`, `estab` y `ptoEmi` de tu ambiente.\n5. Ejecuta **00 · Inicio** y luego **01 · Emitir**. Copia el `idOperacion` de la respuesta para **02 · Seguimiento**.\n\n## Autenticacion\nTodas las rutas `/v1` exigen la cabecera `X-Api-Key` (ya configurada en la coleccion). Ademas, la IP de origen debe estar autorizada para tu credencial. La ruta `/salud` es publica.\n\n## Convenciones\n- Rutas y propiedades en espanol ASCII, sin tildes.\n- Importes: numeros JSON decimales sin comillas, punto decimal.\n- Fechas fiscales: `dd/MM/yyyy`. Periodo: `MM/yyyy`.\n- Ambiente: lo determina la URL (`staging` = pruebas, `api` = produccion).\n- `Idempotency-Key` es **obligatoria** al emitir: si repites la misma clave con el mismo cuerpo, la API responde `202` con `codigo` `201` (reintento); con otro cuerpo responde `409`.\n- Emitir responde `202 Accepted` (admision durable), no autorizacion. El resultado final se consulta en **02 · Seguimiento**.\n\n## Respuesta de exito\nEmision y consumo son planas; las consultas de listado/contexto usan `{ \"datos\": { ... } }`.\n\n## Respuesta de error\n`{ \"codigo\": \"401\", \"mensaje\": \"Comprobante duplicado.\", \"errores\": [ \"...\" ] }` (`errores` solo en validacion; sin `estadoHttp`/`idSeguimiento`). El correlation id va en la cabecera `X-Correlation-Id`. Codigos HTTP: 400 validacion, 401 credencial, 403 alcance/IP, 404 no encontrado, 409 conflicto, 413 cuerpo excedido, 422 regla fiscal, 429 cupo o limite de solicitudes, 501 XML no implementado, 502/503/504 dependencia.",
      "type": "text/markdown"
    },
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "apikey",
    "apikey": [
      { "key": "key", "value": "X-Api-Key", "type": "string" },
      { "key": "value", "value": "{{apiKey}}", "type": "string" },
      { "key": "in", "value": "header", "type": "string" }
    ]
  },
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "// Fechas fiscales en horario Ecuador (UTC-5).",
          "const now = new Date(Date.now() - 5 * 60 * 60 * 1000);",
          "const dd = String(now.getUTCDate()).padStart(2, '0');",
          "const mm = String(now.getUTCMonth() + 1).padStart(2, '0');",
          "const yyyy = String(now.getUTCFullYear());",
          "pm.collectionVariables.set('fechaEmision', dd + '/' + mm + '/' + yyyy);",
          "pm.collectionVariables.set('periodoFiscal', mm + '/' + yyyy);",
          "pm.collectionVariables.set('fechaIso', yyyy + '-' + mm + '-' + dd);",
          "// Clave de idempotencia y referencia por defecto (la carpeta de emision las regenera).",
          "pm.collectionVariables.set('idempotencyKey', 'pm-' + pm.variables.replaceIn('{{$guid}}'));",
          "pm.collectionVariables.set('referenciaExterna', ('postman-' + Date.now().toString()).slice(0, 128));"
        ]
      }
    }
  ],
  "variable": [
    { "key": "baseUrl", "value": "http://127.0.0.1:5197", "type": "string", "description": "URL base del API. Local por defecto; el equipo de Ecuafact entrega la URL de pruebas y produccion." },
    { "key": "apiKey", "value": "", "type": "secret", "description": "Credencial de integracion (lookup.secret). Se entrega tras el registro y la aprobacion comercial. No la compartas." },
    { "key": "identificacion", "value": "0123456789", "type": "string", "description": "10 primeros digitos del RUC del contribuyente emisor." },
    { "key": "ruc", "value": "0123456789001", "type": "string", "description": "RUC completo (13 digitos) del emisor." },
    { "key": "estab", "value": "002", "type": "string", "description": "Codigo de establecimiento (3 digitos)." },
    { "key": "ptoEmi", "value": "001", "type": "string", "description": "Punto de emision (3 digitos)." },
    { "key": "idOperacion", "value": "", "type": "string", "description": "Se llena con la ultima emision (usado por Seguimiento)." },
    { "key": "idOperacion01", "value": "", "type": "string", "description": "idOperacion de la ultima factura." },
    { "key": "idOperacion03", "value": "", "type": "string", "description": "idOperacion de la ultima liquidacion de compra." },
    { "key": "idOperacion04", "value": "", "type": "string", "description": "idOperacion de la ultima nota de credito." },
    { "key": "idOperacion05", "value": "", "type": "string", "description": "idOperacion de la ultima nota de debito." },
    { "key": "idOperacion06", "value": "", "type": "string", "description": "idOperacion de la ultima guia de remision." },
    { "key": "idOperacion07", "value": "", "type": "string", "description": "idOperacion de la ultima retencion." },
    { "key": "fechaEmision", "value": "", "type": "string", "description": "Calculada por el script: dd/MM/yyyy (Ecuador)." },
    { "key": "periodoFiscal", "value": "", "type": "string", "description": "Calculada por el script: MM/yyyy." },
    { "key": "fechaIso", "value": "", "type": "string", "description": "Calculada por el script: yyyy-MM-dd." },
    { "key": "idempotencyKey", "value": "", "type": "string", "description": "Generada por el script por request. No la reutilices con otro cuerpo." },
    { "key": "referenciaExterna", "value": "", "type": "string", "description": "Generada por el script por request. Identificador propio e idempotente." }
  ],
  "item": [
    {
      "name": "00 · Inicio y diagnostico",
      "description": {
        "content": "Verifica que el servicio responde, que tu credencial es valida y cuanto cupo te queda en el despliegue.",
        "type": "text/markdown"
      },
      "item": [
        {
          "name": "00.1 · Salud del servicio (publico)",
          "auth": { "type": "noauth" },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Servicio activo (200)', function () {",
                  "  pm.response.to.have.status(200);",
                  "  pm.expect(pm.response.json().estado).to.eql('activo');",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": { "raw": "{{baseUrl}}/salud", "host": ["{{baseUrl}}"], "path": ["salud"] },
            "description": {
              "content": "Comprueba disponibilidad del API. **No requiere credencial.**\n\n- `GET /salud`\n- Respuesta `200`: `{ \"servicio\": \"EcuafactSRIApi\", \"estado\": \"activo\" }`",
              "type": "text/markdown"
            }
          },
          "response": [
            {
              "name": "200 · Servicio activo",
              "originalRequest": { "method": "GET", "header": [], "url": { "raw": "{{baseUrl}}/salud" } },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [{ "key": "Content-Type", "value": "application/json; charset=utf-8" }],
              "cookie": [],
              "body": "{\n  \"servicio\": \"EcuafactSRIApi\",\n  \"estado\": \"activo\"\n}"
            }
          ]
        },
        {
          "name": "00.2 · Contexto de la credencial",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('200 con datos', function () {",
                  "  pm.response.to.have.status(200);",
                  "  pm.expect(pm.response.json().datos).to.be.ok;",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": { "raw": "{{baseUrl}}/v1/contexto", "host": ["{{baseUrl}}"], "path": ["v1", "contexto"] },
            "description": {
              "content": "Devuelve los **RUC/servicios autorizados** de tu credencial y los servicios habilitados en el ambiente de la URL.\n\n- `GET /v1/contexto`\n- Cabecera: `X-Api-Key`.\n- `datos.contribuyentes[].identificacion` = 10 primeros digitos; `identificacionCompleta` = RUC de 13.\n- `puedeEmitir`, `puedeRecibir` y `tiposComprobante` del ambiente de la URL.",
              "type": "text/markdown"
            }
          },
          "response": [
            {
              "name": "200 · Contexto",
              "originalRequest": { "method": "GET", "header": [], "url": { "raw": "{{baseUrl}}/v1/contexto" } },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [{ "key": "Content-Type", "value": "application/json; charset=utf-8" }],
              "cookie": [],
              "body": "{\n  \"datos\": {\n    \"idCliente\": \"8f2b6c1a-0d3e-4a5b-9c7d-1e2f3a4b5c6d\",\n    \"nombre\": \"MI EMPRESA S.A.\",\n    \"contribuyentes\": [\n      {\n        \"identificacion\": \"0123456789\",\n        \"identificacionCompleta\": \"0123456789001\",\n        \"puedeEmitir\": true,\n        \"puedeRecibir\": false,\n        \"tiposComprobante\": [\"01\", \"03\", \"04\", \"05\", \"06\", \"07\"]\n      }\n    ]\n  }\n}"
            }
          ]
        },
        {
          "name": "00.3 · Cupo del despliegue",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('200 con datos', function () {",
                  "  pm.response.to.have.status(200);",
                  "  pm.expect(pm.response.json().limiteDocumentos).to.be.ok;",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/v1/consumo",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "consumo"],
              "query": []
            },
            "description": {
              "content": "Cupo efectivo del despliegue: **suma el plan y los paquetes** de documentos.\n\n- `GET /v1/consumo`\n- `limiteDocumentos`, `reservados`, `consumidos`, `disponibles` = total (plan + paquete).\n- `limiteExtra`, `reservadosExtra`, `consumidosExtra`, `disponiblesExtra` = solo el paquete.\n- `vigenteHasta` = vigencia del plan; sin plan (solo paquete) informa `9999-12-31`.\n\nCuando el cupo se agota, emitir responde `429` con codigo `quota_exhausted`.",
              "type": "text/markdown"
            }
          },
          "response": [
            {
              "name": "200 · Cupo",
              "originalRequest": { "method": "GET", "header": [], "url": { "raw": "{{baseUrl}}/v1/consumo" } },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [{ "key": "Content-Type", "value": "application/json; charset=utf-8" }],
              "cookie": [],
              "body": "{\n  \"limiteDocumentos\": 20,\n  \"reservados\": 0,\n  \"consumidos\": 0,\n  \"disponibles\": 20,\n  \"vigenteHasta\": \"2026-12-31T23:59:59\",\n  \"limiteExtra\": 0,\n  \"reservadosExtra\": 0,\n  \"consumidosExtra\": 0,\n  \"disponiblesExtra\": 0\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "01 · Emitir comprobantes",
      "description": {
        "content": "Emision de comprobantes. Todas usan el mismo endpoint; cambia `infoTributaria.codDoc` y el bloque de `info`.\n\n- `POST /v1/contribuyentes/{identificacion}/comprobantes`\n- Cabeceras: `Content-Type: application/json`, `X-Api-Key`, **`Idempotency-Key`** (obligatoria).\n- Respuesta `202 Accepted` (plana): `codigo` (`200` nueva, `201` reintento), `mensaje`, `idOperacion`, `urlEstado`, `uid`.\n- El resultado fiscal final se obtiene en **02 · Seguimiento**.\n\nLa coleccion genera automaticamente `Idempotency-Key` y `referenciaExterna` por request.",
        "type": "text/markdown"
      },
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Clave de idempotencia y referencia unicas por request.",
              "pm.collectionVariables.set('idempotencyKey', 'pm-' + pm.variables.replaceIn('{{$guid}}'));",
              "const stamp = Date.now().toString();",
              "const name = String(pm.info.requestName || 'doc').replace(/\\s+/g, '-').slice(0, 40);",
              "pm.collectionVariables.set('referenciaExterna', ('postman-' + stamp + '-' + name).slice(0, 128));"
            ]
          }
        }
      ],
      "item": [
        {
          "name": "01.1 · Factura (codDoc=01)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('202 Aceptado', function () { pm.response.to.have.status(202); });",
                  "const json = pm.response.json();",
                  "pm.test('idOperacion', function () {",
                  "  pm.expect(json.idOperacion).to.be.ok;",
                  "  pm.expect(json.idOperacion).to.be.ok;",
                  "});",
                  "if (json && json.idOperacion) {",
                  "  pm.environment.set('idOperacion', json.idOperacion);",
                  "  pm.environment.set('idOperacion01', json.idOperacion);",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Idempotency-Key", "value": "{{idempotencyKey}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"origenReferencia\": \"Postman\",\n  \"referenciaExterna\": \"{{referenciaExterna}}\",\n  \"infoTributaria\": {\n    \"ruc\": \"{{ruc}}\",\n    \"codDoc\": \"01\",\n    \"estab\": \"{{estab}}\",\n    \"ptoEmi\": \"{{ptoEmi}}\"\n  },\n  \"infoAdicional\": [\n    { \"nombre\": \"Prueba\", \"valor\": \"POSTMAN - AMBIENTE DE PRUEBAS\" }\n  ],\n  \"detalles\": [\n    {\n      \"codigoPrincipal\": \"API-TEST-01\",\n      \"descripcion\": \"DOCUMENTO DE PRUEBA INTEGRACION\",\n      \"cantidad\": 1,\n      \"precioUnitario\": 1,\n      \"descuento\": 0,\n      \"precioTotalSinImpuesto\": 1,\n      \"impuestos\": [\n        { \"codigo\": \"2\", \"codigoPorcentaje\": \"0\", \"tarifa\": 0, \"baseImponible\": 1, \"valor\": 0 }\n      ]\n    }\n  ],\n  \"info\": {\n    \"fechaEmision\": \"{{fechaEmision}}\",\n    \"dirEstablecimiento\": \"DIRECCION DE PRUEBAS\",\n    \"tipoIdentificacionComprador\": \"05\",\n    \"identificacionComprador\": \"0123456789\",\n    \"razonSocialComprador\": \"CONTRIBUYENTE DE PRUEBAS\",\n    \"direccionComprador\": \"DIRECCION DE PRUEBAS\",\n    \"totalSinImpuestos\": 1,\n    \"moneda\": \"DOLAR\",\n    \"totalDescuento\": 0,\n    \"totalConImpuestos\": [\n      { \"codigo\": \"2\", \"codigoPorcentaje\": \"0\", \"baseImponible\": 1, \"valor\": 0 }\n    ],\n    \"importeTotal\": 1,\n    \"propina\": 0,\n    \"pagos\": [\n      { \"formaPago\": \"01\", \"total\": 1, \"plazo\": 0, \"unidadTiempo\": \"dias\" }\n    ]\n  }\n}",
              "options": { "raw": { "language": "json" } }
            },
            "url": {
              "raw": "{{baseUrl}}/v1/contribuyentes/{{identificacion}}/comprobantes",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "contribuyentes", "{{identificacion}}", "comprobantes"]
            },
            "description": {
              "content": "**Factura electronica (01).**\n\n- `info` (solo 01): `fechaEmision`, datos del comprador (`tipoIdentificacionComprador`, `identificacionComprador`, `razonSocialComprador`), totales (`totalSinImpuestos`, `totalDescuento`, `totalConImpuestos`, `importeTotal`, `moneda`), `propina` y `pagos`.\n- `detalles[]`: `codigoPrincipal`, `descripcion`, `cantidad`, `precioUnitario`, `descuento`, `precioTotalSinImpuesto`, `impuestos[]`.\n- Los totales deben cuadrar (base + impuestos = total) antes de reservar cupo.\n\n**Respuestas tipicas:** `202` aceptado; `400` (`codigo` `301`) sin `Idempotency-Key` o formato invalido; `403` conflicto de idempotencia; `422` regla fiscal; `429` (`codigo` `501`) cupo agotado.",
              "type": "text/markdown"
            }
          },
          "response": [
            {
              "name": "202 · Operacion aceptada",
              "originalRequest": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "url": { "raw": "{{baseUrl}}/v1/contribuyentes/{{identificacion}}/comprobantes" }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                { "key": "Content-Type", "value": "application/json; charset=utf-8" },
                { "key": "X-Correlation-Id", "value": "0HN7EXAMPLE0001" }
              ],
              "cookie": [],
              "body": "{\n  \"codigo\": \"200\",\n  \"mensaje\": \"Operacion exitosa.\",\n  \"idOperacion\": \"3f1c8f2e-9d4a-4f6b-9c2e-1a2b3c4d5e6f\",\n  \"urlEstado\": \"/v1/operaciones/3f1c8f2e-9d4a-4f6b-9c2e-1a2b3c4d5e6f\"\n}"
            },
            {
              "name": "409 · Conflicto de idempotencia",
              "originalRequest": {
                "method": "POST",
                "header": [{ "key": "Idempotency-Key", "value": "<misma clave, cuerpo distinto>" }],
                "url": { "raw": "{{baseUrl}}/v1/contribuyentes/{{identificacion}}/comprobantes" }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [{ "key": "Content-Type", "value": "application/json; charset=utf-8" }],
              "cookie": [],
              "body": "{\n  \"codigo\": \"403\",\n  \"mensaje\": \"Conflicto de idempotencia o referencia.\"\n}"
            }
          ]
        },
        {
          "name": "01.2 · Liquidacion de compra (codDoc=03)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('202 Aceptado', function () { pm.response.to.have.status(202); });",
                  "const json = pm.response.json();",
                  "if (json && json.idOperacion) {",
                  "  pm.environment.set('idOperacion', json.idOperacion);",
                  "  pm.environment.set('idOperacion03', json.idOperacion);",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Idempotency-Key", "value": "{{idempotencyKey}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"origenReferencia\": \"Postman\",\n  \"referenciaExterna\": \"{{referenciaExterna}}\",\n  \"infoTributaria\": {\n    \"ruc\": \"{{ruc}}\",\n    \"codDoc\": \"03\",\n    \"estab\": \"{{estab}}\",\n    \"ptoEmi\": \"{{ptoEmi}}\"\n  },\n  \"infoAdicional\": [\n    { \"nombre\": \"Prueba\", \"valor\": \"POSTMAN - AMBIENTE DE PRUEBAS\" }\n  ],\n  \"detalles\": [\n    {\n      \"codigoPrincipal\": \"API-TEST-01\",\n      \"descripcion\": \"DOCUMENTO DE PRUEBA INTEGRACION\",\n      \"cantidad\": 1,\n      \"precioUnitario\": 1,\n      \"descuento\": 0,\n      \"precioTotalSinImpuesto\": 1,\n      \"impuestos\": [\n        { \"codigo\": \"2\", \"codigoPorcentaje\": \"0\", \"tarifa\": 0, \"baseImponible\": 1, \"valor\": 0 }\n      ]\n    }\n  ],\n  \"info\": {\n    \"fechaEmision\": \"{{fechaEmision}}\",\n    \"dirEstablecimiento\": \"DIRECCION DE PRUEBAS\",\n    \"tipoIdentificacionProveedor\": \"05\",\n    \"identificacionProveedor\": \"0123456789\",\n    \"razonSocialProveedor\": \"CONTRIBUYENTE DE PRUEBAS\",\n    \"direccionProveedor\": \"DIRECCION DE PRUEBAS\",\n    \"totalSinImpuestos\": 1,\n    \"moneda\": \"DOLAR\",\n    \"totalDescuento\": 0,\n    \"totalConImpuestos\": [\n      { \"codigo\": \"2\", \"codigoPorcentaje\": \"0\", \"baseImponible\": 1, \"valor\": 0 }\n    ],\n    \"importeTotal\": 1,\n    \"pagos\": [\n      { \"formaPago\": \"01\", \"total\": 1, \"plazo\": 0, \"unidadTiempo\": \"dias\" }\n    ]\n  }\n}",
              "options": { "raw": { "language": "json" } }
            },
            "url": {
              "raw": "{{baseUrl}}/v1/contribuyentes/{{identificacion}}/comprobantes",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "contribuyentes", "{{identificacion}}", "comprobantes"]
            },
            "description": {
              "content": "**Liquidacion de compra de bienes y prestacion de servicios (03).**\n\n- `info` (solo 03): datos del **proveedor** (`tipoIdentificacionProveedor`, `identificacionProveedor`, `razonSocialProveedor`), totales, `moneda` y `pagos`.\n- Usa `detalles[]` igual que la factura.\n\n**Errores tipicos:** `422` por descuadre de totales o campo no modelado.",
              "type": "text/markdown"
            }
          }
        },
        {
          "name": "01.3 · Nota de credito (codDoc=04)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('202 Aceptado', function () { pm.response.to.have.status(202); });",
                  "const json = pm.response.json();",
                  "if (json && json.idOperacion) {",
                  "  pm.environment.set('idOperacion', json.idOperacion);",
                  "  pm.environment.set('idOperacion04', json.idOperacion);",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Idempotency-Key", "value": "{{idempotencyKey}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"origenReferencia\": \"Postman\",\n  \"referenciaExterna\": \"{{referenciaExterna}}\",\n  \"infoTributaria\": {\n    \"ruc\": \"{{ruc}}\",\n    \"codDoc\": \"04\",\n    \"estab\": \"{{estab}}\",\n    \"ptoEmi\": \"{{ptoEmi}}\"\n  },\n  \"infoAdicional\": [\n    { \"nombre\": \"Prueba\", \"valor\": \"POSTMAN - AMBIENTE DE PRUEBAS\" }\n  ],\n  \"detalles\": [\n    {\n      \"codigoInterno\": \"API-TEST-01\",\n      \"descripcion\": \"DOCUMENTO DE PRUEBA INTEGRACION\",\n      \"cantidad\": 1,\n      \"precioUnitario\": 1,\n      \"descuento\": 0,\n      \"precioTotalSinImpuesto\": 1,\n      \"impuestos\": [\n        { \"codigo\": \"2\", \"codigoPorcentaje\": \"0\", \"tarifa\": 0, \"baseImponible\": 1, \"valor\": 0 }\n      ]\n    }\n  ],\n  \"info\": {\n    \"fechaEmision\": \"{{fechaEmision}}\",\n    \"dirEstablecimiento\": \"DIRECCION DE PRUEBAS\",\n    \"tipoIdentificacionComprador\": \"05\",\n    \"identificacionComprador\": \"0123456789\",\n    \"razonSocialComprador\": \"CONTRIBUYENTE DE PRUEBAS\",\n    \"direccionComprador\": \"DIRECCION DE PRUEBAS\",\n    \"totalSinImpuestos\": 1,\n    \"moneda\": \"DOLAR\",\n    \"codDocModificado\": \"01\",\n    \"numDocModificado\": \"002-001-000000002\",\n    \"fechaEmisionDocSustento\": \"{{fechaEmision}}\",\n    \"totalConImpuestos\": [\n      { \"codigo\": \"2\", \"codigoPorcentaje\": \"0\", \"baseImponible\": 1, \"valor\": 0 }\n    ],\n    \"valorModificacion\": 1,\n    \"motivo\": \"DEVOLUCION DE PRUEBAS\"\n  }\n}",
              "options": { "raw": { "language": "json" } }
            },
            "url": {
              "raw": "{{baseUrl}}/v1/contribuyentes/{{identificacion}}/comprobantes",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "contribuyentes", "{{identificacion}}", "comprobantes"]
            },
            "description": {
              "content": "**Nota de credito (04).**\n\n- `info` (solo 04): datos del comprador, `codDocModificado`, `numDocModificado` (`ddd-ddd-ddddddddd`), `fechaEmisionDocSustento`, totales, `valorModificacion` y `motivo`.\n- `detalles[]` usa `codigoInterno`. Documenta el sustento que modifica.",
              "type": "text/markdown"
            }
          }
        },
        {
          "name": "01.4 · Nota de debito (codDoc=05)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('202 Aceptado', function () { pm.response.to.have.status(202); });",
                  "const json = pm.response.json();",
                  "if (json && json.idOperacion) {",
                  "  pm.environment.set('idOperacion', json.idOperacion);",
                  "  pm.environment.set('idOperacion05', json.idOperacion);",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Idempotency-Key", "value": "{{idempotencyKey}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"origenReferencia\": \"Postman\",\n  \"referenciaExterna\": \"{{referenciaExterna}}\",\n  \"infoTributaria\": {\n    \"ruc\": \"{{ruc}}\",\n    \"codDoc\": \"05\",\n    \"estab\": \"{{estab}}\",\n    \"ptoEmi\": \"{{ptoEmi}}\"\n  },\n  \"infoAdicional\": [\n    { \"nombre\": \"Prueba\", \"valor\": \"POSTMAN - AMBIENTE DE PRUEBAS\" }\n  ],\n  \"motivos\": [\n    { \"razon\": \"AJUSTE DE PRUEBAS\", \"valor\": 1 }\n  ],\n  \"info\": {\n    \"fechaEmision\": \"{{fechaEmision}}\",\n    \"dirEstablecimiento\": \"DIRECCION DE PRUEBAS\",\n    \"tipoIdentificacionComprador\": \"05\",\n    \"identificacionComprador\": \"0123456789\",\n    \"razonSocialComprador\": \"CONTRIBUYENTE DE PRUEBAS\",\n    \"direccionComprador\": \"DIRECCION DE PRUEBAS\",\n    \"totalSinImpuestos\": 1,\n    \"moneda\": \"DOLAR\",\n    \"codDocModificado\": \"01\",\n    \"numDocModificado\": \"002-001-000000002\",\n    \"fechaEmisionDocSustento\": \"{{fechaEmision}}\",\n    \"valorTotal\": 1,\n    \"impuestos\": [\n      { \"codigo\": \"2\", \"codigoPorcentaje\": \"0\", \"tarifa\": 0, \"baseImponible\": 1, \"valor\": 0 }\n    ],\n    \"pagos\": [\n      { \"formaPago\": \"01\", \"total\": 1, \"plazo\": 0, \"unidadTiempo\": \"dias\" }\n    ]\n  }\n}",
              "options": { "raw": { "language": "json" } }
            },
            "url": {
              "raw": "{{baseUrl}}/v1/contribuyentes/{{identificacion}}/comprobantes",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "contribuyentes", "{{identificacion}}", "comprobantes"]
            },
            "description": {
              "content": "**Nota de debito (05).**\n\n- `motivos[]` con `{ razon, valor }` (coleccion propia del 05).\n- `info` (solo 05): comprador, `codDocModificado`, `numDocModificado`, `fechaEmisionDocSustento`, `valorTotal`, `impuestos[]` y `pagos[]`.",
              "type": "text/markdown"
            }
          }
        },
        {
          "name": "01.5 · Guia de remision (codDoc=06)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('202 Aceptado', function () { pm.response.to.have.status(202); });",
                  "const json = pm.response.json();",
                  "if (json && json.idOperacion) {",
                  "  pm.environment.set('idOperacion', json.idOperacion);",
                  "  pm.environment.set('idOperacion06', json.idOperacion);",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Idempotency-Key", "value": "{{idempotencyKey}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"origenReferencia\": \"Postman\",\n  \"referenciaExterna\": \"{{referenciaExterna}}\",\n  \"infoTributaria\": {\n    \"ruc\": \"{{ruc}}\",\n    \"codDoc\": \"06\",\n    \"estab\": \"{{estab}}\",\n    \"ptoEmi\": \"{{ptoEmi}}\"\n  },\n  \"infoAdicional\": [\n    { \"nombre\": \"Prueba\", \"valor\": \"POSTMAN - AMBIENTE DE PRUEBAS\" }\n  ],\n  \"destinatarios\": [\n    {\n      \"identificacionDestinatario\": \"0123456789\",\n      \"razonSocialDestinatario\": \"CONTRIBUYENTE DE PRUEBAS\",\n      \"dirDestinatario\": \"DESTINO PRUEBAS\",\n      \"motivoTraslado\": \"TRASLADO DE PRUEBAS\",\n      \"codEstabDestino\": \"001\",\n      \"ruta\": \"RUTA DE PRUEBAS\",\n      \"detalles\": [\n        { \"codigoInterno\": \"API-TEST-01\", \"descripcion\": \"TRASLADO DE PRUEBA\", \"cantidad\": 1 }\n      ]\n    }\n  ],\n  \"info\": {\n    \"dirEstablecimiento\": \"DIRECCION DE PRUEBAS\",\n    \"dirPartida\": \"ORIGEN PRUEBAS\",\n    \"razonSocialTransportista\": \"CONDUCTOR DE PRUEBAS\",\n    \"tipoIdentificacionTransportista\": \"05\",\n    \"rucTransportista\": \"0123456789\",\n    \"fechaIniTransporte\": \"{{fechaEmision}}\",\n    \"fechaFinTransporte\": \"{{fechaEmision}}\",\n    \"placa\": \"PBA0001\"\n  }\n}",
              "options": { "raw": { "language": "json" } }
            },
            "url": {
              "raw": "{{baseUrl}}/v1/contribuyentes/{{identificacion}}/comprobantes",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "contribuyentes", "{{identificacion}}", "comprobantes"]
            },
            "description": {
              "content": "**Guia de remision (06).**\n\n- `info` (solo 06): `dirPartida`, transportista (`razonSocialTransportista`, `tipoIdentificacionTransportista`, `rucTransportista`), `fechaIniTransporte`, `fechaFinTransporte`, `placa`.\n- `destinatarios[]`: receptor, motivo de traslado y `detalles[]` (sin importes).",
              "type": "text/markdown"
            }
          }
        },
        {
          "name": "01.6 · Comprobante de retencion (codDoc=07)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('202 Aceptado', function () { pm.response.to.have.status(202); });",
                  "const json = pm.response.json();",
                  "if (json && json.idOperacion) {",
                  "  pm.environment.set('idOperacion', json.idOperacion);",
                  "  pm.environment.set('idOperacion07', json.idOperacion);",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Idempotency-Key", "value": "{{idempotencyKey}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"origenReferencia\": \"Postman\",\n  \"referenciaExterna\": \"{{referenciaExterna}}\",\n  \"infoTributaria\": {\n    \"ruc\": \"{{ruc}}\",\n    \"codDoc\": \"07\",\n    \"estab\": \"{{estab}}\",\n    \"ptoEmi\": \"{{ptoEmi}}\"\n  },\n  \"infoAdicional\": [\n    { \"nombre\": \"Prueba\", \"valor\": \"POSTMAN - AMBIENTE DE PRUEBAS\" }\n  ],\n  \"docsSustento\": [\n    {\n      \"codSustento\": \"01\",\n      \"codDocSustento\": \"01\",\n      \"numDocSustento\": \"002001000000002\",\n      \"fechaEmisionDocSustento\": \"07/09/2026\",\n      \"fechaRegistroContable\": \"{{fechaEmision}}\",\n      \"numAutDocSustento\": \"0709202601012345678900110020010000000029846951114\",\n      \"pagoLocExt\": \"01\",\n      \"totalSinImpuestos\": 1,\n      \"importeTotal\": 1,\n      \"impuestosDocSustento\": [\n        { \"codImpuestoDocSustento\": \"2\", \"codigoPorcentaje\": \"0\", \"baseImponible\": 1, \"tarifa\": 0, \"valorImpuesto\": 0 }\n      ],\n      \"retenciones\": [\n        { \"codigo\": \"1\", \"codigoRetencion\": \"303\", \"baseImponible\": 1, \"porcentajeRetener\": 10, \"valorRetenido\": 0.10 }\n      ],\n      \"pagos\": [\n        { \"formaPago\": \"01\", \"total\": 1, \"plazo\": 0, \"unidadTiempo\": \"dias\" }\n      ]\n    }\n  ],\n  \"info\": {\n    \"fechaEmision\": \"{{fechaEmision}}\",\n    \"dirEstablecimiento\": \"DIRECCION DE PRUEBAS\",\n    \"tipoIdentificacionSujetoRetenido\": \"05\",\n    \"razonSocialSujetoRetenido\": \"CONTRIBUYENTE DE PRUEBAS\",\n    \"identificacionSujetoRetenido\": \"0123456789\",\n    \"parteRel\": \"NO\",\n    \"periodoFiscal\": \"{{periodoFiscal}}\"\n  }\n}",
              "options": { "raw": { "language": "json" } }
            },
            "url": {
              "raw": "{{baseUrl}}/v1/contribuyentes/{{identificacion}}/comprobantes",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "contribuyentes", "{{identificacion}}", "comprobantes"]
            },
            "description": {
              "content": "**Comprobante de retencion (07).**\n\n- `info` (solo 07): sujeto retenido (`tipoIdentificacionSujetoRetenido`, `identificacionSujetoRetenido`, `razonSocialSujetoRetenido`), `periodoFiscal` (`MM/yyyy`) y `parteRel`.\n- `docsSustento[]`: sustento electronico, impuestos del sustento y `retenciones[]` (`codigo` 1=IR, 2=IVA).",
              "type": "text/markdown"
            }
          }
        }
      ]
    },
    {
      "name": "02 · Seguimiento de operacion",
      "description": {
        "content": "Emitir responde `202` (aceptado), no autorizado. Aqui consultas el estado de la operacion.\n\nEstados de `datos.estado`: `en_cola`, `enviando`, `enviado`, `resultado_desconocido`, `cancelado`, `desconocido`.\nEstados de `datos.estadoAutorizacion`: `no_disponible`, `pendiente`, `autorizado`, `error`, `desconocido`.",
        "type": "text/markdown"
      },
      "item": [
        {
          "name": "02.1 · Ver operacion",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('200 con datos', function () {",
                  "  pm.response.to.have.status(200);",
                  "  pm.expect(pm.response.json().datos).to.be.ok;",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": { "raw": "{{baseUrl}}/v1/operaciones/{{idOperacion}}", "host": ["{{baseUrl}}"], "path": ["v1", "operaciones", "{{idOperacion}}"] },
            "description": {
              "content": "Lee el estado persistido de la operacion.\n\n- `GET /v1/operaciones/{idOperacion}`\n- `datos.estado` = avance del envio; `datos.estadoAutorizacion` = resultado fiscal.\n- `claveAcceso` aparece cuando el comprobante ya tiene clave.",
              "type": "text/markdown"
            }
          },
          "response": [
            {
              "name": "200 · En cola / pendiente",
              "originalRequest": { "method": "GET", "header": [], "url": { "raw": "{{baseUrl}}/v1/operaciones/{{idOperacion}}" } },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [{ "key": "Content-Type", "value": "application/json; charset=utf-8" }],
              "cookie": [],
              "body": "{\n  \"datos\": {\n    \"idOperacion\": \"3f1c8f2e-9d4a-4f6b-9c2e-1a2b3c4d5e6f\",\n    \"ambiente\": 1,\n    \"codDoc\": \"01\",\n    \"estado\": \"en_cola\",\n    \"claveAcceso\": null,\n    \"codigoError\": null,\n    \"fechaCreacion\": \"2026-09-25T15:04:05Z\",\n    \"fechaActualizacion\": \"2026-09-25T15:04:05Z\",\n    \"estadoAutorizacion\": \"pendiente\",\n    \"fechaAutorizacion\": null,\n    \"fechaConsulta\": null,\n    \"codigoErrorConsulta\": null\n  }\n}"
            },
            {
              "name": "200 · Autorizado",
              "originalRequest": { "method": "GET", "header": [], "url": { "raw": "{{baseUrl}}/v1/operaciones/{{idOperacion}}" } },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [{ "key": "Content-Type", "value": "application/json; charset=utf-8" }],
              "cookie": [],
              "body": "{\n  \"datos\": {\n    \"idOperacion\": \"3f1c8f2e-9d4a-4f6b-9c2e-1a2b3c4d5e6f\",\n    \"ambiente\": 1,\n    \"codDoc\": \"01\",\n    \"estado\": \"enviado\",\n    \"claveAcceso\": \"0709202601012345678900110020010000000029846951114\",\n    \"codigoError\": null,\n    \"fechaCreacion\": \"2026-09-25T15:04:05Z\",\n    \"fechaActualizacion\": \"2026-09-25T15:04:09Z\",\n    \"estadoAutorizacion\": \"autorizado\",\n    \"fechaAutorizacion\": \"2026-09-25T15:04:08Z\",\n    \"fechaConsulta\": \"2026-09-25T15:04:09Z\",\n    \"codigoErrorConsulta\": null\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "03 · Consultar documentos",
      "description": {
        "content": "Listados paginados de comprobantes **emitidos**.\n\n- Rango maximo: 366 dias. Sin fechas, ultimos 30 dias.\n- `pagina` 1..10000. `tamanoPagina`: 1..100.\n- `buscar` hasta 100 caracteres. `codDoc` filtra por tipo.\n- `fechaEmision` proviene de la clave de acceso.\n- La paginacion se aplica antes del filtrado fiscal: una pagina puede venir vacia con `hayMas=true`.",
        "type": "text/markdown"
      },
      "item": [
        {
          "name": "03.1 · Emitidos",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('200 con datos', function () {",
                  "  pm.response.to.have.status(200);",
                  "  pm.expect(pm.response.json().datos).to.be.ok;",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/v1/contribuyentes/{{identificacion}}/comprobantes/emitidos?desde=2026-01-01&hasta={{fechaIso}}&codDoc=&buscar=&pagina=1&tamanoPagina=20",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "contribuyentes", "{{identificacion}}", "comprobantes", "emitidos"],
              "query": [
                { "key": "desde", "value": "2026-01-01" },
                { "key": "hasta", "value": "{{fechaIso}}" },
                { "key": "codDoc", "value": "" },
                { "key": "buscar", "value": "" },
                { "key": "pagina", "value": "1" },
                { "key": "tamanoPagina", "value": "20" }
              ]
            },
            "description": {
              "content": "`GET /v1/contribuyentes/{identificacion}/comprobantes/emitidos`\n\nQuery: `desde`, `hasta` (`yyyy-MM-dd`), `codDoc`, `buscar`, `pagina`, `tamanoPagina`.",
              "type": "text/markdown"
            }
          },
          "response": [
            {
              "name": "200 · Pagina de emitidos",
              "originalRequest": { "method": "GET", "header": [], "url": { "raw": "{{baseUrl}}/v1/contribuyentes/0123456789/comprobantes/emitidos" } },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [{ "key": "Content-Type", "value": "application/json; charset=utf-8" }],
              "cookie": [],
              "body": "{\n  \"datos\": {\n    \"comprobantes\": [\n      {\n        \"claveAcceso\": \"0709202601012345678900110020010000000029846951114\",\n        \"numeroDocumento\": \"002-001-000000002\",\n        \"codDoc\": \"01\",\n        \"fechaEmision\": \"07/09/2026\",\n        \"identificacionContraparte\": \"0123456789\",\n        \"razonSocialContraparte\": \"CONTRIBUYENTE DE PRUEBAS\",\n        \"total\": 1.00,\n        \"estadoAutorizacion\": \"AUTORIZADO\",\n        \"fechaAutorizacion\": \"2026-09-07T10:15:00\",\n        \"codigoError\": null,\n        \"fechaExpress\": null\n      }\n    ],\n    \"pagina\": 1,\n    \"tamanoPagina\": 20,\n    \"hayMas\": false\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "04 · Errores y casos limite",
      "description": {
        "content": "Ejemplos para conocer el contrato de error. No son flujos de exito: al ejecutarlos veras el JSON de error real del API.\n\nFormato comun: `{ codigo, mensaje, errores[] }` (`errores` solo en validacion). Conserve el `X-Correlation-Id` de la cabecera para soporte.",
        "type": "text/markdown"
      },
      "item": [
        {
          "name": "04.1 · 401 sin credencial",
          "auth": { "type": "noauth" },
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": { "raw": "{{baseUrl}}/v1/contexto", "host": ["{{baseUrl}}"], "path": ["v1", "contexto"] },
            "description": {
              "content": "Peticion **sin** `X-Api-Key`. Respuesta `401` con codigo `invalid_credentials`. Ademas, tras varios intentos fallidos, el API aplica un bloqueo temporal por IP (`429 rate_limited` con `Retry-After`).",
              "type": "text/markdown"
            }
          },
          "response": [
            {
              "name": "401 · Credencial invalida",
              "originalRequest": { "method": "GET", "header": [], "url": { "raw": "{{baseUrl}}/v1/contexto" } },
              "status": "Unauthorized",
              "code": 401,
              "_postman_previewlanguage": "json",
              "header": [{ "key": "Content-Type", "value": "application/json; charset=utf-8" }],
              "cookie": [],
              "body": "{\n  \"codigo\": \"101\",\n  \"mensaje\": \"Credenciales invalidas.\"\n}"
            }
          ]
        },
        {
          "name": "04.2 · 400 falta Idempotency-Key",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"origenReferencia\": \"Postman\",\n  \"referenciaExterna\": \"error-idempotency\",\n  \"infoTributaria\": { \"ruc\": \"{{ruc}}\", \"codDoc\": \"01\", \"estab\": \"{{estab}}\", \"ptoEmi\": \"{{ptoEmi}}\" },\n  \"detalles\": [ { \"codigoPrincipal\": \"X\", \"descripcion\": \"X\", \"cantidad\": 1, \"precioUnitario\": 1, \"descuento\": 0, \"precioTotalSinImpuesto\": 1, \"impuestos\": [ { \"codigo\": \"2\", \"codigoPorcentaje\": \"0\", \"tarifa\": 0, \"baseImponible\": 1, \"valor\": 0 } ] } ],\n  \"info\": { \"fechaEmision\": \"{{fechaEmision}}\", \"tipoIdentificacionComprador\": \"05\", \"identificacionComprador\": \"0123456789\", \"razonSocialComprador\": \"X\", \"totalSinImpuestos\": 1, \"moneda\": \"DOLAR\", \"totalDescuento\": 0, \"totalConImpuestos\": [ { \"codigo\": \"2\", \"codigoPorcentaje\": \"0\", \"baseImponible\": 1, \"valor\": 0 } ], \"importeTotal\": 1, \"pagos\": [ { \"formaPago\": \"01\", \"total\": 1, \"plazo\": 0, \"unidadTiempo\": \"dias\" } ] }\n}",
              "options": { "raw": { "language": "json" } }
            },
            "url": {
              "raw": "{{baseUrl}}/v1/contribuyentes/{{identificacion}}/comprobantes",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "contribuyentes", "{{identificacion}}", "comprobantes"]
            },
            "description": {
              "content": "`Idempotency-Key` es **obligatoria** al emitir. Sin ella (o invalida) la API responde `400` (`codigo` `301`) con `errores` indicando `Idempotency-Key`.\n\nFormato esperado: ASCII estable, maximo 128 caracteres.",
              "type": "text/markdown"
            }
          },
          "response": [
            {
              "name": "400 · Solicitud invalida",
              "originalRequest": { "method": "POST", "header": [], "url": { "raw": "{{baseUrl}}/v1/contribuyentes/{{identificacion}}/comprobantes" } },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [{ "key": "Content-Type", "value": "application/json; charset=utf-8" }],
              "cookie": [],
              "body": "{\n  \"codigo\": \"301\",\n  \"mensaje\": \"Solicitud invalida.\",\n  \"errores\": [\n    \"Idempotency-Key: La cabecera Idempotency-Key es obligatoria.\"\n  ]\n}"
            }
          ]
        },
        {
          "name": "04.3 · 422 campo no soportado",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Idempotency-Key", "value": "{{idempotencyKey}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"version\": \"1\",\n  \"formato\": \"json\",\n  \"origenReferencia\": \"Postman\",\n  \"referenciaExterna\": \"error-campo\",\n  \"infoTributaria\": { \"ruc\": \"{{ruc}}\", \"codDoc\": \"01\", \"estab\": \"{{estab}}\", \"ptoEmi\": \"{{ptoEmi}}\" },\n  \"detalles\": [],\n  \"info\": { \"fechaEmision\": \"{{fechaEmision}}\", \"tipoIdentificacionComprador\": \"05\", \"identificacionComprador\": \"0123456789\", \"razonSocialComprador\": \"X\", \"totalSinImpuestos\": 1, \"moneda\": \"DOLAR\", \"totalDescuento\": 0, \"totalConImpuestos\": [], \"importeTotal\": 1, \"pagos\": [] }\n}",
              "options": { "raw": { "language": "json" } }
            },
            "url": {
              "raw": "{{baseUrl}}/v1/contribuyentes/{{identificacion}}/comprobantes",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "contribuyentes", "{{identificacion}}", "comprobantes"]
            },
            "description": {
              "content": "El sobre **no** admite `version` ni `formato` (los fija la plataforma). Su presencia responde `422` indicando el campo no soportado. El parser tambien rechaza campos desconocidos.",
              "type": "text/markdown"
            }
          },
          "response": [
            {
              "name": "422 · Campo no soportado",
              "originalRequest": { "method": "POST", "header": [], "url": { "raw": "{{baseUrl}}/v1/contribuyentes/{{identificacion}}/comprobantes" } },
              "status": "Unprocessable Entity",
              "code": 422,
              "_postman_previewlanguage": "json",
              "header": [{ "key": "Content-Type", "value": "application/json; charset=utf-8" }],
              "cookie": [],
              "body": "{\n  \"codigo\": \"302\",\n  \"mensaje\": \"Comprobante invalido.\",\n  \"errores\": [\n    \"$.info: Campo no soportado en este contrato.\"\n  ]\n}"
            }
          ]
        },
        {
          "name": "04.4 · 429 cupo agotado",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Idempotency-Key", "value": "{{idempotencyKey}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"origenReferencia\": \"Postman\",\n  \"referenciaExterna\": \"error-cupo\",\n  \"infoTributaria\": { \"ruc\": \"{{ruc}}\", \"codDoc\": \"01\", \"estab\": \"{{estab}}\", \"ptoEmi\": \"{{ptoEmi}}\" },\n  \"detalles\": [ { \"codigoPrincipal\": \"X\", \"descripcion\": \"X\", \"cantidad\": 1, \"precioUnitario\": 1, \"descuento\": 0, \"precioTotalSinImpuesto\": 1, \"impuestos\": [ { \"codigo\": \"2\", \"codigoPorcentaje\": \"0\", \"tarifa\": 0, \"baseImponible\": 1, \"valor\": 0 } ] } ],\n  \"info\": { \"fechaEmision\": \"{{fechaEmision}}\", \"tipoIdentificacionComprador\": \"05\", \"identificacionComprador\": \"0123456789\", \"razonSocialComprador\": \"X\", \"totalSinImpuestos\": 1, \"moneda\": \"DOLAR\", \"totalDescuento\": 0, \"totalConImpuestos\": [ { \"codigo\": \"2\", \"codigoPorcentaje\": \"0\", \"baseImponible\": 1, \"valor\": 0 } ], \"importeTotal\": 1, \"pagos\": [ { \"formaPago\": \"01\", \"total\": 1, \"plazo\": 0, \"unidadTiempo\": \"dias\" } ] }\n}",
              "options": { "raw": { "language": "json" } }
            },
            "url": {
              "raw": "{{baseUrl}}/v1/contribuyentes/{{identificacion}}/comprobantes",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "contribuyentes", "{{identificacion}}", "comprobantes"]
            },
            "description": {
              "content": "Si el cupo del despliegue esta agotado, emitir responde `429` con `quota_exhausted` y cabecera `Retry-After`. Consulta `/v1/consumo` para ver `disponibles`. El mismo `429` se usa para el limite de solicitudes por minuto (`rate_limited`).",
              "type": "text/markdown"
            }
          },
          "response": [
            {
              "name": "429 · Cupo agotado",
              "originalRequest": { "method": "POST", "header": [], "url": { "raw": "{{baseUrl}}/v1/contribuyentes/{{identificacion}}/comprobantes" } },
              "status": "Too Many Requests",
              "code": 429,
              "_postman_previewlanguage": "json",
              "header": [
                { "key": "Content-Type", "value": "application/json; charset=utf-8" },
                { "key": "Retry-After", "value": "60" }
              ],
              "cookie": [],
              "body": "{\n  \"codigo\": \"501\",\n  \"mensaje\": \"Cupo agotado.\"\n}"
            }
          ]
        },
        {
          "name": "04.5 · 501 XML no implementado",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/xml" },
              { "key": "Idempotency-Key", "value": "{{idempotencyKey}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<factura id=\"comprobante\" version=\"1.0.0\">\n  <infoTributaria>...</infoTributaria>\n</factura>"
            },
            "url": {
              "raw": "{{baseUrl}}/v1/contribuyentes/{{identificacion}}/comprobantes",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "contribuyentes", "{{identificacion}}", "comprobantes"]
            },
            "description": {
              "content": "El envio de **XML crudo** no esta implementado. Con `Content-Type: application/xml` o `text/xml` el API responde `501` con `sri_xml_not_implemented`, despues de autenticar y antes de reservar cupo. Usa el cuerpo **JSON**.",
              "type": "text/markdown"
            }
          },
          "response": [
            {
              "name": "501 · Implementacion pendiente",
              "originalRequest": { "method": "POST", "header": [], "url": { "raw": "{{baseUrl}}/v1/contribuyentes/{{identificacion}}/comprobantes" } },
              "status": "Not Implemented",
              "code": 501,
              "_postman_previewlanguage": "json",
              "header": [{ "key": "Content-Type", "value": "application/json; charset=utf-8" }],
              "cookie": [],
              "body": "{\n  \"codigo\": \"005\",\n  \"mensaje\": \"Funcionalidad no implementada.\"\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "05 · Consultas SRI",
      "item": [
        {
          "name": "Contribuyente por identificacion",
          "request": {
            "method": "GET",
            "header": [ { "key": "Accept", "value": "application/json" } ],
            "url": {
              "raw": "{{baseUrl}}/v1/consultas/contribuyentes/{{ruc}}?fusionar=true",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "consultas", "contribuyentes", "{{ruc}}"],
              "query": [ { "key": "fusionar", "value": "true" } ]
            },
            "description": { "content": "Datos del contribuyente por cedula, RUC o pasaporte. Respuesta plana (sin `datos`).", "type": "text/markdown" }
          }
        },
        {
          "name": "Contribuyentes por nombre",
          "request": {
            "method": "GET",
            "header": [ { "key": "Accept", "value": "application/json" } ],
            "url": {
              "raw": "{{baseUrl}}/v1/consultas/contribuyentes?apellidos=PEREZ%20LOPEZ&nombres=JUAN&clase=PersonaNatural&max=10",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "consultas", "contribuyentes"],
              "query": [
                { "key": "apellidos", "value": "PEREZ LOPEZ" },
                { "key": "nombres", "value": "JUAN" },
                { "key": "clase", "value": "PersonaNatural" },
                { "key": "max", "value": "10" }
              ]
            },
            "description": { "content": "`apellidos` es obligatorio. Devuelve un arreglo plano.", "type": "text/markdown" }
          }
        },
        {
          "name": "Establecimientos de un RUC",
          "request": {
            "method": "GET",
            "header": [ { "key": "Accept", "value": "application/json" } ],
            "url": {
              "raw": "{{baseUrl}}/v1/consultas/establecimientos/{{ruc}}?filtro=Todos",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "consultas", "establecimientos", "{{ruc}}"],
              "query": [ { "key": "filtro", "value": "Todos" } ]
            }
          }
        },
        {
          "name": "Validar identificacion",
          "request": {
            "method": "GET",
            "header": [ { "key": "Accept", "value": "application/json" } ],
            "url": {
              "raw": "{{baseUrl}}/v1/consultas/identificacion/validar/{{ruc}}",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "consultas", "identificacion", "validar", "{{ruc}}"]
            },
            "description": { "content": "Valida el formato sin red. Responde `200` tambien cuando no es valido: revise `valido`.", "type": "text/markdown" }
          }
        },
        {
          "name": "Decodificar clave de acceso",
          "request": {
            "method": "GET",
            "header": [ { "key": "Accept", "value": "application/json" } ],
            "url": {
              "raw": "{{baseUrl}}/v1/consultas/comprobantes/decodificar/{{claveAcceso}}",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "consultas", "comprobantes", "decodificar", "{{claveAcceso}}"]
            },
            "description": { "content": "Descompone una clave de 49 digitos. No prueba la autorizacion fiscal.", "type": "text/markdown" }
          }
        }
      ]
    }
  ]
}
