curl --request POST \
--url https://api.tupana.ai/v2/documents/batch/ \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"documents": [
{
"dte_type": {
"code": "33"
},
"date_issued": "2024-01-15",
"document_issuer": {
"rut": "12345678-9",
"business_name": "Mi Empresa SpA"
},
"document_receiver": {
"rut": "98765432-1",
"business_name": "Cliente Importante Ltda"
},
"details": [
{
"item_name": "Servicio de Consultoría",
"quantity": 1,
"unit_price": 100000
}
]
}
]
}
'import requests
url = "https://api.tupana.ai/v2/documents/batch/"
payload = { "documents": [
{
"dte_type": { "code": "33" },
"date_issued": "2024-01-15",
"document_issuer": {
"rut": "12345678-9",
"business_name": "Mi Empresa SpA"
},
"document_receiver": {
"rut": "98765432-1",
"business_name": "Cliente Importante Ltda"
},
"details": [
{
"item_name": "Servicio de Consultoría",
"quantity": 1,
"unit_price": 100000
}
]
}
] }
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
documents: [
{
dte_type: {code: '33'},
date_issued: '2024-01-15',
document_issuer: {rut: '12345678-9', business_name: 'Mi Empresa SpA'},
document_receiver: {rut: '98765432-1', business_name: 'Cliente Importante Ltda'},
details: [{item_name: 'Servicio de Consultoría', quantity: 1, unit_price: 100000}]
}
]
})
};
fetch('https://api.tupana.ai/v2/documents/batch/', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.tupana.ai/v2/documents/batch/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'documents' => [
[
'dte_type' => [
'code' => '33'
],
'date_issued' => '2024-01-15',
'document_issuer' => [
'rut' => '12345678-9',
'business_name' => 'Mi Empresa SpA'
],
'document_receiver' => [
'rut' => '98765432-1',
'business_name' => 'Cliente Importante Ltda'
],
'details' => [
[
'item_name' => 'Servicio de Consultoría',
'quantity' => 1,
'unit_price' => 100000
]
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.tupana.ai/v2/documents/batch/"
payload := strings.NewReader("{\n \"documents\": [\n {\n \"dte_type\": {\n \"code\": \"33\"\n },\n \"date_issued\": \"2024-01-15\",\n \"document_issuer\": {\n \"rut\": \"12345678-9\",\n \"business_name\": \"Mi Empresa SpA\"\n },\n \"document_receiver\": {\n \"rut\": \"98765432-1\",\n \"business_name\": \"Cliente Importante Ltda\"\n },\n \"details\": [\n {\n \"item_name\": \"Servicio de Consultoría\",\n \"quantity\": 1,\n \"unit_price\": 100000\n }\n ]\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.tupana.ai/v2/documents/batch/")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"documents\": [\n {\n \"dte_type\": {\n \"code\": \"33\"\n },\n \"date_issued\": \"2024-01-15\",\n \"document_issuer\": {\n \"rut\": \"12345678-9\",\n \"business_name\": \"Mi Empresa SpA\"\n },\n \"document_receiver\": {\n \"rut\": \"98765432-1\",\n \"business_name\": \"Cliente Importante Ltda\"\n },\n \"details\": [\n {\n \"item_name\": \"Servicio de Consultoría\",\n \"quantity\": 1,\n \"unit_price\": 100000\n }\n ]\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tupana.ai/v2/documents/batch/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"documents\": [\n {\n \"dte_type\": {\n \"code\": \"33\"\n },\n \"date_issued\": \"2024-01-15\",\n \"document_issuer\": {\n \"rut\": \"12345678-9\",\n \"business_name\": \"Mi Empresa SpA\"\n },\n \"document_receiver\": {\n \"rut\": \"98765432-1\",\n \"business_name\": \"Cliente Importante Ltda\"\n },\n \"details\": [\n {\n \"item_name\": \"Servicio de Consultoría\",\n \"quantity\": 1,\n \"unit_price\": 100000\n }\n ]\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"batch_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "processing",
"created_at": "2024-01-15T10:30:00Z",
"documents": [
{
"index": 0,
"status": "created",
"document": {
"id": "docu_9f2a7c1b8e4d0",
"folio": "1",
"date_issued": "2024-01-15",
"amount_with_iva": 119000,
"receiver_id": "ment_4829301923847",
"is_draft": false,
"can_be_issued": true,
"dte_type": {
"code": "33",
"description": "Factura Electrónica"
},
"sender": {
"id": "ment_4829301923847",
"name": "Mi Empresa SpA",
"tax_id": "12345678-9"
},
"receiver": {
"id": "ment_4829301923847",
"name": "Cliente Importante Ltda",
"tax_id": "98765432-1"
},
"items": [
{
"item_name": "Servicio de Consultoría",
"item_description": null,
"quantity": 1,
"unit_price": 100000,
"unit": "UN",
"item_code": null,
"item_type_code": null,
"discount_percent": null,
"other_tax": null
}
],
"document_total": {
"net_amount": 100000,
"iva_rate": 19,
"iva_amount": 19000,
"total_amount": 119000
},
"pdf_url": "https://s3.amazonaws.com/bucket/documento_12345.pdf?signature=...",
"pdf_download_url": "/api/master-entities/123/documents/12345/file/"
}
}
]
}{
"error": "Esta entidad no tiene credenciales SII válidas configuradas"
}{
"error": "VALIDATION_ERROR",
"message": "<string>"
}{
"error": "VALIDATION_ERROR",
"message": "<string>"
}Emisión masiva de documentos
Crea hasta 200 documentos en una sola llamada. La respuesta incluye información completa de cada documento creado, incluyendo PDF cuando está disponible. Los resultados también se enviarán por webhook si está configurado.
Permisos requeridos: La API Key debe tener el permiso document:create o permisos completos (*). Además, la entidad emisora debe tener credenciales SII válidas configuradas.
curl --request POST \
--url https://api.tupana.ai/v2/documents/batch/ \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"documents": [
{
"dte_type": {
"code": "33"
},
"date_issued": "2024-01-15",
"document_issuer": {
"rut": "12345678-9",
"business_name": "Mi Empresa SpA"
},
"document_receiver": {
"rut": "98765432-1",
"business_name": "Cliente Importante Ltda"
},
"details": [
{
"item_name": "Servicio de Consultoría",
"quantity": 1,
"unit_price": 100000
}
]
}
]
}
'import requests
url = "https://api.tupana.ai/v2/documents/batch/"
payload = { "documents": [
{
"dte_type": { "code": "33" },
"date_issued": "2024-01-15",
"document_issuer": {
"rut": "12345678-9",
"business_name": "Mi Empresa SpA"
},
"document_receiver": {
"rut": "98765432-1",
"business_name": "Cliente Importante Ltda"
},
"details": [
{
"item_name": "Servicio de Consultoría",
"quantity": 1,
"unit_price": 100000
}
]
}
] }
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
documents: [
{
dte_type: {code: '33'},
date_issued: '2024-01-15',
document_issuer: {rut: '12345678-9', business_name: 'Mi Empresa SpA'},
document_receiver: {rut: '98765432-1', business_name: 'Cliente Importante Ltda'},
details: [{item_name: 'Servicio de Consultoría', quantity: 1, unit_price: 100000}]
}
]
})
};
fetch('https://api.tupana.ai/v2/documents/batch/', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.tupana.ai/v2/documents/batch/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'documents' => [
[
'dte_type' => [
'code' => '33'
],
'date_issued' => '2024-01-15',
'document_issuer' => [
'rut' => '12345678-9',
'business_name' => 'Mi Empresa SpA'
],
'document_receiver' => [
'rut' => '98765432-1',
'business_name' => 'Cliente Importante Ltda'
],
'details' => [
[
'item_name' => 'Servicio de Consultoría',
'quantity' => 1,
'unit_price' => 100000
]
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.tupana.ai/v2/documents/batch/"
payload := strings.NewReader("{\n \"documents\": [\n {\n \"dte_type\": {\n \"code\": \"33\"\n },\n \"date_issued\": \"2024-01-15\",\n \"document_issuer\": {\n \"rut\": \"12345678-9\",\n \"business_name\": \"Mi Empresa SpA\"\n },\n \"document_receiver\": {\n \"rut\": \"98765432-1\",\n \"business_name\": \"Cliente Importante Ltda\"\n },\n \"details\": [\n {\n \"item_name\": \"Servicio de Consultoría\",\n \"quantity\": 1,\n \"unit_price\": 100000\n }\n ]\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.tupana.ai/v2/documents/batch/")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"documents\": [\n {\n \"dte_type\": {\n \"code\": \"33\"\n },\n \"date_issued\": \"2024-01-15\",\n \"document_issuer\": {\n \"rut\": \"12345678-9\",\n \"business_name\": \"Mi Empresa SpA\"\n },\n \"document_receiver\": {\n \"rut\": \"98765432-1\",\n \"business_name\": \"Cliente Importante Ltda\"\n },\n \"details\": [\n {\n \"item_name\": \"Servicio de Consultoría\",\n \"quantity\": 1,\n \"unit_price\": 100000\n }\n ]\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tupana.ai/v2/documents/batch/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"documents\": [\n {\n \"dte_type\": {\n \"code\": \"33\"\n },\n \"date_issued\": \"2024-01-15\",\n \"document_issuer\": {\n \"rut\": \"12345678-9\",\n \"business_name\": \"Mi Empresa SpA\"\n },\n \"document_receiver\": {\n \"rut\": \"98765432-1\",\n \"business_name\": \"Cliente Importante Ltda\"\n },\n \"details\": [\n {\n \"item_name\": \"Servicio de Consultoría\",\n \"quantity\": 1,\n \"unit_price\": 100000\n }\n ]\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"batch_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "processing",
"created_at": "2024-01-15T10:30:00Z",
"documents": [
{
"index": 0,
"status": "created",
"document": {
"id": "docu_9f2a7c1b8e4d0",
"folio": "1",
"date_issued": "2024-01-15",
"amount_with_iva": 119000,
"receiver_id": "ment_4829301923847",
"is_draft": false,
"can_be_issued": true,
"dte_type": {
"code": "33",
"description": "Factura Electrónica"
},
"sender": {
"id": "ment_4829301923847",
"name": "Mi Empresa SpA",
"tax_id": "12345678-9"
},
"receiver": {
"id": "ment_4829301923847",
"name": "Cliente Importante Ltda",
"tax_id": "98765432-1"
},
"items": [
{
"item_name": "Servicio de Consultoría",
"item_description": null,
"quantity": 1,
"unit_price": 100000,
"unit": "UN",
"item_code": null,
"item_type_code": null,
"discount_percent": null,
"other_tax": null
}
],
"document_total": {
"net_amount": 100000,
"iva_rate": 19,
"iva_amount": 19000,
"total_amount": 119000
},
"pdf_url": "https://s3.amazonaws.com/bucket/documento_12345.pdf?signature=...",
"pdf_download_url": "/api/master-entities/123/documents/12345/file/"
}
}
]
}{
"error": "Esta entidad no tiene credenciales SII válidas configuradas"
}{
"error": "VALIDATION_ERROR",
"message": "<string>"
}{
"error": "VALIDATION_ERROR",
"message": "<string>"
}Headers
Idempotency-Key (Opcional)
- Tipo: String
- Descripción: Header opcional que previene la creación de lotes duplicados
- Restricciones: Máximo 256 caracteres, expira después de 24 horas
- Ejemplo:
"batch_2024_01_15_001"
X-Use-Defaults (Opcional)
⚠️ IMPORTANTE: Se recomienda encarecidamente usar el header X-Use-Defaults: true en todas tus solicitudes de emisión masiva de documentos. Este header simplifica significativamente la creación de documentos al hacer opcionales muchos campos y completar automáticamente los datos faltantes según tu configuración en Tupana.
- Tipo: String
- Valores permitidos:
"true","false" - Por defecto:
"false" - Descripción: Si se establece como
"true", el sistema usará valores por defecto para campos no proporcionados, reduciendo la complejidad y cantidad de datos que necesitas enviar
Campos que se vuelven opcionales o se completan automáticamente
A nivel del documento:date_issued: Si no se proporciona, se usa la fecha actual (en zona horaria de Chile)folio: Si no se proporciona, se genera automáticamente por el sistemadte_type.code: Si no se proporciona, se usa"33"(Factura Electrónica) por defectoheader.payment_method: Si no se proporciona, se establece como"2"(crédito)
document_issuer (solo con RUT):
Con X-Use-Defaults: true, solo necesitas proporcionar el rut del emisor. El sistema completa automáticamente todos los demás campos desde tu configuración:
business_name: Razón social del emisorbusiness_activity: Giro o actividad económicaaddress: Dirección del emisordistrict: Comunacity: Ciudademail: Email de contactophone_number: Teléfonoactivity_code: Código de actividad económica
document_receiver (solo con RUT):
Con X-Use-Defaults: true, solo necesitas proporcionar el rut del receptor. El sistema completa automáticamente todos los demás campos desde la configuración del cliente o datos disponibles:
business_name: Razón social del receptor ✅ Opcionalcontact: Contacto del receptor ✅ Opcionalbusiness_activity: Giro o actividad económica ✅ Opcional (no se valida si está vacío)address: Dirección del receptor ✅ Opcional (no se valida si está vacío)district: Comuna ✅ Opcional (no se valida si está vacío)city: Ciudad ✅ Opcional (no se valida si está vacío)
Request Body
documents (Obligatorio)
- Tipo: Array
- Descripción: Lista de documentos a crear en el lote
- Restricciones: Máximo 200 documentos por lote
Estructura de cada documento
Campos base (aplican a todos los tipos de documentos)
dte_type (Obligatorio)- Tipo: Object
- Campos:
code(String): Código del tipo de documento
- Tipo: String (formato YYYY-MM-DD)
- Descripción: Fecha de emisión del documento
- Obligatorio: Sí, excepto si se usa
X-Use-Defaults: true(usa fecha actual)
- Tipo: Integer
- Descripción: Número de folio del documento
- Comportamiento: Si no se proporciona, se genera automáticamente
Tipos de Documentos Soportados
Validación de campos desconocidos
La API compara cada documento con los campos que acepta. Un campo que no existe (por ejemplo, un nombre mal escrito o de una versión antigua de la documentación) no se usa al emitir: antes se descartaba sin aviso; ahora se informa.Modo aviso: warnings
La respuesta del batch (v1 y v2) puede incluir un arreglo warnings en el primer nivel, con un elemento por campo desconocido. El documento se crea igual, sin ese campo.
{
"batch_id": "doba_4829301923847561203",
"status": "processing",
"warnings": [
{
"document_index": 0,
"field": "header.transfer_indicator",
"code": "unknown_field",
"message": "Campo desconocido: se ignoró.",
"suggestion": "transport_data.transport_type"
}
]
}
| Campo | Tipo | Descripción |
|---|---|---|
document_index | Integer | Posición del documento en el arreglo documents (desde 0) |
field | String | Ruta del campo dentro del documento |
code | String | Tipo de aviso. Hoy siempre "unknown_field" |
message | String | Texto para personas; puede cambiar, no lo parsees |
suggestion | String o null | Campo correcto, si se reconoce el error; null si no hay sugerencia |
| Campo enviado | Campo correcto |
|---|---|
header.transfer_indicator | transport_data.transport_type |
export_data.export_clause | export_data.sale_clause_code |
export_data.destination_country | export_data.destination_country_code |
header.transfer_indicator la guía se emite con el tipo de traslado por defecto ("1", venta), y con export_data.export_clause la factura de exportación sale sin cláusula de venta. Revisa los warnings en cada respuesta y corrige tu integración.Modo estricto: 422
Las API keys con validación estricta reciben 422 en vez del aviso, y no se crea ningún documento del batch. El error va bajo la posición del documento (como string, desde "0") y la ruta del campo; en las listas (details, references, payments) la posición de la línea también es una llave:
{
"documents": {
"0": {
"header": {
"transfer_indicator": ["Campo desconocido. ¿Quisiste decir transport_data.transport_type?"]
},
"details": {
"1": {"exento": ["Campo desconocido."]}
}
}
}
}
- Las API keys nuevas tienen la validación estricta activada.
- Las integraciones existentes reciben primero los
warnings, para que puedan corregir sus campos sin que se rompa la emisión. El paso a modo estricto de una API key existente se coordina con Tupana. - El texto del mensaje puede cambiar: usa la ruta del campo para identificar el error.
- API keys del flujo diferido (prefijo
gw_): el aviso llega en el202junto abatch_id, y con validación estricta el422trae el mismo objeto dentro deerrors({"errors": {"documents": {...}}, "request": {...}}).
Respuesta
Respuesta Inmediata de la API
201 - Documentos creados exitosamente
- Tipo: Object
- Campos:
batch_id(String): Identificador único del lotestatus(String): Estado del procesamiento ("processing")total_documents(Integer): Número total de documentos en el lotemessage(String): Mensaje descriptivo del estadowarnings(Array, opcional): Avisos sobre campos desconocidos que se ignoraron. Ver Validación de campos desconocidos
413 - Límite excedido
- Descripción: Más de 200 documentos en el array
- Campos:
error(String): Descripción del errorcode(String): Código de error
400 - Credenciales no activas
- Descripción: La empresa emisora no tiene credenciales SII activas configuradas
- Campos:
error(String): Mensaje descriptivo indicando que no hay credenciales activas para el RUT especificado
422 - Error de validación
- Descripción: Cuerpo malformado o fallo de validación
- Cuerpo malformado (por ejemplo
documentsno es una lista):{"error": "..."}. - Validación de documentos: los errores van bajo
documents, con la posición del documento como llave y la ruta del campo adentro. Ejemplo con una guía de traslado de exportación sin datos de Aduana:
{
"documents": {
"0": {
"transport_data": {
"gross_weight": ["Requerido en guías de traslado de exportación (transport_type 8 o 9): el SII lo exige en Transporte/Aduana."]
}
}
}
}
Respuesta del Webhook
Cuando un documento se emite exitosamente, Tupana envía un webhook con la siguiente estructura: event (Obligatorio)- Tipo: String
- Valor:
"document.issued" - Descripción: Tipo de evento del webhook
- Tipo: String (ISO 8601)
- Descripción: Timestamp de cuando se generó el webhook
- Tipo: Object
- Descripción: Datos completos del documento emitido
Campos del objeto data
Información básica del documento:id(Integer): ID único del documento en Tupanafolio(String): Folio asignado por el SIIdate_issued(String): Fecha de emisión (formato YYYY-MM-DD)amount_with_iva(Number): Monto total con IVA incluidois_sandbox(Boolean): Indica si es un documento de prueba
code(String): Código del tipo de documentodescription(String): Descripción del tipo de documento
id(Integer): ID del emisor en Tupananame(String): Nombre/razón social del emisortax_id(String): RUT del emisor (formato con puntos y guión)email(String): Email del emisor
id(Integer): ID del receptor en Tupananame(String): Nombre/razón social del receptortax_id(String): RUT del receptor (formato con puntos y guión)email(String): Email del receptor
purchase_transaction_type(Integer): Tipo de transacción de comprasale_transaction_type(Integer): Tipo de transacción de ventapayment_method(String): Método de pagodue_date(String): Fecha de vencimiento (formato YYYY-MM-DD)retention_type(String): Tipo de retención (solo para boletas de honorarios)
rut(String): RUT del emisorbusiness_name(String): Razón socialbusiness_activity(String): Giro o actividad económicaphone_number(String): Teléfonoemail(String): Emailactivity_code(Integer): Código de actividad económicasii_branch_code(String): Código de sucursal SIIaddress(String): Direccióndistrict(String): Comunacity(String): Ciudad
rut(String): RUT del receptorbusiness_name(String): Razón socialbusiness_activity(String): Giro o actividad económicacontact(String): Contactoaddress(String): Direccióndistrict(String): Comunacity(String): Ciudad
net_amount(Number): Monto neto (sin IVA)iva_rate(Number): Tasa de IVA aplicadaiva_amount(Number): Monto del IVAtotal_amount(Number): Monto total
item_name(String): Nombre del producto/servicioitem_description(String): Descripción del producto/servicioquantity(Number): Cantidadunit_price(Number): Precio unitario neto, sin IVA. Si el documento se emitió en bruto (boletas 39/41 congross_unit_price), este campo refleja el monto bruto de la línea —gross_unit_pricees solo de entrada y no se retorna en la respuesta.item_code(String): Código del producto/servicioitem_type_code(String): Código del tipo de ítemunit(String): Unidad de medidadiscount_percent(Number): Porcentaje de descuentoother_tax(Number): Otros impuestos
dte_type_code(String): Código del tipo de DTE de referenciareference_folio(String): Folio del documento referenciadoreference_date(String): Fecha del documento referenciadoreference_reason(String): Razón de la referencia
pdf_file(String): URL temporal para descargar el PDF del documentoxml_file(String): URL temporal para descargar el XML del documento
- Descripción: Campos propios del cliente que se guardan tal cual junto con el documento. Se envía dentro de cada elemento de
documents(mismo nivel queheader,details, etc.). - Estructura: Objeto JSON libre, ej.
{"external_order_id": "PED-123", "idempotency_key": "..."}. No se valida ni se transforma. - Lectura: vuelve en el detalle (
GET /documents/{document_id}/) y en el listado. - Búsqueda: el listado permite
json_param__<key>=<valor>(ver Filtrar por json_param). Guarda ahí tu propio identificador (por ejemplo elIdempotency-Keycon que creaste el batch) para reencontrar el documento aunque pierdas la respuesta de creación.
{
"documents": [
{
"dte_type": { "code": "33" },
"document_issuer": { "...": "..." },
"document_receiver": { "...": "..." },
"details": [ { "...": "..." } ],
"json_param": { "external_order_id": "PED-123" }
}
]
}
- Descripción: Texto libre que se imprime en un recuadro “Información adicional” al final del PDF, justo antes del timbre. Se envía dentro de cada elemento de
documents(mismo nivel queheader,details, etc.). - Largo máximo: 1000 caracteres. Los saltos de línea (
\n) separan líneas dentro del recuadro. - No se envía al SII: no forma parte del XML del documento, solo del PDF.
- Dónde aparece: solo en el PDF propio de Tu Pana o del facturador de mercado (ver aviso arriba).
- Edición: se puede cambiar mientras el documento es borrador; una vez emitido no se puede modificar.
- Lectura: vuelve en la respuesta del batch, en el detalle (
GET /documents/{document_id}/), en el listado y en los webhooks (nullsi no se envió).
{
"documents": [
{
"dte_type": { "code": "33" },
"document_issuer": { "...": "..." },
"document_receiver": { "...": "..." },
"details": [ { "...": "..." } ],
"additional_info": "Orden de compra N° 4500123\nPago por transferencia a la cuenta corriente 00-123-45678-09"
}
]
}
Consideraciones Especiales por Tipo de Documento
Ejemplos de Uso por Tipo de Documento
Factura Electrónica (DTE 33)
{
"documents": [
{
"dte_type": {
"code": "33"
},
"date_issued": "2024-01-15",
"document_issuer": {
"rut": "12345678-9",
"business_name": "Mi Empresa SpA"
},
"document_receiver": {
"rut": "98765432-1",
"business_name": "Cliente Importante Ltda"
},
"details": [
{
"item_name": "Servicio de Consultoría",
"quantity": 1,
"unit_price": 100000
}
]
}
]
}
Factura de Compra (DTE 46)
{
"documents": [
{
"dte_type": {
"code": "46"
},
"date_issued": "2024-01-15",
"document_issuer": {
"rut": "98765432-1",
"business_name": "Proveedor SpA"
},
"document_receiver": {
"rut": "12345678-9",
"business_name": "Mi Empresa SpA"
},
"header": {
"purchase_transaction_type": 1,
"payment_method": "2"
},
"details": [
{
"item_name": "Equipo de Oficina",
"quantity": 2,
"unit_price": 50000
}
]
}
]
}
Guía de Despacho de venta (DTE 52)
Guía que acompaña una venta, despachada por el emisor a una bodega del cliente distinta de su dirección. Las líneas son afectas: la guía lleva IVA.{
"documents": [
{
"dte_type": {
"code": "52"
},
"date_issued": "2026-09-15",
"document_issuer": {
"rut": "12345678-9"
},
"document_receiver": {
"rut": "98765432-1",
"business_name": "Cliente Importante Ltda"
},
"transport_data": {
"transport_type": "1",
"dispatch_type": "2",
"transport_rut": "76234567-6",
"transport_plate": "ABCD12",
"trailer_plate": "JK1234",
"driver_rut": "12345678-5",
"driver_name": "Juan Pérez",
"departure_date": "2026-11-02",
"departure_time": "08:30",
"arrival_date": "2026-11-02",
"destination_address": "Camino Lo Boza 120, Bodega 4",
"destination_district": "Pudahuel",
"destination_city": "Santiago"
},
"details": [
{
"item_name": "Pastillas de freno",
"quantity": 40,
"unit": "UN",
"unit_price": 12500
},
{
"item_name": "Discos de freno",
"quantity": 10,
"unit": "UN",
"unit_price": 38000
}
]
}
]
}
Guía de Despacho de traslado para exportación (DTE 52)
Traslado de mercadería de exportación desde la fábrica al aeropuerto. La venta va en la factura de exportación; la guía declara el tipo de traslado"8", los datos de Aduana, el valor de la carga como línea exenta y el DUS como referencia.
{
"documents": [
{
"dte_type": {
"code": "52"
},
"date_issued": "2026-09-15",
"document_issuer": {
"rut": "12345678-9"
},
"document_receiver": {
"rut": "76123456-0",
"business_name": "Agencia de Aduanas Ejemplo Ltda"
},
"transport_data": {
"transport_type": "8",
"dispatch_type": "3",
"transfer_issuer_code": "1",
"transport_rut": "76234567-6",
"transport_plate": "PJRL69",
"driver_rut": "12345678-5",
"driver_name": "Juan Pérez",
"destination_address": "Aeropuerto Arturo Merino Benitez",
"destination_district": "Pudahuel",
"destination_city": "Santiago",
"departure_port_code": "992",
"arrival_port_code": "134",
"gross_weight": "1414.00",
"gross_weight_unit_code": "6",
"total_packages": 3,
"package_type_code": "22"
},
"details": [
{
"item_name": "Balatas de freno",
"item_description": "Partida arancelaria 6813.81.00",
"quantity": 3,
"unit_price": 1350000,
"is_exempt": true
}
],
"references": [
{
"dte_type_code": "807",
"reference_folio": "13717477-4",
"reference_date": "2026-09-15",
"reference_reason": "DUS 13717477-4"
}
]
}
]
}
exempt_amount 4.050.000, IVA 0 y total 4.050.000.
Factura de Exportación (DTE 110)
{
"documents": [
{
"dte_type": {
"code": "110"
},
"date_issued": "2024-01-15",
"document_issuer": {
"rut": "12345678-9",
"business_name": "Exportadora SpA"
},
"document_receiver": {
"rut": "99999999-9",
"business_name": "Importador Internacional Inc",
"address": "123 Main Street",
"city": "New York"
},
"header": {
"sale_transaction_type": 1,
"currency": "USD"
},
"export_data": {
"destination_country_code": "225",
"currency_code": "13",
"sale_mode_code": "1",
"sale_clause_code": "5",
"export_payment_method_code": "11",
"exchange_rate": "965.40"
},
"details": [
{
"item_name": "Producto Exportado",
"quantity": 100,
"unit_price": 50
}
]
}
]
}
Nota de Crédito (DTE 61)
{
"documents": [
{
"dte_type": {
"code": "61"
},
"date_issued": "2024-01-16",
"document_issuer": {
"rut": "12345678-9",
"business_name": "Mi Empresa SpA"
},
"document_receiver": {
"rut": "98765432-1",
"business_name": "Cliente Importante Ltda"
},
"references": [
{
"dte_type_code": "33",
"reference_folio": 12345,
"reference_date": "2024-01-15",
"reference_reason": "Corrección de precio"
}
],
"details": [
{
"item_name": "Ajuste por Corrección",
"quantity": -1,
"unit_price": 5000
}
]
}
]
}
Boleta de Honorarios por usuario autorizado (DTE 80)
El emisor de la boleta esdocument_issuer.rut, pero la emite un usuario autorizado por el SII (dueño de una credencial sii_company). header.authorized_user_rut indica cuál credencial usar cuando hay varias accesibles.
{
"documents": [
{
"dte_type": {
"code": "80"
},
"document_issuer": {
"rut": "76543210-3"
},
"document_receiver": {
"rut": "12345678-9"
},
"header": {
"retention_type": "RETRECEPTOR",
"authorized_user_rut": "19615893-6"
},
"details": [
{
"item_name": "Asesoría profesional",
"quantity": 1,
"unit_price": 50000
}
]
}
]
}
Boleta de Honorarios de Terceros (DTE 90)
Ejemplo mínimo con headerX-Use-Defaults: true: con solo RUT en emisor y receptor el backend completa business_name y el resto si existen en Tupana; usa fecha actual si se omite date_issued.
{
"documents": [
{
"dte_type": {
"code": "90"
},
"document_issuer": {
"rut": "76543210-3"
},
"document_receiver": {
"rut": "12345678-9"
},
"header": {
"retention_type": "RETRECEPTOR"
},
"details": [
{
"item_name": "Servicio de reparto de pedidos",
"quantity": 1,
"unit_price": 15000
}
]
}
]
}
🧾 Factura de Compra (DTE 46)
Campos específicos del header:
-
purchase_transaction_type(Integer, Obligatorio):1: Compras del giro - Productos/servicios relacionados con tu actividad principal2: Compras fuera del giro - Productos/servicios no relacionados con tu actividad principal3: Activo fijo - Bienes que se incorporan al patrimonio de la empresa (maquinaria, muebles, etc.)
-
payment_method(String, Opcional):"1": Contado - Pago inmediato"2": Crédito - Pago diferido"3": Sin costo - Producto/servicio recibido gratuitamente
Validaciones importantes:
- Registro contable: Este documento genera asiento automático en tu contabilidad
- IVA recuperable: El IVA pagado puede ser recuperado según el tipo de compra
- Proveedor extranjero: Si el proveedor es extranjero, usar RUT genérico
55555555-5 - Fecha límite: Las compras deben registrarse dentro del mes siguiente a la recepción
Casos de uso comunes:
- Registro de compras a proveedores locales
- Incorporación de activos fijos
- Servicios profesionales recibidos
- Compras de materias primas o insumos
🚚 Guía de Despacho (DTE 52)
Campos de transport_data
Todos los campos son opcionales salvo lo que se indica. Los mismos campos se aceptan enPOST /v1/documents/batch/ y en POST /v2/documents/batch/. La columna Res. 154 marca lo que pasa a ser obligatorio en la guía el 1 de noviembre de 2026 (ver Resolución 154).
| Campo | Tipo | Obligatorio | Res. 154 | Validación | Campo del DTE |
|---|---|---|---|---|---|
transport_type | String "1"–"9" | No (por defecto "1") | Obligatorio | Tabla de tipos de traslado | IdDoc/IndTraslado |
dispatch_type | String "1"–"3" | No (si no se envía, se emite 3) | — | No se permite con transport_type "5" | IdDoc/TipoDespacho |
transport_rut | String | No | Obligatorio (o transport_unknown_reason) | Si el dígito verificador es inválido se emite igual y la respuesta trae un aviso invalid_rut | Transporte/RUTTrans |
transport_plate | String | No | Obligatorio (o transport_unknown_reason) | Se normaliza a mayúsculas sin guion ni espacios; máximo 8 caracteres | Transporte/Patente |
driver_rut | String | Con driver_name | Obligatorio (o transport_unknown_reason) | Si el dígito verificador es inválido se emite igual y la respuesta trae un aviso invalid_rut | Transporte/Chofer/RUTChofer |
driver_name | String | Con driver_rut | Obligatorio (o transport_unknown_reason) | Se trunca a 30 caracteres en el DTE | Transporte/Chofer/NombreChofer |
destination_address | String | No | Obligatoria (vale la dirección del receptor) | Máximo 70 caracteres | Transporte/DirDest |
destination_district | String | No | Obligatoria (vale la comuna del receptor) | Máximo 20 caracteres | Transporte/CmnaDest |
destination_city | String | No | — | Máximo 20 caracteres | Transporte/CiudadDest |
transfer_issuer_code | String "1"–"4" | Con traslado "8"/"9" (facturador de mercado) | — | Ver Emisor del traslado. Sólo con transport_type "8" o "9" | Emisor/GuiaExport/CdgTraslado |
authorization_resolution_number | Integer | Con transfer_issuer_code "4" | — | Mayor a 0; no se permite con otro código | Emisor/GuiaExport/FolioAut |
authorization_resolution_date | String YYYY-MM-DD | Con transfer_issuer_code "4" | — | No se permite con otro código | Emisor/GuiaExport/FchAut |
departure_port_code | String | Con traslado "8"/"9" (facturador de mercado) | — | Código o nombre exacto de la tabla de puertos de Aduana | Aduana/CodPtoEmbarque |
arrival_port_code | String | Con traslado "8"/"9" (facturador de mercado) | — | Código o nombre exacto de la tabla de puertos de Aduana | Aduana/CodPtoDesemb |
gross_weight | String decimal | Con traslado "8"/"9" (facturador de mercado) | — | Mayor a 0, hasta 2 decimales | Aduana/PesoBruto |
gross_weight_unit_code | String | Con traslado "8"/"9" (facturador de mercado) | — | Tabla de unidades de medida de Aduana | Aduana/CodUnidPesoBruto |
total_packages | Integer | No | — | Mayor a 0 | Aduana/TotBultos |
package_type_code | String | Si se envía total_packages | — | Tabla de tipos de bulto de Aduana | Aduana/TipoBultos/CodTpoBultos |
trailer_plate | String | No | Aviso si hay patente y no viene carro (res154_trailer_plate, nunca 422) | Igual que transport_plate: mayúsculas, sin guion ni espacios, máximo 8 | Transporte/PatenteCarro |
departure_date | String YYYY-MM-DD | No | Obligatoria | Fecha válida | Transporte/FchSalida |
departure_time | String HH:MM | No | Obligatoria | También se acepta HH:MM:SS | Transporte/HraSalida |
arrival_date | String YYYY-MM-DD | No | — | No puede ser anterior a departure_date | Transporte/FchLlegada |
transfer_reason | String | No | Obligatorio si un traslado que no es venta omite unit_price | Máximo 200 caracteres | Texto en el detalle |
transport_unknown_reason | String | No | Reemplaza patente, transportista y chofer cuando no se conocen | Máximo 100 caracteres | Texto en el detalle |
timber_enabled, comuna_rol, manzana_rol, predio_rol, geo_ref_system, latitude, longitude, conaf_plan_code | — | No | — | Sin cambios | ManejoMadera (CONAF) |
destination_commune_role, destination_block_role, destination_property_role | String numérico (1 a 6 dígitos) | No | Obligatorios con timber_enabled (facturador de mercado) | Sólo con timber_enabled | ManejoMadera/ComunaRolDestino, MnzRolDestino, PrdRolDestino |
work_execution_notice, destination_latitude, destination_longitude | String | No | — | Máximo 40 / 30 / 30 caracteres. Sólo con timber_enabled | ManejoMadera/AvisoEjecucionFaena, LatitudDestinoMadera, LongitudDestinoMadera |
transport_type "8" o "9".
Tipo de traslado (transport_type)
| Código | Tipo de traslado | Código | Tipo de traslado |
|---|---|---|---|
"1" | Operación constituye venta | "6" | Otros traslados no venta |
"2" | Ventas por efectuar | "7" | Devolución de mercaderías |
"3" | Consignaciones | "8" | Traslado para exportación (no venta) |
"4" | Entrega gratuita | "9" | Venta para exportación |
"5" | Traslados internos |
Tipo de despacho (dispatch_type)
| Código | Tipo de despacho |
|---|---|
"1" | Por cuenta del receptor (el cliente retira) |
"2" | Por cuenta del emisor, a instalaciones del cliente |
"3" | Por cuenta del emisor, a otras instalaciones |
Datos de Aduana (traslados "8" y "9")
-
El SII los exige en guías con tipo de traslado 8 y 9: con el facturador de mercado,
transfer_issuer_code,departure_port_code,arrival_port_code,gross_weightygross_weight_unit_codeson obligatorios. -
Mismos nombres que en
export_datade la factura de exportación, para usar las mismas llaves en la guía y en la factura. -
Los puertos aceptan el código o el nombre exacto de la tabla de Aduana del SII (
"992"o"AEROP.A.M.BENITEZ", indistintamente). Ejemplos:"906"= SAN ANTONIO,"905"= VALPARAISO,"992"= AEROP.A.M.BENITEZ,"134"= NEW YORK,"292"= SANTOS. -
gross_weight_unit_codeusa la tabla de unidades de Aduana (ej:"6"= KN).package_type_codeusa la tabla de tipos de bulto (ej:"22"= CAJA DE CARTON). -
Tablas completas de puertos, unidades y tipos de bulto: Códigos de transporte y Aduana.
Ejemplo:
"transport_data": { "transport_type": "8", "transfer_issuer_code": "1", "departure_port_code": "AEROP.A.M.BENITEZ", "arrival_port_code": "134", "gross_weight": "1414.00", "gross_weight_unit_code": "6", "total_packages": 3, "package_type_code": "22" }
Emisor del traslado (transfer_issuer_code)
En guías de traslado 8 y 9 el SII exige indicar en qué calidad se emite la guía (Emisor/GuiaExport/CdgTraslado). Sin este dato el SII acepta la guía con reparo (HED-2-804), por eso con el facturador de mercado es obligatorio.
| Código | Emisor del traslado |
|---|---|
"1" | Exportador |
"2" | Agente de Aduana |
"3" | Vendedor |
"4" | Contribuyente autorizado expresamente por el SII: requiere authorization_resolution_number y authorization_resolution_date |
Resolución 154 (DTE 52)
La Resolución Exenta SII N°154 de 2025, prorrogada por la Resolución Exenta N°52 de 2026, fija el contenido mínimo de la guía de despacho y rige desde el 1 de noviembre de 2026. La API aplica las mismas reglas en v1 y v2:- Hasta el 31 de octubre de 2026: la guía se acepta igual y la respuesta del batch trae un aviso por cada dato faltante en
warnings, condocument_index,field,code(res154_*),messageysuggestion. Los avisos también aparecen en el borrador y en la vista previa de la plataforma. - Desde el 1 de noviembre de 2026: los mismos datos faltantes responden
422con el campo bajodocuments→ posición →transport_dataodetails[], y la guía no se crea. El único aviso que nunca pasa a422esres154_trailer_plate.
| Código del aviso | Qué falta | Cómo resolverlo |
|---|---|---|
res154_transfer_type | transport_type | Informar el tipo de traslado "1"–"9" |
res154_carrier | transport_plate, transport_rut o driver_rut + driver_name | Informarlos, o declarar en transport_unknown_reason por qué no se conocen |
res154_destination | Dirección o comuna de destino | destination_address + destination_district, o la dirección y comuna del receptor en document_receiver |
res154_departure | departure_date o departure_time | Fecha y hora de inicio del traslado |
res154_unit | details[].unit | Unidad de medida en cada línea (UN, KG, M3, …) |
res154_transfer_reason | Precio unitario | En un traslado que constituye venta ("1", "9") cada línea lleva unit_price; en los demás se puede omitir si viene transfer_reason |
res154_trailer_plate | trailer_plate | Sólo aviso: si el vehículo lleva carro o remolque, informar su patente |
res75_timber_destination | Rol predial de destino de la madera | destination_commune_role, destination_block_role y destination_property_role (sólo con timber_enabled, facturador de mercado) |
{
"warnings": [
{
"document_index": 0,
"field": "transport_data.departure_time",
"code": "res154_departure",
"message": "La hora de inicio del traslado es obligatoria.",
"suggestion": "Informe transport_data.departure_time (HH:MM)."
}
]
}
Origen efectivo del traslado
La resolución exige el origen efectivo de las mercaderías. La guía toma como origen la dirección del emisor (document_issuer.address, district, city). Puedes usar cualquier dirección de la empresa registrada en el SII (casa matriz o sucursal): Tupana las sincroniza al perfil de la empresa con su código de sucursal, y al coincidir el texto de document_issuer.address con una de ellas la guía sale con ese código en Emisor/CdgSIISucur. Usa exactamente el mismo texto que figura en el perfil de la empresa. Si la bodega no está registrada en el SII, regístrala primero allí; las direcciones no se administran por la API.
Anulación de una guía
Si cambia lo informado (cantidad, destino, transporte), la resolución pide emitir una guía nueva que referencie a la anterior (references[] con dte_type_code "52") y registrar la original como anulada. La anulación se registra con el endpoint de estados del documento:
curl -X POST "https://api.tupana.ai/v2/documents/{document_id}/states/" \
-H "Authorization: Api-Key TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{"event_code": "ANNULLED", "reason": "Reemplazada por guía folio 1051: cambió la cantidad de bultos"}'
200:
{
"success": true,
"annulment": {
"annulled": true,
"already_annulled": false,
"registry": "delivery_note_book",
"registry_note": "La guía queda como anulada en el Libro de Guías de Despacho del período."
}
}
- Sólo el emisor puede anular (
403), sólo guías (DTE 52) emitidas con folio y siempre conreason(400concodeannulment_only_for_delivery_notes,annulment_only_for_issued_delivery_notesoannulment_reason_required). registryindica dónde queda el registro mientras el SII no habilite el Registro de Guías:delivery_note_book(Libro de Guías, facturador de mercado) oportal_follow_up(facturador gratuito del SII: además hay que anotarla en “Seguimiento del documento” del portal).- Anular dos veces responde
200conalready_annulled: true. El mismo endpoint existe en v1 (POST /v1/documents/{document_id}/states/).
Líneas exentas (details[].is_exempt)
is_exempt: truemarca la línea como no afecta o exenta (IndExe = 1en el DTE).- Las líneas exentas suman a
document_total.exempt_amounty no generan IVA; las afectas suman al neto y llevan IVA 19%.total_amount = net_amount + iva_amount + exempt_amount. - Para una guía toda exenta, marca todas las líneas. No hay marca a nivel de documento.
- Por ahora sólo en DTE 52: en otros tipos de documento la API responde
422.
Facturador gratuito del SII (MiPyme)
| Campo | Facturador de mercado | Facturador gratuito |
|---|---|---|
transport_type (incluidos "8" y "9") | ✅ | ✅ |
transport_rut, transport_plate, driver_rut, driver_name, madera (origen) | ✅ | ✅ |
trailer_plate, departure_date, departure_time, arrival_date, transfer_reason, transport_unknown_reason | ✅ (tags del DTE o texto en el detalle) | ✅ (texto en la primera línea del detalle) |
destination_commune_role, destination_block_role, destination_property_role, work_execution_notice, destination_latitude, destination_longitude | ✅ | ❌ 422 |
dispatch_type | ✅ | ✅ (texto en la primera línea del detalle) |
destination_address, destination_district, destination_city | ✅ | ✅ (texto en la primera línea del detalle) |
| Datos de Aduana | ✅ (obligatorios con "8"/"9") | ❌ 422 (no se exigen con "8"/"9") |
details[].is_exempt | ✅ | ❌ 422 |
Destino: Camino Lo Boza 120, Pudahuel, Santiago. Despacho: Por cuenta del emisor a instalaciones del cliente. Salida: 02-11-2026 08:30.
Errores de validación (422)
La guía se valida al recibir el batch, antes de emitir, para no quemar folios con rechazos del SII. Cada error indica el documento y la ruta del campo:| Caso | Respuesta |
|---|---|
transport_type fuera de "1"–"9" o dispatch_type fuera de "1"–"3" | 422 con las opciones válidas |
dispatch_type con transport_type "5" | 422 |
Sólo driver_rut o sólo driver_name | 422: se envían los dos o ninguno |
destination_address > 70, destination_district > 20 o destination_city > 20 caracteres | 422 |
Datos de Aduana con un transport_type distinto de "8"/"9" | 422 |
Traslado "8"/"9" sin puertos, peso bruto o unidad (facturador de mercado) | 422 |
| Puerto, unidad o tipo de bulto fuera de la tabla de Aduana | 422 |
gross_weight o total_packages menor o igual a 0 | 422 |
total_packages sin package_type_code | 422 |
details[].is_exempt en un documento que no es DTE 52 | 422: no soportado para este tipo de documento |
Aduana, destino de la madera o is_exempt con emisor del facturador gratuito | 422: no disponible para emisores del facturador gratuito del SII |
trailer_plate de más de 8 caracteres (sin guion ni espacios) | 422 |
arrival_date anterior a departure_date | 422 |
transfer_reason > 200 o transport_unknown_reason > 100 caracteres | 422 |
| Rol predial de destino de la madera con otra cosa que 1 a 6 dígitos | 422 |
Desde el 1 de noviembre de 2026: falta tipo de traslado, patente/transportista/chofer (sin transport_unknown_reason), destino, salida, details[].unit, precio en una venta o rol predial de destino con madera | 422 (hasta esa fecha, aviso res154_*) |
documents):
{
"documents": [
{
"transport_data": {
"dispatch_type": ["Valor inválido. Opciones: 1, 2, 3."]
}
}
]
}
type validation_error.
Respuesta
GET /v1/documents/{id} y GET /v2/documents/{id}/ devuelven transport_data con todos los campos anteriores, details[].is_exempt y document_total.exempt_amount.
✈️ Factura de Exportación (DTE 110)
Campos requeridos en export_data:
-
destination_country_code(String, Obligatorio):- No es código ISO 3166-1. Es el código de país del SII (ej:
"225"= U.S.A.,"220"= Brasil,"224"= Argentina). Ver Países de exportación para la tabla completa. - Es el destino final de la mercadería (
CodPaisDestin). Si el receptor está en otro país, ver la sección “País y nacionalidad del receptor” más abajo
- No es código ISO 3166-1. Es el código de país del SII (ej:
-
currency_code(String, Obligatorio):- Código de moneda del SII (ej:
"13"= Dólar USA). No es ISO 4217.
- Código de moneda del SII (ej:
-
sale_mode_code(String, Obligatorio):- Código de modalidad de venta del SII (no una cláusula Incoterm). Ver Modalidades de venta de exportación para la tabla completa.
País y nacionalidad del receptor
El DTE de exportación declara tres países distintos. Normalmente son el mismo y basta condestination_country_code. Cuando no coinciden (por ejemplo, el comprador es una distribuidora en Holanda y la carga va directo a Alemania), se informan por separado:
| Campo | Tag del DTE | Si no se envía |
|---|---|---|
destination_country_code | Aduana/CodPaisDestin | Obligatorio |
receiver_country_code | Aduana/CodPaisRecep | Se usa destination_country_code |
receiver_nationality_code | Receptor/Extranjero/Nacionalidad | Se usa receiver_country_code y, si tampoco viene, destination_country_code |
400.
"export_data": {
"destination_country_code": "563",
"receiver_country_code": "515",
"currency_code": "142",
"sale_mode_code": "1"
}
563), el comprador está en Holanda (515) y su nacionalidad también queda como Holanda, porque no se envió receiver_nationality_code.
Cláusula de venta (Incoterm)
-
sale_clause_code(String, Opcional):- Es el Incoterm de la operación (
CodClauVentadel DTE): FOB, EXW, CIF, etc. - No confundir con
sale_mode_code: ése es la modalidad de venta (a firme, en consignación…). Son dos campos distintos del DTE. - Se acepta el código o el nombre:
"5"y"FOB"son equivalentes.
Ejemplo — pasar de Ex Works a FOB:Código Cláusula Código Cláusula "1"CIF "8"OTROS "2"CFR "9"DDP "3"EXW "10"FCA "4"FAS "11"CPT "5"FOB "12"CIP "6"S/CL "17"DAT "18"DAP "export_data": { "destination_country_code": "225", "currency_code": "13", "sale_mode_code": "1", "sale_clause_code": "FOB" } - Es el Incoterm de la operación (
Forma de pago de exportación
-
export_payment_method_code(String, Opcional, por defecto"21"):- Es la forma de pago de la operación de exportación (
FmaPagExpdel DTE). header.payment_methodno aplica a exportación: el DTE de exportación no lleva la forma de pago nacional (contado / crédito), así que ese campo se ignora en los tipos 110, 111 y 112.- Se acepta el código o el nombre:
"11"y"ACRED"son equivalentes.
Código Forma de pago Código Forma de pago "1"COB1 "32"ANTICIPO "2"COBRANZA "50"ANT/COB "11"ACRED "60"ANT/CRED "12"CBOF "80"S/PAGO/COB "21"S/PAGO - Sin el campo el documento sale como sin pago (
"21"): el SII exige entonces que el total en pesos (MntTotOtrMnda) vaya en cero. - Con ANTICIPO (
"32") el DTE declara como fecha de pago la fecha de emisión. - La forma de pago se muestra en el PDF, en el recuadro de exportación.
- Es la forma de pago de la operación de exportación (
Campos específicos del header:
-
sale_transaction_type(Integer, Obligatorio):1: Operación constituye venta - Venta normal2: Ventas por acto o contrato - Contratos especiales3: Boleto de pasaje - Para agencias de viajes
-
currency(String, Obligatorio):"USD": Dólares americanos"EUR": Euros"CLP": Pesos chilenos"UF": Unidades de Fomento
Información del receptor extranjero:
- RUT: Puede usar identificadores especiales como
99999999-9para extranjeros - Dirección: Dirección completa en el extranjero
- País:
document_receiverno lleva país. Los países van enexport_data:destination_country_code(destino) y, si son distintos,receiver_country_codeyreceiver_nationality_code
Precios y cálculos:
- FOB (Free on Board): Los precios deben incluir costos hasta la entrega al transportista
- Moneda: Debe coincidir con
header.currency - Sin IVA: Las exportaciones están exentas de IVA chileno
Requisitos legales:
- Registro de exportación: Debe estar registrado en el sistema aduanero
- Certificado de origen: Puede requerirse según acuerdos comerciales
- Documentos aduaneros: Factura comercial, certificado de origen, etc.
💼 Boletas de Honorarios (DTE 80, 90)
Campos específicos del header:
retention_type(String, Obligatorio):"RETRECEPTOR": La retención la realiza el receptor (99% de los casos)"RETCONTRIBUYENTE": La retención la realiza el contribuyente emisor (casos excepcionales)
authorized_user_rut(String, Opcional): RUT del usuario autorizado por el SII (dueño de la credencialsii_company) que emite en representación del emisor. Selecciona determinísticamente la credencial cuando hay varias accesibles. Solo válido para DTE 80 y 90.
Retención automática del 14.5%:
- Cálculo: Se aplica sobre el monto bruto antes de IVA
- Responsable: Normalmente el pagador retiene y declara el impuesto
- Pago al profesional: Se paga el 85.5% restante (bruto menos retención)
Información del receptor (profesional):
- Campos opcionales: A diferencia de facturas, no todos los datos son obligatorios
- RUT obligatorio: Siempre se requiere el RUT del profesional
- Actividad económica: Debe corresponder a servicios profesionales
Diferencias entre DTE 80 y 90:
DTE 80 - Boleta de Honorarios:- Emisión directa por el pagador al profesional
- Relación directa pagador-profesional
- document_issuer: Quien paga (empresa o persona que contrata)
- Emisión por intermediario (plataformas, marketplaces)
- document_issuer: Contribuyente real (quien paga — restaurante, empresa cliente)
- document_receiver: Profesional que recibe (repartidor, freelancer, instructor)
- Requiere enrolamiento de usuarios autorizados para emisión por terceros
- Misma estructura de request que DTE 80; solo cambia
dte_type.code: "90"
Validaciones específicas:
- Tope mensual: Límite de emisión sin retención ampliada
- Tipo de servicio: Debe corresponder a honorarios profesionales
- Declaración: El retenedor debe declarar y pagar el impuesto retenido
Casos de uso:
- DTE 80: Honorarios de abogados, contadores, médicos; servicios de consultoría; pagos directos a freelancers
- DTE 90: Apps de delivery (Rappi, Uber Eats); plataformas freelance; marketplaces de servicios; plataformas educativas
🔒 Seguridad y URLs temporales
URLs de archivos temporales:
- PDF y XML: URLs válidas por 1 hora aproximadamente
- Autenticación: Incluyen tokens de acceso automático
- Recomendación: Descargar inmediatamente al recibir el webhook
Medidas de seguridad:
- Encriptación: Archivos transmitidos de forma segura
- Validación: Solo el emisor puede acceder a sus documentos
- Auditoría: Todas las descargas quedan registradas
Authorizations
API Key para autenticación. Debe proporcionarse en el header Authorization con el formato: 'Api-Key YOUR-API-KEY' (incluye el prefijo 'Api-Key ' seguido de tu API key)
Headers
Previene lotes duplicados (≤ 256 caracteres, expira después de 24 h)
Si se establece como true, el sistema usará valores por defecto para campos no proporcionados:
- Fecha actual para date_issued
- Datos del emisor según configuración de la plataforma o primera actividad/dirección disponible
- Datos del receptor según configuración del cliente o primera actividad/dirección disponible
- Payment method = '2' (crédito) en el header del documento
Body
Lote de documentos a crear
Array de documentos a crear (máximo 200)
Show child attributes
Show child attributes
Response
Solicitud de creación de documentos aceptada. Los resultados se enviarán por webhook.
Identificador único del lote
Estado del batch
created, processing, completed, failed "processing"
Fecha y hora de creación del batch
Array de documentos procesados en el batch
Show child attributes
Show child attributes
Avisos sobre campos desconocidos que se ignoraron (modo aviso). Sólo aparece si hay avisos. Con validación estricta, la API responde 422 en vez de avisar.
Show child attributes
Show child attributes
