Resumen ejecutivo
El SII dispone de varios servicios, no una sola API. A efectos de desarrollo web, la integración se divide en:
- DTE (facturas, notas, guías, etc.): servicios SOAP para Autenticación (semilla/token), Upload de envíos, Consulta Estado de Envío y Consulta Estado de DTE.
- Boleta Electrónica: servicios REST (documentados en Swagger) para autenticación, envío de boletas, consulta de estado de envío y de boletas. Requiere TLS 1.2+ y hasta 500 boletas por envío; el track-id de boleta tiene 15 dígitos.
- Registro de Aceptación/Reclamo (ACD, ERM, RCD, RFP, RFT): WebService para registrar/consultar eventos del DTE con reglas (por ejemplo, ventana de 8 días).
La documentación oficial de la API REST de Boleta está publicada en el portal Swagger del SII.
Mapa de servicios & ambientes
Ambientes y dominios más usados
- Autenticación SOAP (semilla/token):
https://palena.sii.cl/DTEWS/CrSeed.jws?WSDL
,https://palena.sii.cl/DTEWS/GetTokenFromSeed.jws?WSDL
. - Consulta Estado DTE (SOAP):
https://maullin.sii.cl/DTEWS/QueryEstDte.jws?WSDL
. - Consulta Estado de Envío DTE (SOAP):
https://maullin.sii.cl/DTEWS/QueryEstUp.jws?WSDL
. - Upload de DTE:
POST /cgi_dte/UPL/DTEUpload
(usar host del ambiente, p. ej.,palena
/maullin
). RequiereCookie: TOKEN=...
y camposrutSender
,dvSender
,rutCompany
,dvCompany
,archivo
. - Boleta REST (Swagger): portal de endpoints y modelos en
https://www4c.sii.cl/bolcoreinternetui/api/
.
Para formatos XML y anexos (DTE, EnvíoDTE, RVD), ver el Instructivo Técnico de DTE.
Requisitos previos
- Certificado digital (archivo
.p12/.pfx
) válido para el SII y usuario autorizado. - Servidor Web con PHP 8.x, extensiones
curl
,openssl
,soap
, y librería xmlseclibs (para firmas XMLDSIG). - Base de datos MySQL para persistir tokens/track-ids/logs.
- TLS 1.2 o superior en boleta REST (certificación y producción).
Arquitectura recomendada
- Módulo de autenticación: obtiene y cachea el token (SOAP para DTE; REST específico para Boleta). La semilla expira en ~2 minutos, por lo que debe usarse de inmediato para solicitar el token.
- Módulo de envío:
- DTE: POST multipart a
DTEUpload
conTOKEN
en cookie. - Boleta: endpoint REST de “envío de boletas” (ver Swagger). Límite 500 boletas por envío; diagnóstico por servicio REST.
- DTE: POST multipart a
- Módulo de consultas:
- Estado de envío (SOAP:
QueryEstUp
), Estado de DTE (SOAP:QueryEstDte
). - Boleta: REST para estado de envío y consulta de boleta (ver Swagger).
- Estado de envío (SOAP:
- Eventos del DTE (Aceptación/Reclamo): WS para
ingresarAceptacionReclamoDoc
,listarEventosHistDoc
,consultarDocDteCedible
,consultarFechaRecepcionSii
. Ventana de 8 días.
Esquema MySQL base
-- Tokens de autenticación (separar por ámbito)
CREATE TABLE sii_tokens (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
scope ENUM('DTE','BOLETA') NOT NULL,
token VARCHAR(500) NOT NULL,
issued_at DATETIME NOT NULL,
expires_at DATETIME NULL,
meta JSON NULL,
UNIQUE KEY uq_scope(scope)
);
-- Envíos (DTE y Boleta)
CREATE TABLE sii_envios (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
tipo ENUM('DTE','BOLETA') NOT NULL,
track_id VARCHAR(20) NULL,
estado VARCHAR(10) NULL,
glosa VARCHAR(255) NULL,
payload MEDIUMTEXT NULL,
respuesta MEDIUMTEXT NULL,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL
);
-- Documentos DTE/Boleta (cabecera mínima)
CREATE TABLE sii_documentos (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
tipo ENUM('33','34','39','41','52','61','56','46') NOT NULL, -- etc.
folio INT NOT NULL,
rut_emisor VARCHAR(12) NOT NULL,
rut_receptor VARCHAR(12) NOT NULL,
fecha DATE NOT NULL,
monto_total INT NOT NULL,
xml MEDIUMTEXT NULL,
estado_sii VARCHAR(50) NULL,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
UNIQUE KEY uq_doc (tipo, folio, rut_emisor)
);
-- Bitácora de integración
CREATE TABLE sii_logs (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
servicio VARCHAR(80) NOT NULL,
metodo VARCHAR(80) NULL,
request MEDIUMTEXT NULL,
response MEDIUMTEXT NULL,
http_status INT NULL,
created_at DATETIME NOT NULL
);
Utilitarios PHP (certificados y helpers)
<?php
// Cargar credenciales desde variables de entorno
$CERT_PFX = getenv('SII_CERT_PFX_PATH'); // /secure/certificado.p12
$CERT_PFX_PASS = getenv('SII_CERT_PFX_PASS'); // contraseña .p12
$CERT_KEY_PEM = getenv('SII_CERT_KEY_PEM'); // /secure/cert.key (PEM)
$CERT_CRT_PEM = getenv('SII_CERT_CRT_PEM'); // /secure/cert.crt (PEM)
// Si sólo tienes .p12, exporta a PEM una vez (con openssl) y referencia esas rutas.
// openssl pkcs12 -in certificado.p12 -out cert_full.pem -nodes
// openssl pkey -in cert_full.pem -out cert.key
// openssl crl2pkcs7 -nocrl -certfile cert_full.pem | openssl pkcs7 -print_certs -out cert.crt
function rut_sin_puntos($rut){ return preg_replace('/[^0-9kK]/','',$rut); }
function dv($rut){ // cálculo Módulo 11
$s=1; for($m=0;$rut;$rut=floor($rut/10)) $s=($s+$rut%10*(9-$m++%6))%11;
return $s?$s-1:'K';
}
?>
Autenticación SOAP para DTE (semilla → token)
Flujo: getSeed → firmar XML de semilla (XMLDSIG) → getToken → usar TOKEN
en servicios. La semilla expira en ~2 minutos, por lo que se debe firmar y canjear inmediatamente.
1) Obtener semilla
<?php
$wsdlSeed = 'https://palena.sii.cl/DTEWS/CrSeed.jws?WSDL';
$client = new SoapClient($wsdlSeed, ['trace' => 1, 'exceptions' => true]);
$resp = $client->getSeed();
$xml = new SimpleXMLElement($resp->getSeedReturn);
$semilla = (string)$xml->SEMILLA;
?>
2) Firmar semilla (XMLDSIG)
<?php
use RobRichards\XMLSecLibs\XMLSecurityDSig;
use RobRichards\XMLSecLibs\XMLSecurityKey;
$doc = new DOMDocument('1.0','UTF-8');
$doc->loadXML('<getToken><Semilla>'.htmlspecialchars($semilla).'</Semilla></getToken>');
$dsig = new XMLSecurityDSig();
$dsig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
$dsig->addReference($doc->documentElement, XMLSecurityDSig::SHA1, ['http://www.w3.org/2000/09/xmldsig#enveloped-signature']); // RSA-SHA1 histórico
$key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, ['type'=>'private']);
$key->loadKey($CERT_KEY_PEM, true);
$dsig->sign($key);
$dsig->add509Cert(file_get_contents($CERT_CRT_PEM));
$dsig->appendSignature($doc->documentElement);
$xmlFirmado = $doc->saveXML();
?>
3) Obtener token
<?php
$wsdlTok = 'https://palena.sii.cl/DTEWS/GetTokenFromSeed.jws?WSDL';
$clientTok = new SoapClient($wsdlTok, ['trace' => 1, 'exceptions' => true]);
$respTok = $clientTok->getToken(['pszXml' => $xmlFirmado]);
$xmlTok = new SimpleXMLElement($respTok->getTokenReturn);
$token = (string)$xmlTok->TOKEN;
// Persistir token en DB (scope = 'DTE')
?>
Envío de DTE (Upload)
El envío se realiza vía HTTP POST multipart a /cgi_dte/UPL/DTEUpload
, con el TOKEN
en la cookie y campos de formulario: rutSender
, dvSender
, rutCompany
, dvCompany
, más el archivo XML firmado.
<?php
$host = 'https://palena.sii.cl'; // o maullin según ambiente
$curl = curl_init($host.'/cgi_dte/UPL/DTEUpload');
$fields = [
'rutSender' => '66666666',
'dvSender' => '6',
'rutCompany' => '77777777',
'dvCompany' => '7',
'archivo' => new CURLFile('/path/EnvioDTE.xml','application/xml','EnvioDTE.xml'),
];
curl_setopt_array($curl, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $fields,
CURLOPT_HTTPHEADER => ['Cookie: TOKEN='.$token],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
]);
$resp = curl_exec($curl);
$http = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
// Guardar respuesta y track-id en sii_envios
?>
Consultas SOAP para DTE
Consulta Estado de Envío (QueryEstUp
)
Servicio SOAP para consultar el estado de un archivo subido (por TrackId).
<?php
$wsdl = 'https://maullin.sii.cl/DTEWS/QueryEstUp.jws?WSDL';
$cli = new SoapClient($wsdl, ['trace'=>1,'exceptions'=>true]);
$params = [
'RutCompania' => '77777777',
'DvCompania' => '7',
'TrackId' => $trackId,
'Token' => $token,
];
$resp = $cli->getEstUp($params);
echo $resp->getEstUpReturn;
?>
Consulta Estado de DTE (QueryEstDte
)
Servicio SOAP para consultar un DTE específico (emisor/tipo/folio/fecha/monto).
<?php
$wsdl = 'https://maullin.sii.cl/DTEWS/QueryEstDte.jws?WSDL';
$cli = new SoapClient($wsdl, ['trace'=>1,'exceptions'=>true]);
$params = [
'RutConsultante' => '66666666',
'DvConsultante' => '6',
'RutCompania' => '77777777',
'DvCompania' => '7',
'RutReceptor' => '55555555',
'DvReceptor' => '5',
'TipoDte' => '33',
'FolioDte' => '12345',
'FechaEmisionDte' => '2025-08-10',
'MontoDte' => '10620',
'Token' => $token,
];
$resp = $cli->getEstDte($params);
echo $resp->getEstDteReturn;
?>
Boleta Electrónica — API REST (Swagger)
Características clave:
- Servicios REST dedicados para autenticación, envío, estado de envío y consulta de boletas.
- Requiere TLS 1.2+ en certificación y producción.
- Máx. 500 boletas por envío; diagnóstico por servicio REST; track-id de 15 dígitos.
- La documentación oficial (OpenAPI/Swagger) está en el portal de la API del SII.
Flujo típico (resumen)
- Autenticación Boleta: solicitar semilla (REST), firmarla (XMLDSIG) y canjear por token específico de Boleta (distinto al token SOAP de facturas).
- Enviar boletas: POST de lote (hasta 500) con encabezado de autorización (token Boleta).
- Consultar estado de envío: REST por track-id (15 dígitos).
- Consultar boleta: endpoint de estado/validación por RUT–DV–Tipo–Folio (ver Swagger).
Ejemplo base con cURL en PHP (esqueleto)
<?php
$base = 'https://www4c.sii.cl/bolcoreinternetui/api'; // Ver rutas exactas en Swagger
// 1) Semilla (REST) - ejemplo genérico (ajusta ruta y cuerpo según Swagger)
$ch = curl_init($base.'/boleta.electronica.semilla'); // placeholder: verifica nombre real en Swagger
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 60]);
$resp = curl_exec($ch); curl_close($ch);
$semilla = json_decode($resp, true)['semilla'] ?? null;
// 2) Firmar semilla (igual que en SOAP, XMLDSIG) y canjear token (REST)
$xmlFirmado = firmar_semilla_xml($semilla, $CERT_KEY_PEM, $CERT_CRT_PEM); // reusa helper del módulo SOAP
$ch = curl_init($base.'/boleta.electronica.token'); // placeholder: verifica ruta exacta
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/xml'],
CURLOPT_POSTFIELDS => $xmlFirmado,
CURLOPT_RETURNTRANSFER => true
]);
$resp = curl_exec($ch); curl_close($ch);
$tokenBoleta = json_decode($resp, true)['token'] ?? null;
// 3) Envío de boletas (hasta 500)
$ch = curl_init($base.'/boleta.electronica.envio'); // placeholder: verifica ruta exacta
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer '.$tokenBoleta, 'Content-Type: application/xml'],
CURLOPT_POSTFIELDS => file_get_contents('/path/EnvioBoleta.xml'),
CURLOPT_RETURNTRANSFER => true
]);
$resp = curl_exec($ch); curl_close($ch);
$trackId = json_decode($resp, true)['trackid'] ?? null;
// 4) Consultar estado de envío y/o boleta
?>
El portal Swagger muestra las rutas y modelos exactos de cada llamada (autenticación, envío, consulta). Úsalo como fuente de verdad para nombres de endpoints y campos.
Registro de Aceptación/Reclamo (ACD/ERM/RCD/RFP/RFT)
WebService para que receptor/emisor/tenedor vigente registren o consulten eventos del DTE. WSDL de certificación/producción y métodos disponibles: ingresarAceptacionReclamoDoc
, listarEventosHistDoc
, consultarDocDteCedible
, consultarFechaRecepcionSii
. Regla clave: ventana de 8 días desde la recepción del DTE en SII.
<?php
$wsdl = 'https://ws1.sii.cl/WSREGISTRORECLAMODTE/registroreclamodteservice?wsdl'; // prod
$cli = new SoapClient($wsdl, ['trace'=>1,'exceptions'=>true]);
$params = [
'rutEmisor' => '77777777',
'dvEmisor' => '7',
'tipoDoc' => 33, // 33=Factura, 34=Exenta, 43=Liquidación Factura
'folio' => 12345,
'accionDoc' => 'ACD' // ACD/ERM/RCD/RFP/RFT
];
$resp = $cli->ingresarAceptacionReclamoDoc($params);
// Evaluar códigos de respuesta (1 OK; etc.)
?>
Paso a paso de implementación (checklist)
Preparar certificados
- Exportar
.p12
a.key
(privada) y.crt
(cadena) en PEM; proteger rutas y permisos.
Configurar entorno
- Variables de entorno para rutas y contraseñas; dominios de ambiente (
palena
/maullin
/ws1/ws2
/www4c
). - Verificar TLS 1.2+ en clientes HTTP (boleta REST).
Autenticación DTE
- Llamar
getSeed
(SOAP), firmar y obtenerTOKEN
conGetTokenFromSeed
. Usar la semilla de inmediato (expira ~2 min).
Upload DTE & consultas
- POST multipart a
/cgi_dte/UPL/DTEUpload
con cookieTOKEN
. Guardar track-id. - Consultar estado de envío (
QueryEstUp
) y estado de DTE (QueryEstDte
).
Boleta REST
- Autenticación específica vía REST (semilla → token), envío por lotes (≤500), consulta de envío/boleta.
- Usar el portal Swagger como referencia de rutas y modelos.
Aceptación/Reclamo
- WS de Registro: aplicar acciones ACD/ERM/RCD/RFP/RFT cumpliendo ventana de 8 días; exponer consulta de eventos.
Buenas prácticas y operación
- Cachea tokens por ámbito (DTE vs Boleta). Maneja expiración/renovación automática al detectar fallo por expiración.
- Backoff en consultas de estado: no “martillar” servicios; registra reintentos con jitter.
- Validaciones locales (schema XML) antes de enviar.
- Auditoría: guarda request/response (enmascara datos sensibles) y correlaciona por track-id.
- Monitoreo: métricas de tasa de aceptación, latencia, errores por servicio.
- Seguridad: clave privada fuera del árbol web; least privilege en DB; rotate de certificados.
Solución de problemas comunes
Síntoma | Causa probable | Acción |
---|---|---|
“Semilla inválida / expirada” | Demora entre getSeed y getToken | Obtén nueva semilla y firma de inmediato. |
Upload responde error de cookie | Falta Cookie: TOKEN=... | Incluye cookie; verifica vigencia del token. |
Boleta: handshake TLS fallido | Cliente usa TLS < 1.2 | Habilita TLS 1.2+ en cURL/OpenSSL. |
No puedo registrar “ERM” tras reclamo | Reglas de negocio del WS de Registro | Revisa combinaciones válidas/errores y ventana de 8 días. |
Anexos (esenciales)
- Instructivo técnico de Boleta Electrónica (TLS 1.2+, REST, 500 por envío, track-id 15 dígitos, URL Swagger).
- Autenticación automática SOAP (CrSeed/GetTokenFromSeed; semilla ≈ 2 min).
- Consulta Estado de DTE (QueryEstDte).
- Consulta Estado de Envío (QueryEstUp).
- Ejemplo oficial de upload automático (DTEUpload, cookie TOKEN, campos).
- WS Registro de Aceptación/Reclamo (acciones y reglas).
Notas importantes
- Las rutas exactas de la API REST de Boleta y los cuerpos de cada operación se consultan en el portal Swagger del SII (si cambian, allí se refleja).
- Esta guía no reemplaza los formatos XML oficiales de DTE/EnvioDTE/RVD ni las resoluciones del SII; úsala como complemento implementativo.