REST · ¿Me avisan si cambia?
Vigilancia de RUT
Tus listas de RUT, verificadas contra cada publicación del SII, con las novedades —también las del Boletín Concursal— por API, correo o webhook. Los ejemplos de abajo son la petición y la respuesta real de cada operación, no una aproximación.
Lo que descuenta cada operación es lo mismo por REST, SOAP, GraphQL y MCP —pagas por el dato, no por el protocolo—; la tabla completa está en Empezar.
GET /v1/vigilancia/novedades
Las novedades de tu cartera
Lo que el SII o el Boletín Concursal publicó sobre los RUT que vigilas, ya entregado: se lee las veces que quieras, por cualquier mecanismo. De la más antigua a la más nueva desde el cursor, con retenidas diciendo cuántas esperan a que tu cuenta tenga consultas.
Parámetros
| Parámetro | Tipo | Qué es |
|---|---|---|
desde | string | Solo las entregadas desde ese día, inclusive, en hora de Chile. Por defecto todas. ISO 8601 solo fecha (1993-01-01), sin hora ni zona. |
lista | string | Solo las de esa lista (su id). Por defecto todas las tuyas. |
limite | integer | Novedades por página: 1 a 500. Por defecto 100. |
pagina | string | El pagina_siguiente de la respuesta anterior. Lleva los filtros adentro: o no los repites, o los repites todos iguales. |
Lo que devuelve
| Campo | Tipo | Qué es |
|---|---|---|
novedades | array | La página de novedades, de la más antigua a la más nueva. Vacía si no hay nada nuevo desde el cursor. |
hay_mas | boolean | true si quedan más novedades por pedir. |
pagina_siguiente | string | Pásalo tal cual en pagina para pedir la siguiente. null cuando no hay más. Lleva los filtros adentro: no los repitas distintos. |
retenidas | integer | Cuántas novedades esperan a que tu cuenta tenga consultas: se entregan solas cuando alcance. 0 mientras tengas plan o saldo. |
fuente | string | De dónde salen los datos de esta respuesta, en texto listo para citar («Tus listas, cruzadas con el historial de cambios del padrón del SII»). Es constante para esta llamada: guárdalo una vez y no lo parsees. |
padron_publicado | string | De cuándo son las nóminas vigentes del padrón. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. Es la publicación contra la que se verifica cada RUT vigilado. |
consultado_en | string | Cuándo se respondió esta llamada. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. |
Dentro de novedades
| Campo | Tipo | Qué es |
|---|---|---|
id | integer | El id de la novedad, creciente: es por lo que se pagina. |
rut | string | El RUT vigilado que cambió, normalizado. |
rut_formateado | string | El mismo RUT listo para mostrar. |
razon_social | string | Su nombre legal hoy según el padrón; si salió del padrón, el que tenía. |
descripcion | string | Qué cambió, en una frase («Cambió de razón social», «Salió del padrón»): la misma que el correo y el panel. |
publicado | string | La publicación del SII en que apareció el cambio. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. Es la fecha con la que se pagina y se filtra. |
aspecto | string | Qué parte de la ficha cambió: contribuyente, domicilios, actividades, casilla, concurso. contribuyente es la razón social, la clasificación de sociedad, el inicio de actividades y el término de giro; domicilios, actividades y casilla, sus listas y la casilla; y concurso, sus procedimientos concursales según el Boletín Concursal: hay un cambio cuando la empresa registra o deja de registrar un procedimiento, o cuando uno cambia de materia. |
tipo | string | alta, baja, cambio: apareció, desapareció o cambió. Un RUT que sale del padrón es una baja de contribuyente. |
campos | array | En un cambio de contribuyente, qué campos difieren entre antes y despues (razon_social, cod_subtipo, inicio_actividades, termino_giro). null en los demás: un alta o una baja no tienen qué comparar, y los otros aspectos son listas. |
antes | object|array | Cómo era, con la forma que ese aspecto tiene en la ficha: un objeto para contribuyente y casilla, la lista completa para domicilios y actividades, y para concurso la lista de sus procedimientos con rol_causa, tribunal, tipo y apertura. null en un alta. |
despues | object|array | Cómo quedó, con la misma forma. null en una baja. |
lista | string | El nombre de la lista en que vigilas ese RUT. |
etiqueta | string | La etiqueta que le pusiste al RUT en esa lista. "" si no. |
entregada_en | string | Cuándo se entregó y se descontó esta novedad. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. |
Cuándo responde cada cosa
- 200 Siempre que la key sirva: cada novedad ya se descontó al entregarse, y leerla no descuenta. Vacía mientras el SII no publique nada sobre tus RUT. No descuenta.
- 401 No mandaste el header, o no empieza con dtr_. No descuenta.
- 401 La key viajó bien pero ya no sirve: la revocaste o la rotaste. No descuenta.
-
422
desdeno es un día. No descuenta. -
422
listano es un id, o no es de una lista tuya. No descuenta. -
422
limiteno es un entero en el rango. No descuenta. - 422 El token de página llegó adulterado o incompleto. Se pide de nuevo desde la primera. No descuenta.
-
422
Con
pagina, los filtros van DENTRO del token. Idénticos se aceptan; distintos no. No descuenta. -
429
Fuiste más rápido que las consultas por minuto de tu plan.
Retry-Afterdice cuánto esperar. No descuenta.
curl -s -i -H "Authorization: Bearer dtr_TU_KEY" \
https://api.datario.cl/v1/vigilancia/novedades
import requests
r = requests.get(
"https://api.datario.cl/v1/vigilancia/novedades",
headers={"Authorization": "Bearer dtr_TU_KEY"},
timeout=10,
)
cuerpo = r.json()
if r.status_code != 200:
raise SystemExit(f"{cuerpo['error']}: {cuerpo['detail']}")
print(cuerpo["retenidas"])
print(r.headers.get("X-Plan-Remaining"), "restantes")
const r = await fetch(
"https://api.datario.cl/v1/vigilancia/novedades",
{ headers: { "Authorization": "Bearer dtr_TU_KEY" } },
);
const cuerpo = await r.json();
if (!r.ok) {
if (r.status === 429) {
const s = r.headers.get("Retry-After");
throw new Error(`Reintenta en ${s} s`);
}
throw new Error(`${cuerpo.error}: ${cuerpo.detail}`);
}
console.log(cuerpo.retenidas);
<?php
$ch = curl_init(
"https://api.datario.cl/v1/vigilancia/novedades"
);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer dtr_TU_KEY"],
]);
$cuerpo = json_decode(curl_exec($ch), true);
$estado = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($estado !== 200) {
throw new Exception(
$cuerpo["error"] . ": " . $cuerpo["detail"]
);
}
echo $cuerpo["retenidas"];
using var http = new HttpClient();
http.DefaultRequestHeaders.Add(
"Authorization", "Bearer dtr_TU_KEY");
var r = await http.GetAsync(
"https://api.datario.cl/v1/vigilancia/novedades");
var raiz = JsonDocument.Parse(
await r.Content.ReadAsStringAsync()).RootElement;
if (!r.IsSuccessStatusCode)
{
throw new Exception(
raiz.GetProperty("error").GetString() + ": " +
raiz.GetProperty("detail").GetString());
}
Console.WriteLine(
raiz.GetProperty("retenidas").GetString());
var req = HttpRequest.newBuilder()
.uri(URI.create(
"https://api.datario.cl/v1/vigilancia/novedades"))
.header("Authorization", "Bearer dtr_TU_KEY")
.build();
var r = HttpClient.newHttpClient()
.send(req, BodyHandlers.ofString());
if (r.statusCode() != 200) {
// El cuerpo trae siempre {error, detail}.
throw new IOException(r.body());
}
System.out.println(r.body());
req, _ := http.NewRequest("GET",
"https://api.datario.cl/v1/vigilancia/novedades", nil)
req.Header.Set("Authorization", "Bearer dtr_TU_KEY")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
if res.StatusCode != 200 {
var e struct {
Error string `json:"error"`
Detail string `json:"detail"`
}
json.NewDecoder(res.Body).Decode(&e)
log.Fatalf("%s: %s", e.Error, e.Detail)
}
var cuerpo map[string]any
json.NewDecoder(res.Body).Decode(&cuerpo)
fmt.Println(cuerpo["retenidas"])
uri = URI("https://api.datario.cl/v1/vigilancia/novedades")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer dtr_TU_KEY"
res = Net::HTTP.start(
uri.host, uri.port, use_ssl: uri.scheme == "https"
) { |h| h.request(req) }
cuerpo = JSON.parse(res.body)
unless res.code == "200"
raise "#{cuerpo['error']}: #{cuerpo['detail']}"
end
puts cuerpo["retenidas"]
Set Variable [ $url ; Value:
"https://api.datario.cl/v1/vigilancia/novedades" ]
Insert from URL [ Select ; With dialog: Off ; Target: $r ;
$url ; cURL options:
"-H \"Authorization: Bearer dtr_TU_KEY\"" ]
Set Variable [ $e ; Value: JSONGetElement ( $r ; "error" ) ]
If [ not IsEmpty ( $e ) ]
Show Custom Dialog [ $e & ": " &
JSONGetElement ( $r ; "detail" ) ]
Exit Script [ Text Result: $e ]
End If
Show Custom Dialog [
JSONGetElement ( $r ; "retenidas" ) ]
Respuestas
{
"novedades": [],
"hay_mas": false,
"pagina_siguiente": null,
"retenidas": 0,
"fuente": "Tus listas, cruzadas con el historial de cambios del padrón del SII",
"padron_publicado": "2026-08-05T15:36:37+00:00",
"consultado_en": "2026-08-29T04:12:07+00:00"
}
Headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset
{
"error": "api_key_invalida",
"detail": "Falta la API key: envíala en el header Authorization: Bearer dtr_…."
}
{
"error": "api_key_invalida",
"detail": "La API key no existe o fue revocada."
}
{
"error": "parametros_invalidos",
"detail": "desde debe ser un día ISO 8601 (YYYY-MM-DD)."
}
{
"error": "parametros_invalidos",
"detail": "lista debe ser el id de una de tus listas."
}
{
"error": "parametros_invalidos",
"detail": "limite debe ser un entero entre 1 y 500."
}
{
"error": "parametros_invalidos",
"detail": "pagina no es válida: pide la primera página sin ese parámetro."
}
{
"error": "parametros_invalidos",
"detail": "pagina ya lleva los filtros: no los repitas distintos."
}
{
"error": "limite_de_velocidad",
"detail": "Superaste las consultas por minuto de tu plan: X-RateLimit-Limit dice cuántas y Retry-After cuánto esperar."
}
Headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset Retry-After
Gestionar las listas
Lo que vigilas son listas de RUT: se crean, se les agregan RUT —de a muchos, con una etiqueta opcional por RUT— y se les quitan. Es administración y va por REST y solo por REST, con la misma key. Solo el alta descuenta: es la primera verificación de cada RUT nuevo; después, una por cada nómina nueva que publique el SII. Si las consultas no alcanzan para todos los RUT nuevos, no entra ninguno.
Lo mismo se hace a mano en el panel, donde además se sube un CSV.
GET /v1/vigilancia/listas
Tus listas
Las listas de RUT que vigilas: cuántos RUT tiene cada una y cuántos ya vieron la última publicación del SII. No descuenta.
Lo que devuelve
| Campo | Tipo | Qué es |
|---|---|---|
listas | array | Tus listas, de la más antigua a la más nueva. |
fuente | string | De dónde salen los datos de esta respuesta, en texto listo para citar («Tus listas, cruzadas con el historial de cambios del padrón del SII»). Es constante para esta llamada: guárdalo una vez y no lo parsees. |
padron_publicado | string | De cuándo son las nóminas vigentes del padrón. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. Es la publicación contra la que se verifica cada RUT vigilado. |
consultado_en | string | Cuándo se respondió esta llamada. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. |
Dentro de listas
| Campo | Tipo | Qué es |
|---|---|---|
id | string | El id de la lista: el que va en la ruta de las demás llamadas. |
nombre | string | Su nombre, único entre tus listas. |
ruts | integer | Cuántos RUT vigila. |
al_dia | integer | Cuántos de ellos ya se verificaron contra la última publicación del SII (padron_publicado). Los que faltan se verifican, y descuentan, en la próxima revisión diaria en que tu cuenta tenga consultas. |
creada_en | string | Cuándo se creó. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. |
Cuándo responde cada cosa
- 200 Siempre que la key sirva. Sin listas, la lista viene vacía. No descuenta.
- 401 No mandaste el header, o no empieza con dtr_. No descuenta.
- 401 La key viajó bien pero ya no sirve: la revocaste o la rotaste. No descuenta.
-
429
Fuiste más rápido que las consultas por minuto de tu plan.
Retry-Afterdice cuánto esperar. No descuenta.
curl -s -i -X GET -H "Authorization: Bearer dtr_TU_KEY" \
https://api.datario.cl/v1/vigilancia/listas
Respuestas
{
"listas": [
{
"id": "8c2a6d3e-5f4b-4a1c-9e7d-2b3c4d5e6f70",
"nombre": "proveedores",
"ruts": 3,
"al_dia": 3,
"creada_en": "2026-08-29T04:12:07+00:00"
}
],
"fuente": "Tus listas, cruzadas con el historial de cambios del padrón del SII",
"padron_publicado": "2026-08-05T15:36:37+00:00",
"consultado_en": "2026-08-29T04:12:07+00:00"
}
Headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset
{
"error": "api_key_invalida",
"detail": "Falta la API key: envíala en el header Authorization: Bearer dtr_…."
}
{
"error": "api_key_invalida",
"detail": "La API key no existe o fue revocada."
}
{
"error": "limite_de_velocidad",
"detail": "Superaste las consultas por minuto de tu plan: X-RateLimit-Limit dice cuántas y Retry-After cuánto esperar."
}
Headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset Retry-After
POST /v1/vigilancia/listas
Crear una lista
Una lista nueva, vacía, con su nombre. No descuenta: lo que descuenta es cada RUT al entrar.
Lo que devuelve
| Campo | Tipo | Qué es |
|---|---|---|
id | string | El id de la lista: el que va en la ruta de las demás llamadas. |
nombre | string | Su nombre, único entre tus listas. |
ruts | integer | Cuántos RUT vigila. |
al_dia | integer | Cuántos de ellos ya se verificaron contra la última publicación del SII (padron_publicado). Los que faltan se verifican, y descuentan, en la próxima revisión diaria en que tu cuenta tenga consultas. |
creada_en | string | Cuándo se creó. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. |
fuente | string | De dónde salen los datos de esta respuesta, en texto listo para citar («Tus listas, cruzadas con el historial de cambios del padrón del SII»). Es constante para esta llamada: guárdalo una vez y no lo parsees. |
padron_publicado | string | De cuándo son las nóminas vigentes del padrón. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. Es la publicación contra la que se verifica cada RUT vigilado. |
consultado_en | string | Cuándo se respondió esta llamada. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. |
Cuándo responde cada cosa
- 200 La lista se creó. Nace vacía y sin RUT al día que verificar. No descuenta.
- 401 No mandaste el header, o no empieza con dtr_. No descuenta.
- 401 La key viajó bien pero ya no sirve: la revocaste o la rotaste. No descuenta.
-
429
Fuiste más rápido que las consultas por minuto de tu plan.
Retry-Afterdice cuánto esperar. No descuenta. - 422 El cuerpo no es JSON, o no trae los campos con su forma. No descuenta.
- 413 El JSON pasa de 16.384 bytes. Este cuerpo es un nombre: nada de lo que se manda acá pesa tanto. No descuenta.
- 422 El nombre viene vacío o demasiado largo. No descuenta.
- 422 Ya tienes otra lista con ese nombre: no se repiten dentro de una cuenta. No descuenta.
- 422 Ya tienes el máximo de listas: 20 por cuenta. No descuenta.
curl -s -i -X POST -H "Authorization: Bearer dtr_TU_KEY" \
-H "Content-Type: application/json" \
-d '{
"nombre": "proveedores"
}' \
https://api.datario.cl/v1/vigilancia/listas
Respuestas
{
"id": "8c2a6d3e-5f4b-4a1c-9e7d-2b3c4d5e6f70",
"nombre": "proveedores",
"ruts": 0,
"al_dia": 0,
"creada_en": "2026-08-29T04:12:07+00:00",
"fuente": "Tus listas, cruzadas con el historial de cambios del padrón del SII",
"padron_publicado": "2026-08-05T15:36:37+00:00",
"consultado_en": "2026-08-29T04:12:07+00:00"
}
Headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset
{
"error": "api_key_invalida",
"detail": "Falta la API key: envíala en el header Authorization: Bearer dtr_…."
}
{
"error": "api_key_invalida",
"detail": "La API key no existe o fue revocada."
}
{
"error": "limite_de_velocidad",
"detail": "Superaste las consultas por minuto de tu plan: X-RateLimit-Limit dice cuántas y Retry-After cuánto esperar."
}
Headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset Retry-After
{
"error": "cuerpo_invalido",
"detail": "El cuerpo debe ser un objeto JSON con la forma documentada."
}
{
"error": "cuerpo_demasiado_grande",
"detail": "El cuerpo supera el tope de bytes de esta petición."
}
{
"error": "parametros_invalidos",
"detail": "nombre no puede quedar vacío ni pasar de 64 caracteres."
}
{
"error": "nombre_ocupado",
"detail": "Ya tienes una lista con ese nombre."
}
{
"error": "demasiadas_listas",
"detail": "Llegaste al máximo de listas de tu cuenta."
}
GET /v1/vigilancia/listas/{id}
Una lista con sus RUT
La lista con sus RUT, de a 100 por página, cada uno con cuándo entró, cuándo se verificó por última vez y contra qué publicación. No descuenta.
Parámetros
| Parámetro | Tipo | Qué es |
|---|---|---|
pagina | string | El pagina_siguiente de la respuesta anterior. |
Lo que devuelve
| Campo | Tipo | Qué es |
|---|---|---|
id | string | El id de la lista: el que va en la ruta de las demás llamadas. |
nombre | string | Su nombre, único entre tus listas. |
ruts | integer | Cuántos RUT vigila. |
al_dia | integer | Cuántos de ellos ya se verificaron contra la última publicación del SII (padron_publicado). Los que faltan se verifican, y descuentan, en la próxima revisión diaria en que tu cuenta tenga consultas. |
creada_en | string | Cuándo se creó. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. |
items | array | Los RUT de la lista, en el orden en que entraron. |
hay_mas | boolean | true si quedan más RUT por pedir. |
pagina_siguiente | string | Pásalo tal cual en pagina para la siguiente página de RUT. null al final. |
fuente | string | De dónde salen los datos de esta respuesta, en texto listo para citar («Tus listas, cruzadas con el historial de cambios del padrón del SII»). Es constante para esta llamada: guárdalo una vez y no lo parsees. |
padron_publicado | string | De cuándo son las nóminas vigentes del padrón. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. Es la publicación contra la que se verifica cada RUT vigilado. |
consultado_en | string | Cuándo se respondió esta llamada. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. |
Dentro de items
| Campo | Tipo | Qué es |
|---|---|---|
rut | string | El RUT vigilado, normalizado. |
rut_formateado | string | El mismo RUT listo para mostrar. |
etiqueta | string | La etiqueta que le pusiste. "" si no. |
agregado_el | string | Cuándo entró a la lista. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. |
verificado_el | string | La última verificación descontada. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. |
publicacion_verificada | string | La publicación del SII contra la que se verificó. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. Si es anterior a padron_publicado, este RUT todavía no vio la última nómina. |
Cuándo responde cada cosa
- 200 La lista es tuya. No descuenta.
- 401 No mandaste el header, o no empieza con dtr_. No descuenta.
- 401 La key viajó bien pero ya no sirve: la revocaste o la rotaste. No descuenta.
-
429
Fuiste más rápido que las consultas por minuto de tu plan.
Retry-Afterdice cuánto esperar. No descuenta. - 404 El id no es de una lista tuya. La de otra cuenta tampoco existe para ti. No descuenta.
- 422 El token de página llegó adulterado o incompleto. Se pide de nuevo desde la primera. No descuenta.
LISTA=8c2a6d3e-5f4b-4a1c-9e7d-2b3c4d5e6f70
curl -s -i -X GET -H "Authorization: Bearer dtr_TU_KEY" \
https://api.datario.cl/v1/vigilancia/listas/$LISTA
Respuestas
{
"id": "8c2a6d3e-5f4b-4a1c-9e7d-2b3c4d5e6f70",
"nombre": "proveedores",
"ruts": 1,
"al_dia": 1,
"creada_en": "2026-08-29T04:12:07+00:00",
"items": [
{
"rut": "61704000-K",
"rut_formateado": "61.704.000-K",
"etiqueta": "casa matriz",
"agregado_el": "2026-08-29T04:12:07+00:00",
"verificado_el": "2026-08-29T04:12:07+00:00",
"publicacion_verificada": "2026-08-05T15:36:37+00:00"
}
],
"hay_mas": false,
"pagina_siguiente": null,
"fuente": "Tus listas, cruzadas con el historial de cambios del padrón del SII",
"padron_publicado": "2026-08-05T15:36:37+00:00",
"consultado_en": "2026-08-29T04:12:07+00:00"
}
Headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset
{
"error": "api_key_invalida",
"detail": "Falta la API key: envíala en el header Authorization: Bearer dtr_…."
}
{
"error": "api_key_invalida",
"detail": "La API key no existe o fue revocada."
}
{
"error": "limite_de_velocidad",
"detail": "Superaste las consultas por minuto de tu plan: X-RateLimit-Limit dice cuántas y Retry-After cuánto esperar."
}
Headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset Retry-After
{
"error": "lista_no_encontrada",
"detail": "No tienes una lista con ese id."
}
{
"error": "parametros_invalidos",
"detail": "pagina no es válida: pide la primera página sin ese parámetro."
}
DELETE /v1/vigilancia/listas/{id}
Borrar una lista
Borra la lista con todos sus RUT. Las novedades ya entregadas se conservan (las pagaste); las retenidas de esa lista se descartan sin descontar. No devuelve lo descontado por las verificaciones ya hechas.
Lo que devuelve
| Campo | Tipo | Qué es |
|---|---|---|
id | string | El id de la lista borrada. |
borrada | boolean | Siempre true: si no era tuya, es el 404. |
ruts | integer | Cuántos RUT vigilaba. |
fuente | string | De dónde salen los datos de esta respuesta, en texto listo para citar («Tus listas, cruzadas con el historial de cambios del padrón del SII»). Es constante para esta llamada: guárdalo una vez y no lo parsees. |
padron_publicado | string | De cuándo son las nóminas vigentes del padrón. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. Es la publicación contra la que se verifica cada RUT vigilado. |
consultado_en | string | Cuándo se respondió esta llamada. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. |
Cuándo responde cada cosa
- 200 La lista era tuya y se borró. No descuenta.
- 401 No mandaste el header, o no empieza con dtr_. No descuenta.
- 401 La key viajó bien pero ya no sirve: la revocaste o la rotaste. No descuenta.
-
429
Fuiste más rápido que las consultas por minuto de tu plan.
Retry-Afterdice cuánto esperar. No descuenta. - 404 El id no es de una lista tuya. La de otra cuenta tampoco existe para ti. No descuenta.
LISTA=8c2a6d3e-5f4b-4a1c-9e7d-2b3c4d5e6f70
curl -s -i -X DELETE -H "Authorization: Bearer dtr_TU_KEY" \
https://api.datario.cl/v1/vigilancia/listas/$LISTA
Respuestas
{
"id": "8c2a6d3e-5f4b-4a1c-9e7d-2b3c4d5e6f70",
"borrada": true,
"ruts": 3,
"fuente": "Tus listas, cruzadas con el historial de cambios del padrón del SII",
"padron_publicado": "2026-08-05T15:36:37+00:00",
"consultado_en": "2026-08-29T04:12:07+00:00"
}
Headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset
{
"error": "api_key_invalida",
"detail": "Falta la API key: envíala en el header Authorization: Bearer dtr_…."
}
{
"error": "api_key_invalida",
"detail": "La API key no existe o fue revocada."
}
{
"error": "limite_de_velocidad",
"detail": "Superaste las consultas por minuto de tu plan: X-RateLimit-Limit dice cuántas y Retry-After cuánto esperar."
}
Headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset Retry-After
{
"error": "lista_no_encontrada",
"detail": "No tienes una lista con ese id."
}
POST /v1/vigilancia/listas/{id}/rut
Agregar RUT a una lista
Agrega RUT a la lista, con o sin etiqueta. Descuenta UNA consulta por RUT NUEVO —es su primera verificación, contra la publicación vigente del SII—; los que ya estaban no descuentan. Después, cada RUT descuenta una consulta por cada nómina nueva que publique el SII, y una por cada novedad al entregarse. Todo o nada: si no alcanza para los nuevos, no entra ninguno.
Se vigila lo que el padrón nombra: una fila mal escrita o un RUT que el SII no publica con nombre se DESCARTA —sin descontar y sin botar el resto— y sale contado en descartados. No hay tope de cuántos RUT mandar en una llamada: el límite es cuántos caben en la lista.
Lo que devuelve
| Campo | Tipo | Qué es |
|---|---|---|
agregados | integer | Cuántos RUT entraron: los que se descontaron. |
repetidos | integer | Cuántos no entraron porque ese RUT ya se estaba vigilando en esa lista, contando los que venían dos veces en la misma carga. No se descuentan. agregados + repetidos + los dos descartados dan la cuenta de las filas que mandaste. |
descartados | object | Los que no entraron, por causa. Ninguno se descuenta. |
total | integer | Cuántos RUT vigila la lista después de esta llamada. |
fuente | string | De dónde salen los datos de esta respuesta, en texto listo para citar («Tus listas, cruzadas con el historial de cambios del padrón del SII»). Es constante para esta llamada: guárdalo una vez y no lo parsees. |
padron_publicado | string | De cuándo son las nóminas vigentes del padrón. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. Es la publicación contra la que se verifica cada RUT vigilado. |
consultado_en | string | Cuándo se respondió esta llamada. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. |
Dentro de descartados
| Campo | Tipo | Qué es |
|---|---|---|
mal_escritos | integer | Cuántos no pasaron el dígito verificador. Revisa esas filas y vuelve a mandarlas. |
no_disponibles | integer | Cuántos no están disponibles para vigilar: el SII no los publica con nombre. Se vigila lo que el padrón nombra, o sea personas jurídicas. |
Cuándo responde cada cosa
-
200
Entraron RUT nuevos: descuenta uno por cada uno. Si todos ya estaban, descuenta cero, la llamada vale igual y las cabeceras
X-Plan-*no viajan: no hubo cobro que las traiga. Descuenta una consulta. - 401 No mandaste el header, o no empieza con dtr_. No descuenta.
- 401 La key viajó bien pero ya no sirve: la revocaste o la rotaste. No descuenta.
-
429
Fuiste más rápido que las consultas por minuto de tu plan.
Retry-Afterdice cuánto esperar. No descuenta. - 404 El id no es de una lista tuya. La de otra cuenta tampoco existe para ti. No descuenta.
- 422 El cuerpo no es JSON, o no trae los campos con su forma. No descuenta.
- 413 El JSON pasa de 5,0 MB. Mándalos en varias cargas. No descuenta.
- 422 La lista llegaría a más de 50.000 RUT. No descuenta.
- 503 El padrón todavía no tiene datos que responder. Es excepcional: reintenta más tarde y, si sigue, mira el estado del servicio. No descuenta.
- 402 Se agotaron las consultas del plan y no hay saldo de recargas. Las consultas se detienen hasta que renueven. No descuenta.
- 402 Se agotaron las consultas del plan, hay saldo de recargas, y el interruptor «usar mi saldo automáticamente» está apagado. Nada se cobra. No descuenta.
LISTA=8c2a6d3e-5f4b-4a1c-9e7d-2b3c4d5e6f70
curl -s -i -X POST -H "Authorization: Bearer dtr_TU_KEY" \
-H "Content-Type: application/json" \
-d '{
"ruts": [
{
"rut": "61.704.000-K",
"etiqueta": "casa matriz"
},
"76.913.653-3"
]
}' \
https://api.datario.cl/v1/vigilancia/listas/$LISTA/rut
Respuestas
{
"agregados": 2,
"repetidos": 0,
"descartados": {
"mal_escritos": 0,
"no_disponibles": 0
},
"total": 2,
"fuente": "Tus listas, cruzadas con el historial de cambios del padrón del SII",
"padron_publicado": "2026-08-05T15:36:37+00:00",
"consultado_en": "2026-08-29T04:12:07+00:00"
}
Headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset X-Plan-Limit X-Plan-Remaining X-Plan-Reset X-Credits-Remaining
{
"error": "api_key_invalida",
"detail": "Falta la API key: envíala en el header Authorization: Bearer dtr_…."
}
{
"error": "api_key_invalida",
"detail": "La API key no existe o fue revocada."
}
{
"error": "limite_de_velocidad",
"detail": "Superaste las consultas por minuto de tu plan: X-RateLimit-Limit dice cuántas y Retry-After cuánto esperar."
}
Headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset Retry-After
{
"error": "lista_no_encontrada",
"detail": "No tienes una lista con ese id."
}
{
"error": "cuerpo_invalido",
"detail": "El cuerpo debe ser un objeto JSON con la forma documentada."
}
{
"error": "cuerpo_demasiado_grande",
"detail": "El cuerpo supera el tope de bytes de esta petición."
}
{
"error": "lista_llena",
"detail": "Esa lista no admite tantos RUT más."
}
{
"error": "padron_no_disponible",
"detail": "El padrón aún no está cargado; intenta más tarde. Estado del servicio: https://status.datario.cl"
}
{
"error": "sin_saldo",
"detail": "Se acabaron las consultas de tu plan y no te queda saldo. Renuevan el día que tu plan cumple el mes (X-Plan-Reset); para seguir ahora, recarga saldo (no vence) en https://datario.cl/panel/packs, o contrata el plan de ese mismo volumen en https://datario.cl/panel/planes, que sale más barato por consulta"
}
Headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset
{
"error": "saldo_protegido",
"detail": "Las consultas del plan no alcanzan y tu saldo está protegido (pediste no gastarlo automáticamente): actívalo en https://datario.cl/panel/configuracion/avisos o renueva tu plan"
}
Headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset
DELETE /v1/vigilancia/listas/{id}/rut/{rut}
Quitar un RUT de una lista
Deja de vigilar ese RUT en esa lista. No descuenta ni devuelve nada.
Lo que devuelve
| Campo | Tipo | Qué es |
|---|---|---|
rut | string | El RUT que salió, normalizado. |
quitado | boolean | Siempre true: si no estaba, es el 404. |
fuente | string | De dónde salen los datos de esta respuesta, en texto listo para citar («Tus listas, cruzadas con el historial de cambios del padrón del SII»). Es constante para esta llamada: guárdalo una vez y no lo parsees. |
padron_publicado | string | De cuándo son las nóminas vigentes del padrón. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. Es la publicación contra la que se verifica cada RUT vigilado. |
consultado_en | string | Cuándo se respondió esta llamada. ISO 8601 con hora y zona (2026-08-05T15:36:37+00:00), siempre en UTC. |
Cuándo responde cada cosa
- 200 El RUT estaba en la lista y salió. No descuenta.
- 401 No mandaste el header, o no empieza con dtr_. No descuenta.
- 401 La key viajó bien pero ya no sirve: la revocaste o la rotaste. No descuenta.
-
429
Fuiste más rápido que las consultas por minuto de tu plan.
Retry-Afterdice cuánto esperar. No descuenta. - 422 El dígito verificador no corresponde al cuerpo. No se cobra: no hubo consulta. No descuenta.
- 404 El id no es de una lista tuya. La de otra cuenta tampoco existe para ti. No descuenta.
- 404 El RUT no estaba en la lista: no hay nada que quitar. No descuenta.
LISTA=8c2a6d3e-5f4b-4a1c-9e7d-2b3c4d5e6f70
curl -s -i -X DELETE -H "Authorization: Bearer dtr_TU_KEY" \
https://api.datario.cl/v1/vigilancia/listas/$LISTA/rut/61704000-K
Respuestas
{
"rut": "61704000-K",
"quitado": true,
"fuente": "Tus listas, cruzadas con el historial de cambios del padrón del SII",
"padron_publicado": "2026-08-05T15:36:37+00:00",
"consultado_en": "2026-08-29T04:12:07+00:00"
}
Headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset
{
"error": "api_key_invalida",
"detail": "Falta la API key: envíala en el header Authorization: Bearer dtr_…."
}
{
"error": "api_key_invalida",
"detail": "La API key no existe o fue revocada."
}
{
"error": "limite_de_velocidad",
"detail": "Superaste las consultas por minuto de tu plan: X-RateLimit-Limit dice cuántas y Retry-After cuánto esperar."
}
Headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset Retry-After
{
"error": "rut_invalido",
"detail": "El RUT no es válido: revisa el dígito verificador."
}
{
"error": "lista_no_encontrada",
"detail": "No tienes una lista con ese id."
}
{
"error": "rut_no_vigilado",
"detail": "Ese RUT no está en esa lista."
}
POST tu URL
El webhook: las novedades, en tu servidor
Cada vez que se entregan novedades de tu cartera, Datario le hace un POST a la URL que registres en el panel, con el cuerpo de abajo y una firma que solo tú puedes verificar. El secreto se muestra una sola vez, al registrar la URL o al generar uno nuevo. Solo https, a un servidor público; una redirección cuenta como rechazo.
Cabeceras
| Cabecera | Qué es |
|---|---|
X-Datario-Entrega | El id de la entrega. Si tu servidor la recibe dos veces —un reintento después de un corte— trae el mismo id: úsalo para no procesarla dos veces. |
X-Datario-Firma | t=<segundos desde 1970>,v1=<hex>: HMAC-SHA256 con tu secreto sobre t, un punto y el cuerpo tal cual llegó, sin re-serializar. Rechaza lo que tenga más de 5 minutos: t es lo que impide repetir una entrega capturada. |
User-Agent | Datario-Webhook/1. |
Lo que trae el cuerpo
| Campo | Tipo | Qué es |
|---|---|---|
id | string | El id de la entrega, el mismo de la cabecera. |
tipo | string | novedades cuando se entregaron novedades; prueba para la prueba que mandas desde el panel. |
enviado_en | string | Cuándo se armó la entrega, en UTC y con offset. |
novedades | array | Las novedades de la tanda, con la MISMA forma que las de GET /v1/vigilancia/novedades. El webhook es delgado: si pagina_siguiente no es null, el resto se sigue por la API con ese cursor. |
total | integer | Cuántas novedades tiene la tanda, quepan o no en este cuerpo. |
pagina_siguiente | string | El cursor para seguir leyendo la tanda por la API; null si vino completa. |
Qué hace Datario con tu respuesta
- 2xx Entregada. No hace falta responder nada más que el código.
- 408, 425, 429, 5xx, o sin respuesta Se reintenta con esperas crecientes, hasta 7 intentos; si ninguno entra, la entrega se da por perdida y su detalle queda en el panel.
- Cualquier otro 4xx, o una redirección Se da por rechazada y no se reintenta.
- 3 perdidas o rechazadas seguidas El webhook se desactiva y te avisamos por correo; las novedades siguen en el panel y en la API. Se reactiva desde el panel.
Responde 2xx apenas guardes la entrega y procésala después: la espera cuenta como sin respuesta. Con X-Datario-Entrega descartas una repetida.
Una entrega, tal cual llega
La de prueba —la que mandas desde el panel—, firmada con el secreto de ejemplo whs_9kQ2pW7xLm4vRt8sNb3cYd6fHg1jZa5e y t=1788883200: sirve para probar tu verificador antes de registrar nada.
Content-Type: application/json
User-Agent: Datario-Webhook/1
X-Datario-Entrega: 3f9d1c2e-7a4b-4d8e-9c1f-5b6a7d8e9f01
X-Datario-Firma: t=1788883200,v1=11887e0a6084028885798b9189393a371adfcd4c29c2eda92b3592970c1b6d20
{
"id": "3f9d1c2e-7a4b-4d8e-9c1f-5b6a7d8e9f01",
"tipo": "prueba",
"enviado_en": "2026-09-08T16:00:00+00:00",
"novedades": [
{
"id": 0,
"rut": "61704000-K",
"rut_formateado": "61.704.000-K",
"razon_social": "CORP NACIONAL DEL COBRE DE CHILE",
"descripcion": "Entrega de prueba: así llega una novedad",
"publicado": null,
"aspecto": "prueba",
"tipo": "prueba",
"campos": null,
"antes": null,
"despues": null,
"lista": "prueba",
"etiqueta": "",
"entregada_en": null
}
],
"total": 1,
"pagina_siguiente": null
}
La comprobación
Antes de la primera entrega —y al menos cada 30 días si no hubo ninguna— Datario le hace un POST a tu URL con un desafío firmado, y tu servidor tiene que devolver un valor derivado del secreto compartido. Un webhook que no pasa la comprobación no recibe novedades: quedan en el panel y en GET /v1/vigilancia/novedades hasta que pase. A las 3 comprobaciones fallidas seguidas el webhook se desactiva y te avisamos por correo.
Lo que trae el desafío
| Campo | Tipo | Qué es |
|---|---|---|
id | uuid | El id de esta comprobación. Viaja también en X-Datario-Entrega. |
tipo | string | comprobacion. Es lo que distingue un desafío de una entrega de novedades: mismo método, misma URL y misma firma, distinto tipo. |
enviado_en | string | Cuándo se mandó, en ISO 8601 con offset. |
desafio | string | 32 caracteres hex. Es lo único que tienes que firmar para contestar. |
Lo que tiene que responder tu servidor
| Qué | Valor | Detalle |
|---|---|---|
Código | 200 | Cualquier 2xx sirve. Un 3xx cuenta como rechazo: no seguimos redirecciones. |
Cuerpo | json | Un objeto con una sola clave, comprobacion. |
comprobacion | string | El HMAC-SHA256 del desafio con tu secreto: 64 caracteres hex en minúscula. Es el mismo primitivo con que verificas la firma, sobre el desafío tal cual llegó. |
Plazo | 3 s | Contestar es un HMAC sobre 32 caracteres: no consultes tu base de datos para responder esto. |
Cuando no pasa
- No llegamos a tu servidor — No pudimos abrir la conexión con tu URL. No es que haya respondido mal: no respondió nada.
- Tu servidor tardó demasiado — Se conectó, pero no alcanzó a contestar en el plazo que esperamos.
- Tu servidor respondió con un error — La dirección existe y contesta, pero no con un 200.
- Tu servidor redirigió a otra dirección — Nos mandó a otra parte, y no seguimos redirecciones: una firma reenviada a otro servidor es exactamente lo que la firma existe para impedir.
- Respondió, pero sin la comprobación — Tu servidor aceptó el desafío, pero el cuerpo no traía el valor que le pedimos. Con una respuesta vacía no podemos distinguirte de cualquier cosa que conteste que sí.
- Lo que devolviste no calza con tu secreto — Nos devolviste un valor con la forma correcta, pero no el que sale de tu secreto. Casi siempre es que tu servidor tiene guardado otro.
Un desafío, tal cual llega
Firmado con el mismo secreto de ejemplo. La respuesta de abajo es la correcta para ESTE desafío: implementa tu eco, calcula, y compara — sin registrar nada.
Content-Type: application/json
User-Agent: Datario-Webhook/1
X-Datario-Entrega: 3f9d1c2e-7a4b-4d8e-9c1f-5b6a7d8e9f01
X-Datario-Firma: t=1788883200,v1=c768a7fd26d89c1d8b5be775b4ce5bef768748e97039e681b9b739700575828a
{
"id": "3f9d1c2e-7a4b-4d8e-9c1f-5b6a7d8e9f01",
"tipo": "comprobacion",
"enviado_en": "2026-09-08T16:00:00+00:00",
"desafio": "7c1f4a90b3e24d58a6c0d2f81e5b9a34"
}
{
"comprobacion": "1723981501a3edc285f274aeafa6f4cf6425257f664f3dbaa6bc83f55b2ec1b8"
}
Cómo verificar la firma y contestar el desafío
Las dos cosas que tu servidor hace, con el mismo secreto y el mismo HMAC: verificar lo que llega, y —cuando lo que llega es una comprobación y no una entrega— devolver el eco. El delta de la comprobación son cuatro líneas y ninguna importación nueva.
Python
import hashlib
import hmac
import os
import time
SECRETO = os.environ["DATARIO_WEBHOOK_SECRETO"]
def firma_valida(cabecera: str, cuerpo: bytes) -> bool:
"""`cabecera` es X-Datario-Firma tal cual; `cuerpo`, los
bytes crudos del POST, sin volver a serializar."""
partes = dict(
p.split("=", 1) for p in cabecera.split(",") if "=" in p
)
try:
t = int(partes.get("t", ""))
except ValueError:
return False
if abs(int(time.time()) - t) > 300:
return False
esperada = hmac.new(
SECRETO.encode(), f"{t}.".encode() + cuerpo, hashlib.sha256
).hexdigest()
return hmac.compare_digest(esperada, partes.get("v1", ""))
def respuesta_comprobacion(carga: dict) -> dict:
"""Lo ÚNICO que se contesta cuando `carga["tipo"]` es
"comprobacion": el mismo HMAC, sobre el desafío."""
desafio = carga["desafio"].encode()
eco = hmac.new(SECRETO.encode(), desafio, hashlib.sha256)
return {"comprobacion": eco.hexdigest()}
# En tu handler, ANTES de leer el JSON:
# if not firma_valida(request.headers["X-Datario-Firma"], cuerpo):
# return 401
# ...y con la carga ya leída:
# if carga["tipo"] == "comprobacion":
# return 200, respuesta_comprobacion(carga)
Node.js
import crypto from "node:crypto";
const SECRETO = process.env.DATARIO_WEBHOOK_SECRETO;
// `cabecera` es X-Datario-Firma tal cual; `cuerpo`, el Buffer crudo
// del POST (en Express: `express.raw({ type: "*/*" })`).
export function firmaValida(cabecera, cuerpo) {
const partes = Object.fromEntries(
cabecera.split(",").map((p) => p.split(/=(.*)/s).slice(0, 2))
);
const t = Number.parseInt(partes.t, 10);
const ahora = Math.floor(Date.now() / 1000);
if (!Number.isFinite(t)) return false;
if (Math.abs(ahora - t) > 300) return false;
const esperada = crypto
.createHmac("sha256", SECRETO)
.update(`${t}.`)
.update(cuerpo)
.digest("hex");
const v1 = partes.v1 ?? "";
return (
v1.length === esperada.length &&
crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(esperada))
);
}
// Lo ÚNICO que se contesta cuando `carga.tipo` es
// "comprobacion": el mismo HMAC, sobre el desafío.
export function respuestaComprobacion(carga) {
return {
"comprobacion": crypto
.createHmac("sha256", SECRETO)
.update(carga.desafio)
.digest("hex"),
};
}
PHP
<?php
$secreto = getenv("DATARIO_WEBHOOK_SECRETO");
// $cabecera es X-Datario-Firma tal cual; $cuerpo, el POST crudo
// (file_get_contents("php://input")), sin volver a serializar.
function firmaValida(string $cabecera, string $cuerpo,
string $secreto): bool {
$partes = [];
foreach (explode(",", $cabecera) as $par) {
[$k, $v] = array_pad(explode("=", $par, 2), 2, "");
$partes[$k] = $v;
}
$t = (int) ($partes["t"] ?? 0);
if (abs(time() - $t) > 300) {
return false;
}
$esperada = hash_hmac("sha256", "$t." . $cuerpo, $secreto);
return hash_equals($esperada, $partes["v1"] ?? "");
}
// Lo ÚNICO que se contesta cuando $carga["tipo"] es
// "comprobacion": el mismo HMAC, sobre el desafío.
function respuestaComprobacion(array $carga,
string $secreto): array {
return ["comprobacion" => hash_hmac(
"sha256", $carga["desafio"], $secreto)];
}
Probar en la consola Este producto por SOAP Este producto por GraphQL Este producto por MCP Qué es Vigilancia de RUT