Autenticación

Todas las llamadas a la API requieren el token de empresa (UUID). Puedes enviarlo de dos formas:

  • Header: X-Company-Token: tu-token-uuid
  • Query param: ?token=tu-token-uuid

El token lo encuentras en el portal, en el detalle de cada empresa. Si el token se ve comprometido, puedes regenerarlo desde tu cuenta.

GET /api/v1/ventas/{period}/

Obtiene el registro de ventas de un período, ya extraído previamente por el sistema.

Parámetros
NombreUbicaciónTipoDescripción
periodpathstringPeríodo en formato YYYYMM (ej. 202602)
formatquerystringFormato de respuesta: json (default) o csv
pagequeryintegerPágina a obtener (default 1)
page_sizequeryintegerRegistros por página (default 1000, mínimo 500, máximo 5000)
Ejemplos de uso
# Reemplaza TU_TOKEN por el token de tu empresa
curl -H "X-Company-Token: TU_TOKEN" \
     "https://apipyme.cl/api/v1/ventas/202602/"
import requests

url = "https://apipyme.cl/api/v1/ventas/202602/"
headers = {"X-Company-Token": "TU_TOKEN"}

response = requests.get(url, headers=headers)

if response.status_code == 200:
    data = response.json()["data"]
    print(f"Se obtuvieron {len(data)} registros")
elif response.status_code == 202:
    task_id = response.json()["task_id"]
    print(f"Extracción iniciada: {task_id}")
// Node.js / fetch
const response = await fetch(
  "https://apipyme.cl/api/v1/ventas/202602/",
  { headers: { "X-Company-Token": "TU_TOKEN" } }
);

if (response.status === 200) {
  const { data } = await response.json();
  console.log(`Se obtuvieron ${data.length} registros`);
} else if (response.status === 202) {
  const { task_id } = await response.json();
  console.log(`Extracción iniciada: ${task_id}`);
}
// PHP con cURL
$ch = curl_init("https://apipyme.cl/api/v1/ventas/202602/");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "X-Company-Token: TU_TOKEN"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$data = json_decode($response, true);

if ($httpCode === 200) {
    echo "Registros: " . count($data["data"]);
} elseif ($httpCode === 202) {
    echo "Extracción iniciada: " . $data["task_id"];
}
# pip install apipyme-sdk
from apipyme import ApiPyme

api = ApiPyme(
    token="TU_TOKEN",
    base_url="https://apipyme.cl/api/v1"
)

# Obtiene los datos; si no existen, espera la extracción
data = api.ventas("202602")
print(f"Se obtuvieron {len(data)} registros")
Respuesta exitosa 200
{
  "period": "202602",
  "rut": "76.543.210-K",
  "actualizado_en": "2026-03-08T10:32:00Z",
  "pagination": {
    "page": 1,
    "page_size": 1000,
    "total_paginas": 3,
    "total_registros": 2450,
    "tiene_siguiente": true
  },
  "data": [
    {
      "id": 1,
      "period": "202602",
      "doc_type": "33",
      "doc_number": "4521",
      "issue_date": "2026-02-05",
      "rut_receiver": "77.888.999-0",
      "receiver_name": "Comercial Acme SpA",
      "net_amount": 1500000,
      "tax_amount": 285000,
      "total_amount": 1785000,
      "exempt_amount": 0,
      "extracted_at": "2026-03-08T10:32:00Z"
    }
  ]
}

La gran mayoría de los períodos tiene menos de 1.000 documentos, por lo que pagination.tiene_siguiente viene en false y toda la data llega en una sola respuesta. Si el período supera page_size, sigue pidiendo ?page=2, ?page=3, etc. hasta que tiene_siguiente sea false — recorrer el resto de las páginas de un mismo período nunca descuenta cuota adicional.
actualizado_en indica cuándo se extrajo por última vez este período. La cuota diaria se descuenta una vez por cada valor distinto de actualizado_en que veas para este módulo y empresa — repetir la misma consulta antes de que ese valor cambie (el sistema extrae cada 2 horas, 8:00–20:00 hrs) es siempre gratis. El límite diario es por empresa, compartido entre todos los módulos contratados — consultar ventas y compras del mismo día descuenta del mismo cupo, no de cupos separados. La cuota de una empresa tampoco afecta a otra.

GET /api/v1/compras/{period}/

Obtiene el registro de compras de un período, ya extraído previamente por el sistema.

Parámetros
NombreUbicaciónTipoDescripción
periodpathstringPeríodo en formato YYYYMM
formatquerystringjson o csv
pagequeryintegerPágina a obtener (default 1)
page_sizequeryintegerRegistros por página (default 1000, mínimo 500, máximo 5000)
Ejemplos de uso
# Reemplaza TU_TOKEN por el token de tu empresa
curl -H "X-Company-Token: TU_TOKEN" \
     "https://apipyme.cl/api/v1/compras/202602/"
import requests

url = "https://apipyme.cl/api/v1/compras/202602/"
headers = {"X-Company-Token": "TU_TOKEN"}

response = requests.get(url, headers=headers)

if response.status_code == 200:
    data = response.json()["data"]
    print(f"Se obtuvieron {len(data)} registros")
elif response.status_code == 202:
    task_id = response.json()["task_id"]
    print(f"Extracción iniciada: {task_id}")
// Node.js / fetch
const response = await fetch(
  "https://apipyme.cl/api/v1/compras/202602/",
  { headers: { "X-Company-Token": "TU_TOKEN" } }
);

if (response.status === 200) {
  const { data } = await response.json();
  console.log(`Se obtuvieron ${data.length} registros`);
} else if (response.status === 202) {
  const { task_id } = await response.json();
  console.log(`Extracción iniciada: ${task_id}`);
}
// PHP con cURL
$ch = curl_init("https://apipyme.cl/api/v1/compras/202602/");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "X-Company-Token: TU_TOKEN"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$data = json_decode($response, true);

if ($httpCode === 200) {
    echo "Registros: " . count($data["data"]);
} elseif ($httpCode === 202) {
    echo "Extracción iniciada: " . $data["task_id"];
}
# pip install apipyme-sdk
from apipyme import ApiPyme

api = ApiPyme(
    token="TU_TOKEN",
    base_url="https://apipyme.cl/api/v1"
)

# Obtiene los datos; si no existen, espera la extracción
data = api.compras("202602")
print(f"Se obtuvieron {len(data)} registros")
Respuesta exitosa 200
{
  "period": "202602",
  "rut": "76.543.210-K",
  "actualizado_en": "2026-03-08T10:35:00Z",
  "pagination": {
    "page": 1,
    "page_size": 1000,
    "total_paginas": 1,
    "total_registros": 340,
    "tiene_siguiente": false
  },
  "data": [
    {
      "id": 1,
      "period": "202602",
      "doc_type": "33",
      "doc_number": "8901",
      "issue_date": "2026-02-10",
      "rut_issuer": "78.111.222-3",
      "issuer_name": "Distribuidora Norte Ltda.",
      "net_amount": 850000,
      "tax_amount": 161500,
      "total_amount": 1011500,
      "exempt_amount": 0,
      "extracted_at": "2026-03-08T10:35:00Z"
    }
  ]
}

Igual que en ventas: la cuota diaria se descuenta por versión de dato (actualizado_en), no por página, y el cupo es por empresa compartido con el resto de los módulos (no uno separado para compras). Ver detalle más arriba.

GET /api/v1/f29/{period}/

Obtiene los datos del Formulario 29 (IVA) de un período.

Parámetros
NombreUbicaciónTipoDescripción
periodpathstringPeríodo en formato YYYYMM
formatquerystringjson o csv
Ejemplos de uso
# Reemplaza TU_TOKEN por el token de tu empresa
curl -H "X-Company-Token: TU_TOKEN" \
     "https://apipyme.cl/api/v1/f29/202602/"
import requests

url = "https://apipyme.cl/api/v1/f29/202602/"
headers = {"X-Company-Token": "TU_TOKEN"}

response = requests.get(url, headers=headers)

if response.status_code == 200:
    data = response.json()["data"]
    print(f"Se obtuvieron {len(data)} registros")
elif response.status_code == 202:
    task_id = response.json()["task_id"]
    print(f"Extracción iniciada: {task_id}")
// Node.js / fetch
const response = await fetch(
  "https://apipyme.cl/api/v1/f29/202602/",
  { headers: { "X-Company-Token": "TU_TOKEN" } }
);

if (response.status === 200) {
  const { data } = await response.json();
  console.log(`Se obtuvieron ${data.length} registros`);
} else if (response.status === 202) {
  const { task_id } = await response.json();
  console.log(`Extracción iniciada: ${task_id}`);
}
// PHP con cURL
$ch = curl_init("https://apipyme.cl/api/v1/f29/202602/");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "X-Company-Token: TU_TOKEN"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$data = json_decode($response, true);

if ($httpCode === 200) {
    echo "Registros: " . count($data["data"]);
} elseif ($httpCode === 202) {
    echo "Extracción iniciada: " . $data["task_id"];
}
# pip install apipyme-sdk
from apipyme import ApiPyme

api = ApiPyme(
    token="TU_TOKEN",
    base_url="https://apipyme.cl/api/v1"
)

# Obtiene los datos; si no existen, espera la extracción
data = api.f29("202602")
print(f"Se obtuvieron {len(data)} registros")
Respuesta exitosa 200
{
  "period": "202602",
  "rut": "76.543.210-K",
  "pagination": {
    "page": 1,
    "page_size": 1000,
    "total_paginas": 1,
    "total_registros": 1,
    "tiene_siguiente": false
  },
  "data": [
    {
      "id": 1,
      "period": "202602",
      "folio": "123456789",
      "total_ventas_afectas": 12450000,
      "total_compras_afectas": 8230000,
      "iva_debito": 2365500,
      "iva_credito": 1563700,
      "iva_neto": 801800,
      "extracted_at": "2026-03-08T10:40:00Z"
    }
  ]
}

El F29 es un solo registro por período, así que siempre viene en una única página.

GET /api/v1/honorarios/{year}/

Obtiene las boletas de honorarios recibidas durante un año completo.

Parámetros
NombreUbicaciónTipoDescripción
yearpathstringAño en formato YYYY (ej. 2026)
formatquerystringjson o csv
pagequeryintegerPágina a obtener (default 1)
page_sizequeryintegerRegistros por página (default 1000, mínimo 500, máximo 5000)
Ejemplos de uso
# Reemplaza TU_TOKEN por el token de tu empresa
curl -H "X-Company-Token: TU_TOKEN" \
     "https://apipyme.cl/api/v1/honorarios/2026/"
import requests

url = "https://apipyme.cl/api/v1/honorarios/2026/"
headers = {"X-Company-Token": "TU_TOKEN"}

response = requests.get(url, headers=headers)

if response.status_code == 200:
    data = response.json()["data"]
    print(f"Se obtuvieron {len(data)} registros")
elif response.status_code == 202:
    task_id = response.json()["task_id"]
    print(f"Extracción iniciada: {task_id}")
// Node.js / fetch
const response = await fetch(
  "https://apipyme.cl/api/v1/honorarios/2026/",
  { headers: { "X-Company-Token": "TU_TOKEN" } }
);

if (response.status === 200) {
  const { data } = await response.json();
  console.log(`Se obtuvieron ${data.length} registros`);
} else if (response.status === 202) {
  const { task_id } = await response.json();
  console.log(`Extracción iniciada: ${task_id}`);
}
// PHP con cURL
$ch = curl_init("https://apipyme.cl/api/v1/honorarios/2026/");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "X-Company-Token: TU_TOKEN"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$data = json_decode($response, true);

if ($httpCode === 200) {
    echo "Registros: " . count($data["data"]);
} elseif ($httpCode === 202) {
    echo "Extracción iniciada: " . $data["task_id"];
}
# pip install apipyme-sdk
from apipyme import ApiPyme

api = ApiPyme(
    token="TU_TOKEN",
    base_url="https://apipyme.cl/api/v1"
)

# Obtiene los datos; si no existen, espera la extracción
data = api.honorarios("2026")
print(f"Se obtuvieron {len(data)} registros")
Respuesta exitosa 200
{
  "year": "2026",
  "rut": "76.543.210-K",
  "pagination": {
    "page": 1,
    "page_size": 1000,
    "total_paginas": 1,
    "total_registros": 48,
    "tiene_siguiente": false
  },
  "data": [
    {
      "id": 1,
      "year": "2026",
      "folio": "00012345",
      "issue_date": "2026-01-15",
      "rut_issuer": "12.345.678-9",
      "issuer_name": "Juan Pérez González",
      "gross_amount": 1000000,
      "retention": 125000,
      "net_amount": 875000,
      "extracted_at": "2026-03-08T10:45:00Z"
    }
  ]
}

Igual que en ventas: solo la primera página consume cuota diaria del módulo. Ver detalle de paginación más arriba.

GET /api/v1/resumen/{period}/ Extra: Resumen Mensual

Retorna un resumen consolidado de ventas y compras del período, con el cálculo de IVA neto. Las notas de crédito (tipo 60, 61) se restan del total y las notas de débito (tipo 56) se suman. Requiere que los datos de ventas y/o compras ya estén extraídos.

Parámetros
NombreUbicaciónTipoDescripción
periodpathstringPeríodo en formato YYYYMM (ej. 202602)
Ejemplos de uso
# Reemplaza TU_TOKEN por el token de tu empresa
curl -H "X-Company-Token: TU_TOKEN" \
     "https://apipyme.cl/api/v1/resumen/202602/"
import requests

url = "https://apipyme.cl/api/v1/resumen/202602/"
headers = {"X-Company-Token": "TU_TOKEN"}

response = requests.get(url, headers=headers)

if response.status_code == 200:
    data = response.json()["data"]
    print(f"Se obtuvieron {len(data)} registros")
elif response.status_code == 202:
    task_id = response.json()["task_id"]
    print(f"Extracción iniciada: {task_id}")
// Node.js / fetch
const response = await fetch(
  "https://apipyme.cl/api/v1/resumen/202602/",
  { headers: { "X-Company-Token": "TU_TOKEN" } }
);

if (response.status === 200) {
  const { data } = await response.json();
  console.log(`Se obtuvieron ${data.length} registros`);
} else if (response.status === 202) {
  const { task_id } = await response.json();
  console.log(`Extracción iniciada: ${task_id}`);
}
// PHP con cURL
$ch = curl_init("https://apipyme.cl/api/v1/resumen/202602/");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "X-Company-Token: TU_TOKEN"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$data = json_decode($response, true);

if ($httpCode === 200) {
    echo "Registros: " . count($data["data"]);
} elseif ($httpCode === 202) {
    echo "Extracción iniciada: " . $data["task_id"];
}
# pip install apipyme-sdk
from apipyme import ApiPyme

api = ApiPyme(
    token="TU_TOKEN",
    base_url="https://apipyme.cl/api/v1"
)

# Obtiene los datos; si no existen, espera la extracción
data = api.resumen("202602")
print(f"Se obtuvieron {len(data)} registros")
Respuesta exitosa 200
{
  "period": "202602",
  "rut": "76.543.210-K",
  "ventas": {
    "documentos": 45,
    "neto": 12450000,
    "iva": 2365500,
    "total": 14815500,
    "exento": 0,
    "notas_credito": {
      "cantidad": 3,
      "neto": 850000,
      "iva": 161500,
      "total": 1011500
    },
    "desglose_tipo_documento": [
      {"doc_type": "33", "cantidad": 38, "neto": 12800000, "iva": 2432000, "total": 15232000, "exento": 0},
      {"doc_type": "56", "cantidad": 4, "neto": 500000, "iva": 95000, "total": 595000, "exento": 0},
      {"doc_type": "61", "cantidad": 3, "neto": 850000, "iva": 161500, "total": 1011500, "exento": 0}
    ]
  },
  "compras": {
    "documentos": 22,
    "neto": 8230000,
    "iva": 1563700,
    "total": 9793700,
    "exento": 120000,
    "notas_credito": {
      "cantidad": 1,
      "neto": 200000,
      "iva": 38000,
      "total": 238000
    },
    "desglose_tipo_documento": [
      {"doc_type": "33", "cantidad": 20, "neto": 8380000, "iva": 1592200, "total": 9972200, "exento": 120000},
      {"doc_type": "34", "cantidad": 1, "neto": 50000, "iva": 9500, "total": 59500, "exento": 0},
      {"doc_type": "61", "cantidad": 1, "neto": 200000, "iva": 38000, "total": 238000, "exento": 0}
    ]
  },
  "balance": {
    "iva_debito": 2365500,
    "iva_credito": 1563700,
    "iva_neto": 801800,
    "iva_a_pagar": 801800,
    "remanente_credito": 0
  }
}
Sin datos 404
{
  "error": "No hay datos de ventas ni compras para el período 202602. Primero extrae los datos."
}
GET /api/v1/comparativa/?desde=YYYYMM&hasta=YYYYMM Extra: Comparativa de Períodos

Compara los resúmenes de ventas y compras entre dos o más períodos consecutivos. Muestra la variación porcentual de cada campo entre un mes y el anterior. Máximo 12 períodos por consulta.

Parámetros
NombreUbicaciónTipoDescripción
desdequerystringPeríodo inicial YYYYMM (ej. 202601)
hastaquerystringPeríodo final YYYYMM (ej. 202603)
Ejemplos de uso
# Reemplaza TU_TOKEN por el token de tu empresa
curl -H "X-Company-Token: TU_TOKEN" \
     "https://apipyme.cl/api/v1/comparativa/?desde=202601&hasta=202603"
import requests

url = "https://apipyme.cl/api/v1/comparativa/?desde=202601&hasta=202603"
headers = {"X-Company-Token": "TU_TOKEN"}

response = requests.get(url, headers=headers)

if response.status_code == 200:
    data = response.json()["data"]
    print(f"Se obtuvieron {len(data)} registros")
elif response.status_code == 202:
    task_id = response.json()["task_id"]
    print(f"Extracción iniciada: {task_id}")
// Node.js / fetch
const response = await fetch(
  "https://apipyme.cl/api/v1/comparativa/?desde=202601&hasta=202603",
  { headers: { "X-Company-Token": "TU_TOKEN" } }
);

if (response.status === 200) {
  const { data } = await response.json();
  console.log(`Se obtuvieron ${data.length} registros`);
} else if (response.status === 202) {
  const { task_id } = await response.json();
  console.log(`Extracción iniciada: ${task_id}`);
}
// PHP con cURL
$ch = curl_init("https://apipyme.cl/api/v1/comparativa/?desde=202601&hasta=202603");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "X-Company-Token: TU_TOKEN"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$data = json_decode($response, true);

if ($httpCode === 200) {
    echo "Registros: " . count($data["data"]);
} elseif ($httpCode === 202) {
    echo "Extracción iniciada: " . $data["task_id"];
}
# pip install apipyme-sdk
from apipyme import ApiPyme

api = ApiPyme(
    token="TU_TOKEN",
    base_url="https://apipyme.cl/api/v1"
)

# Obtiene los datos; si no existen, espera la extracción
data = api.comparativa("")
print(f"Se obtuvieron {len(data)} registros")
Respuesta exitosa 200 (simplificada)
{
  "rut": "76.543.210-K",
  "desde": "202601",
  "hasta": "202603",
  "periodos": ["202601", "202602", "202603"],
  "resumenes": {
    "202601": {"period": "202601", "ventas": {...}, "compras": {...}, "balance": {...}},
    "202602": {"period": "202602", "ventas": {...}, "compras": {...}, "balance": {...}},
    "202603": {"period": "202603", "ventas": {...}, "compras": {...}, "balance": {...}}
  },
  "comparaciones": [
    {
      "periodo_actual": "202602",
      "periodo_anterior": "202601",
      "ventas": {
        "total": {"actual": 14815500, "anterior": 12500000, "diferencia": 2315500, "variacion_pct": 18.52},
        "neto":  {"actual": 12450000, "anterior": 10504202, "diferencia": 1945798, "variacion_pct": 18.52},
        "iva":   {"actual": 2365500,  "anterior": 1995798,  "diferencia": 369702,  "variacion_pct": 18.52},
        "documentos": {"actual": 45, "anterior": 38, "diferencia": 7, "variacion_pct": 18.42},
        "exento": {"actual": 0, "anterior": 0, "diferencia": 0, "variacion_pct": null}
      },
      "compras": {
        "total": {"actual": 9793700, "anterior": 8100000, "diferencia": 1693700, "variacion_pct": 20.91},
        ...
      },
      "balance_iva": {
        "iva_neto_actual": 801800,
        "iva_neto_anterior": 650000,
        "diferencia": 151800,
        "variacion_pct": 23.35
      }
    },
    {
      "periodo_actual": "202603",
      "periodo_anterior": "202602",
      ...
    }
  ]
}
Extracciones automáticas
Los datos se actualizan automáticamente. El sistema extrae información del SII cada 2 horas entre las 8:00 y las 20:00 (hora Santiago), sin que necesites hacer ninguna solicitud. Al consultar un endpoint de datos (ventas, compras, etc.) obtienes siempre la última información disponible en la base de datos.
¿Qué períodos se extraen?
  • Mes en curso: se extrae en todos los ciclos (cada 2 horas).
  • Mes anterior (días 1–13): se extrae una vez al día durante los primeros 13 días del mes, para capturar documentos de cierre que el SII publica con retraso.
  • Año completo: al activar una suscripción de pago por primera vez, se encola automáticamente la extracción de todos los meses del año para tus empresas. Los datos irán apareciendo en las horas siguientes.
¿Qué hago si no tengo datos de un período anterior?

Contacta a soporte indicando el período (YYYYMM) y el módulo. El equipo puede ejecutar una extracción histórica manualmente. Los datos del año en curso ya se extraen automáticamente al activar tu cuenta de pago.

GET /api/v1/extracciones/{task_id}/

Consulta el estado de una extracción por su task_id. El task_id se incluye en el payload del webhook cuando una extracción termina. Útil para hacer polling hasta que status sea SUCCESS o FAILED.

Parámetros
NombreUbicaciónTipoDescripción
task_idpathstringID de la tarea (UUID). Se recibe en el campo task_id del webhook.
Ejemplos de uso
# Reemplaza TU_TOKEN por el token de tu empresa
curl -H "X-Company-Token: TU_TOKEN" \
     "https://apipyme.cl/api/v1/extracciones/a1b2c3d4-e5f6-7890-abcd-ef1234567890/"
import requests

url = "https://apipyme.cl/api/v1/extracciones/a1b2c3d4-e5f6-7890-abcd-ef1234567890/"
headers = {"X-Company-Token": "TU_TOKEN"}

response = requests.get(url, headers=headers)

if response.status_code == 200:
    data = response.json()["data"]
    print(f"Se obtuvieron {len(data)} registros")
elif response.status_code == 202:
    task_id = response.json()["task_id"]
    print(f"Extracción iniciada: {task_id}")
// Node.js / fetch
const response = await fetch(
  "https://apipyme.cl/api/v1/extracciones/a1b2c3d4-e5f6-7890-abcd-ef1234567890/",
  { headers: { "X-Company-Token": "TU_TOKEN" } }
);

if (response.status === 200) {
  const { data } = await response.json();
  console.log(`Se obtuvieron ${data.length} registros`);
} else if (response.status === 202) {
  const { task_id } = await response.json();
  console.log(`Extracción iniciada: ${task_id}`);
}
// PHP con cURL
$ch = curl_init("https://apipyme.cl/api/v1/extracciones/a1b2c3d4-e5f6-7890-abcd-ef1234567890/");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "X-Company-Token: TU_TOKEN"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$data = json_decode($response, true);

if ($httpCode === 200) {
    echo "Registros: " . count($data["data"]);
} elseif ($httpCode === 202) {
    echo "Extracción iniciada: " . $data["task_id"];
}
# pip install apipyme-sdk
from apipyme import ApiPyme

api = ApiPyme(
    token="TU_TOKEN",
    base_url="https://apipyme.cl/api/v1"
)

# Obtiene los datos; si no existen, espera la extracción
data = api.estado("")
print(f"Se obtuvieron {len(data)} registros")
Estados posibles
EstadoDescripción
PENDINGEn cola, esperando ser procesada
RUNNINGExtracción en curso (conectando al SII)
SUCCESSCompletada. Los datos ya están disponibles en el endpoint correspondiente
FAILEDFalló. Revisa error_message para más detalle
GET /api/v1/empresa/

Retorna la información de la empresa asociada al token utilizado. Útil para verificar que el token es correcto.

Ejemplos de uso
# Reemplaza TU_TOKEN por el token de tu empresa
curl -H "X-Company-Token: TU_TOKEN" \
     "https://apipyme.cl/api/v1/empresa/"
import requests

url = "https://apipyme.cl/api/v1/empresa/"
headers = {"X-Company-Token": "TU_TOKEN"}

response = requests.get(url, headers=headers)

if response.status_code == 200:
    data = response.json()["data"]
    print(f"Se obtuvieron {len(data)} registros")
elif response.status_code == 202:
    task_id = response.json()["task_id"]
    print(f"Extracción iniciada: {task_id}")
// Node.js / fetch
const response = await fetch(
  "https://apipyme.cl/api/v1/empresa/",
  { headers: { "X-Company-Token": "TU_TOKEN" } }
);

if (response.status === 200) {
  const { data } = await response.json();
  console.log(`Se obtuvieron ${data.length} registros`);
} else if (response.status === 202) {
  const { task_id } = await response.json();
  console.log(`Extracción iniciada: ${task_id}`);
}
// PHP con cURL
$ch = curl_init("https://apipyme.cl/api/v1/empresa/");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "X-Company-Token: TU_TOKEN"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$data = json_decode($response, true);

if ($httpCode === 200) {
    echo "Registros: " . count($data["data"]);
} elseif ($httpCode === 202) {
    echo "Extracción iniciada: " . $data["task_id"];
}
# pip install apipyme-sdk
from apipyme import ApiPyme

api = ApiPyme(
    token="TU_TOKEN",
    base_url="https://apipyme.cl/api/v1"
)

# Obtiene los datos; si no existen, espera la extracción
data = api.empresa("")
print(f"Se obtuvieron {len(data)} registros")
Respuesta 200
{
  "rut": "76.543.210-K",
  "business_name": "Comercial Ejemplo SpA",
  "client_email": "contacto@ejemplo.cl",
  "client_company": "Integrador Contable Ltda.",
  "is_active": true
}
GET /api/v1/indicadores/ Sin licencia requerida

Retorna indicadores financieros extraídos desde la API oficial de la CMF. Disponible para todas las cuentas — trial y de pago — con token de empresa válido. Los datos se actualizan automáticamente cada mañana a las 7:30 AM.

La respuesta combina dos granularidades:

  • Diarios (UF, dólar observado, euro): valor propio de cada día.
  • Mensuales (UTM, IPC): mismo valor para todos los días del mes. El IPC puede ser null durante los primeros días del mes hasta que la CMF lo publique (~día 8).

Para consultar una fecha histórica usa /api/v1/indicadores/{fecha}/ con formato YYYYMMDD. Si el dato no está en caché lo obtiene de la CMF en tiempo real.

Parámetros
NombreUbicaciónTipoDescripción
fechapath (opcional)stringFecha en formato YYYYMMDD (ej. 20260617). Sin fecha retorna los del día actual.
Ejemplos de uso
# Reemplaza TU_TOKEN por el token de tu empresa
curl -H "X-Company-Token: TU_TOKEN" \
     "https://apipyme.cl/api/v1/indicadores/"
import requests

url = "https://apipyme.cl/api/v1/indicadores/"
headers = {"X-Company-Token": "TU_TOKEN"}

response = requests.get(url, headers=headers)

if response.status_code == 200:
    data = response.json()["data"]
    print(f"Se obtuvieron {len(data)} registros")
elif response.status_code == 202:
    task_id = response.json()["task_id"]
    print(f"Extracción iniciada: {task_id}")
// Node.js / fetch
const response = await fetch(
  "https://apipyme.cl/api/v1/indicadores/",
  { headers: { "X-Company-Token": "TU_TOKEN" } }
);

if (response.status === 200) {
  const { data } = await response.json();
  console.log(`Se obtuvieron ${data.length} registros`);
} else if (response.status === 202) {
  const { task_id } = await response.json();
  console.log(`Extracción iniciada: ${task_id}`);
}
// PHP con cURL
$ch = curl_init("https://apipyme.cl/api/v1/indicadores/");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "X-Company-Token: TU_TOKEN"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$data = json_decode($response, true);

if ($httpCode === 200) {
    echo "Registros: " . count($data["data"]);
} elseif ($httpCode === 202) {
    echo "Extracción iniciada: " . $data["task_id"];
}
# pip install apipyme-sdk
from apipyme import ApiPyme

api = ApiPyme(
    token="TU_TOKEN",
    base_url="https://apipyme.cl/api/v1"
)

# Obtiene los datos; si no existen, espera la extracción
data = api.indicadores("")
print(f"Se obtuvieron {len(data)} registros")
Respuesta exitosa 200
{
  "rut": "76.543.210-K",
  "date": "2026-06-17",
  "data": {
    "uf":    { "nombre": "Unidad de Fomento",               "unidad_medida": "Pesos",      "fecha": "2026-06-17", "valor": 38982.21 },
    "dolar": { "nombre": "Dólar Observado",                 "unidad_medida": "Pesos",      "fecha": "2026-06-17", "valor": 948.47 },
    "euro":  { "nombre": "Euro",                            "unidad_medida": "Pesos",      "fecha": "2026-06-17", "valor": 1073.12 },
    "utm":   { "nombre": "Unidad Tributaria Mensual",       "unidad_medida": "Pesos",      "fecha": "2026-06-01", "valor": 67294 },
    "ipc":   { "nombre": "Índice de Precios al Consumidor", "unidad_medida": "Porcentaje", "fecha": "2026-06-01", "valor": 0.4 }
  },
  "extracted_at": "2026-06-17T07:30:12.345678Z"
}
Notas:
  • El dólar y el euro son null los fines de semana y feriados (la CMF no publica tipo de cambio esos días). La UF y la UTM siempre tienen valor.
  • El IPC puede ser null durante los primeros días del mes hasta que la CMF lo publique (~día 8). Observa el campo "fecha" de cada indicador: los mensuales siempre muestran el día 1 del mes.
Webhooks

Cuando una extracción termina, ApiPyme envía un POST a la URL de webhook que configures en Configuración Webhook (en tu cuenta del portal). Esto te permite recibir notificaciones en tu sistema sin necesidad de hacer polling.

Headers enviados
HeaderValorDescripción
Content-Type application/json Siempre JSON
X-Webhook-Secret Tu secret configurado Solo si configuraste un secret. Úsalo para validar que la notificación viene de ApiPyme.
Payload
{
  "event": "extraction_complete",
  "module": "ventas",
  "rut": "76.543.210-K",
  "period": "202604",
  "status": "SUCCESS",
  "rows": 142,
  "task_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
Campos
CampoTipoDescripción
eventstringTipo de evento. Actualmente siempre extraction_complete.
modulestringventas, compras, f29, honorarios o previred
rutstringRUT de la empresa
periodstringPeríodo en formato YYYYMM o YYYY
statusstringSUCCESS si la extracción fue exitosa, FAILED si falló
rowsint/nullCantidad de registros extraídos. null si falló.
task_idstringID de la tarea. Puedes usarlo para consultar el estado vía GET /api/v1/extracciones/{task_id}/
Validación del secret

Si configuraste un webhook_secret, valida el header en tu endpoint:

# Python (Flask/Django)
secret = request.headers.get('X-Webhook-Secret', '')
if secret != 'tu-secret-configurado':
    return Response(status=401)

# Node.js (Express)
const secret = req.headers['x-webhook-secret'];
if (secret !== 'tu-secret-configurado') {
    return res.sendStatus(401);
}
Tu endpoint debe responder con 2xx en menos de 10 segundos. Si tienes el feature Webhook con reintentos, se reintentará hasta 5 veces con backoff exponencial (1, 2, 4, 8 minutos).
Códigos de error
CódigoSignificadoEjemplo
401 Token no enviado o inválido {"detail": "Token inválido o empresa inactiva."}
403 Sin licencia activa para el módulo {"error": "No tienes licencia activa para el módulo \"ventas\"."}
429 Límite diario de requests alcanzado {"error": "Límite diario de 5 requests alcanzado para esta empresa (compartido entre todos los módulos)."}
404 Recurso no encontrado {"error": "Tarea no encontrada."}
400 Parámetros inválidos o faltantes {"error": "Se requieren los campos \"module\" y \"period\"."}
Formatos de respuesta
JSON (por defecto)

No requiere parámetro adicional. El header Content-Type será application/json.

GET /api/v1/ventas/202602/
CSV

Agrega ?format=csv. El archivo incluye BOM para compatibilidad con Excel y usa ; como delimitador.

GET /api/v1/ventas/202602/?format=csv