# Carpeta tributaria puntual

> Solicita el PDF original del SII mediante el widget y recibe el resultado por API o webhook.



Esta capacidad está en piloto y requiere habilitación de tu organización. El receptor se configura en el servidor y queda fijado al crear la solicitud. La autorización muestra esa institución; quien abre el enlace no puede cambiarla.

El widget conserva cuatro pantallas: autorización, credenciales de la empresa, verificación y confirmación. La confirmación significa que Emisso aceptó la solicitud; el PDF se obtiene en segundo plano.

Si incrustas el enlace, el mensaje `emisso:connect` con `status: "connected"` confirma esa aceptación,
sin esperar el PDF. Al pulsar **Continuar**, el retorno agrega `status=connected` y `connection_id` a
tu `redirect_uri`; salir antes de aceptar devuelve `status=failed`, sin ID de conexión. Sigue
consultando el ID de solicitud para conocer su resultado: salir de la pantalla no cancela el trabajo.
Recargar un acuse válido muestra la confirmación, sin volver a pedir la clave ni abrir acceso al SII.

## Crear una solicitud [#crear-una-solicitud]

La API key necesita `sii:carpeta_tributaria:generar`. La solicitud se crea con `POST /api/v1/connect_sessions`, con `mode: "create"`, `connector_code: "sii"` y el bloque `collection`. No admite conexión existente, `reauth`, `credential_scheme`, `emitir` ni `alcances`.

La cabecera `Idempotency-Key` es obligatoria: hasta 128 caracteres ASCII visibles, sin espacios. Usa una estable por solicitud y conserva la misma identidad de API key al reintentar. Repetirla con el mismo contenido devuelve el mismo enlace mientras la solicitud espera autorización; después devuelve los identificadores y el estado de esa solicitud, sin enlace ni token. Con contenido distinto devuelve `idempotency_conflict`. El enlace dura 24 horas y es secreto; no lo publiques ni lo registres en logs.

```js
const API = "https://connect.emisso.ai/api/v1";
const auth = { Authorization: `Bearer ${process.env.EMISSO_CONNECT_API_KEY}` };

const res = await fetch(`${API}/connect_sessions`, {
  method: "POST",
  headers: {
    ...auth,
    "Content-Type": "application/json",
    // Estable por solicitud: recupera el enlace pendiente o el estado de la solicitud ya aceptada.
    "Idempotency-Key": "application_42_carpeta_v1",
  },
  body: JSON.stringify({
    mode: "create",
    connector_code: "sii",
    collection: {
      kind: "sii_tax_folder",
      mode: "once",
      folder_type: "credit",
      expected_rut: "76123456-0",
      purpose: "Evaluación comercial solicitada por el cliente",
      external_reference: "application_42",
    },
    allowed_origins: ["https://tu-aplicacion.example"],
    redirect_uri: "https://tu-aplicacion.example/solicitud",
  }),
});
const { data: solicitud, error } = await res.json();
if (error) throw new Error(JSON.stringify(error));
// Guarda siempre solicitud.collection_request_id.
if (solicitud.url) {
  // Abre este enlace con el widget hosted mientras espera autorización.
} else {
  // Ya fue aceptada o terminó: consulta la solicitud existente, sin crear otra.
}
```

La respuesta (201) trae en `data` `collection_request_id` y `collection_status`. Al crearla o recuperar
el enlace pendiente también incluye la sesión con `url` y `expires_at`; el `status` de esa sesión no es
el estado de la carpeta. Después de aceptar el enlace, un reintento conserva los mismos identificadores
y devuelve `connection_id`, `document_id`, `error_code` y `expires_at`, sin recuperar el token.

## Consultar y descargar [#consultar-y-descargar]

```js
const id = solicitud.collection_request_id;
const consulta = await (await fetch(`${API}/collection_requests/${id}`, { headers: auth })).json();
if (consulta.error) throw new Error(JSON.stringify(consulta.error));
const resultado = consulta.data;
if (resultado.status === "ready" && resultado.document?.available) {
  const documento = resultado.document.id;
  const pedido = await (await fetch(`${API}/collection_documents/${documento}/download`, { headers: auth })).json();
  if (pedido.error) throw new Error(JSON.stringify(pedido.error));
  // pedido.data.url vence en pedido.data.expires_in segundos (300).
}
```

Endpoints: `GET /api/v1/collection_requests/:id` y `GET /api/v1/collection_documents/:id/download`. La descarga devuelve una URL firmada al PDF original privado. El resultado incluye SHA-256, tamaño, fecha de generación y retención. El archivo se elimina a los 30 días; los metadatos sensibles se purgan a los 90 días.

Emitir el enlace de descarga y cancelar efectivamente una solicitud quedan en la bitácora de control
con el actor y la credencial que los solicitaron. La URL firmada no se guarda en esa bitácora; ese
registro acredita la emisión del enlace, no que el destinatario haya descargado el archivo.

Estados: `awaiting_authorization`, `queued`, `processing`, `ready`, `failed`, `inconclusive`, `expired`, `canceled`. `inconclusive` significa que pudo ocurrir una emisión cuya respuesta no se confirmó, o que el SII ya generó la carpeta y Emisso no completó la entrega del PDF. Emisso no repite ese POST automáticamente: revisa el resultado antes de pedir otra carpeta. `expired` corresponde a una autorización vencida antes de iniciar la emisión.

`failed` indica una falla definitiva o intentos agotados antes de iniciar la emisión; `error_code` explica la causa. Si la entrega falla tras emitir, el estado es `inconclusive`, incluso cuando el código identifica un PDF inválido o un contribuyente distinto. Revisa la carpeta emitida: esos problemas no se solucionan generando otra.

`POST /api/v1/collection_requests/:id/cancel` cancela solicitudes que no están ejecutándose. Si hay trabajo activo devuelve `connection_busy`. Cancelar no revoca una carpeta emitida por el SII.

## Webhooks [#webhooks]

Suscribe `sii.carpeta_tributaria.ready` y `sii.carpeta_tributaria.failed` mediante la [configuración de webhooks](/docs/operar/webhooks) existente. `sii.carpeta_tributaria.failed` cubre todo final sin carpeta: `failed`, `inconclusive`, `expired` y `canceled`; el estado exacto viene en `data.status`. Usan la firma y los reintentos habituales. Deduplica por la cabecera `webhook-id` y consulta la API para recuperar el estado si el webhook no llega.

El evento contiene los identificadores de solicitud, sesión, conexión y documento, `external_reference`, estado, `identity_verified` y `error_code`. Emisso no agrega el PDF, el RUT del contribuyente, la contraseña, el código/clave del repositorio SII ni la URL firmada. Solo `ready` habilita la descarga.

Usa un identificador opaco en `external_reference`, como `application_42`: ese valor se copia al evento. No pongas un RUT ni otros datos personales; la purga de la carpeta no borra los eventos de webhook que ya se publicaron.

La conexión temporal sirve exclusivamente para esta solicitud. No permite RCV, emisión de DTE, sincronizaciones programadas ni renovar credenciales. El plazo de acceso de 15 minutos comienza con el primer intento de verificación y no se renueva al reintentar. El enlace admite hasta cinco intentos. Cerrar y purgar las credenciales precede al resultado terminal y su evento.


---

Esta página es parte de la documentación de Emisso Connect. El índice completo, con cada página y su descripción, está en https://connect.emisso.ai/llms.txt. Esta misma página en HTML: https://connect.emisso.ai/docs/como-consultar/carpeta-tributaria.
