curl --request GET \
--url https://api.pruff.com/api/clients/datahub/{identifier}/f29 \
--header 'x-api-key: <api-key>'import requests
url = "https://api.pruff.com/api/clients/datahub/{identifier}/f29"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://api.pruff.com/api/clients/datahub/{identifier}/f29', 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.pruff.com/api/clients/datahub/{identifier}/f29",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.pruff.com/api/clients/datahub/{identifier}/f29"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.pruff.com/api/clients/datahub/{identifier}/f29")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pruff.com/api/clients/datahub/{identifier}/f29")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"main": {
"142": [
{
"year": "2025",
"JAN": 1200000,
"FEB": 950000,
"MAR": 1100000
},
{
"year": "2026",
"JAN": 1300000,
"FEB": 1000000,
"MAR": 1250000
}
],
"538": [
{
"year": "2025",
"JAN": 4200000,
"FEB": 3900000,
"MAR": 4500000
},
{
"year": "2026",
"JAN": 4600000,
"FEB": 4100000,
"MAR": 4800000
}
],
"total": [
{
"year": "2025",
"JAN": 5508000,
"FEB": 4947000,
"MAR": 5712000
},
{
"year": "2026",
"JAN": 5900000,
"FEB": 5100000,
"MAR": 6050000
}
],
"totalIVA": [
{
"year": "2025",
"JAN": 6554520,
"FEB": 5886930,
"MAR": 6797280
},
{
"year": "2026",
"JAN": 7021000,
"FEB": 6069000,
"MAR": 7199500
}
]
},
"accumulative": {
"142": [
{
"year": "2025",
"JAN": 1200000,
"FEB": 2150000,
"MAR": 3250000
},
{
"year": "2026",
"JAN": 1300000,
"FEB": 2300000,
"MAR": 3550000
}
],
"538": [
{
"year": "2025",
"JAN": 4200000,
"FEB": 8100000,
"MAR": 12600000
},
{
"year": "2026",
"JAN": 4600000,
"FEB": 8700000,
"MAR": 13500000
}
],
"total": [
{
"year": "2025",
"JAN": 5508000,
"FEB": 10455000,
"MAR": 16167000
},
{
"year": "2026",
"JAN": 5900000,
"FEB": 11000000,
"MAR": 17050000
}
],
"totalIVA": [
{
"year": "2025",
"JAN": 6554520,
"FEB": 12441450,
"MAR": 19238730
},
{
"year": "2026",
"JAN": 7021000,
"FEB": 13090000,
"MAR": 20289500
}
]
},
"variation": {
"142": [
{
"year": "2025/2026",
"JAN": "8.33%",
"FEB": "6.98%",
"MAR": "9.23%"
}
],
"538": [
{
"year": "2025/2026",
"JAN": "9.52%",
"FEB": "7.41%",
"MAR": "7.14%"
}
],
"total": [
{
"year": "2025/2026",
"JAN": "7.12%",
"FEB": "5.21%",
"MAR": "5.46%"
}
],
"totalIVA": [
{
"year": "2025/2026",
"JAN": "7.12%",
"FEB": "5.21%",
"MAR": "5.46%"
}
]
}
}{
"message": "Unauthorized: Invalid API Key"
}{
"message": "Business not found"
}{
"message": "Rate limit exceeded: 501 requests in the current 60s window, limit is 500. Retry in 12s.",
"displayMessage": "Superaste el límite de 500 solicitudes cada 60 segundos. Vuelve a intentarlo en 12 segundos.",
"data": {
"code": "RATE_LIMIT_EXCEEDED",
"scope": "All API keys of your company share this budget.",
"limit": 500,
"used": 501,
"windowSeconds": 60,
"retryAfterSeconds": 12,
"resetAt": "2026-11-04T15:00:12.000Z",
"hint": "Wait until resetAt (or honor the Retry-After header) before retrying. Avoid repeating identical requests: reuse responses you already fetched, use filters and larger pageSize values instead of one request per item, and cap your client concurrency."
}
}{
"message": "Internal server error"
}{
"message": "request_timeout",
"displayMessage": "La solicitud excedió el tiempo máximo permitido"
}Obtener F29
Devuelve el Formulario 29 (declaración mensual de IVA) del cliente, con los 24 meses que terminan en el último período declarado que Pruff tiene. La respuesta tiene tres bloques con la misma estructura: main (valores mensuales), accumulative (acumulado año a la fecha) y variation (variación del acumulado entre años consecutivos). Cada bloque agrupa los datos por código del F29 (142, 538 y 020) y por dos totales calculados, total y totalIVA. Todos los montos están en pesos chilenos (CLP). Dentro de la ventana de 24 meses, los meses sin declaración se entregan con valor 0. total y totalIVA se reexpresan con la UF de cada mes: si falta el valor de la UF de un mes, ese mes llega null en main, suma 0 en accumulative (que sigue siendo un número, sin NaN) y variation nunca trae NaN. Las filas de cada serie van ordenadas por año, del más antiguo al más reciente. Si el cliente existe pero Pruff no tiene F29 para él, responde 200 con solo total y totalIVA vacíos en cada bloque. Si el RUT está vinculado a tu empresa, la respuesta usa la información tributaria obtenida por Pruff; si no lo está, usa las carpetas tributarias cargadas manualmente. Es un endpoint de solo lectura: no gatilla nuevas extracciones. Los años y meses del ejemplo se recortaron para abreviar.
curl --request GET \
--url https://api.pruff.com/api/clients/datahub/{identifier}/f29 \
--header 'x-api-key: <api-key>'import requests
url = "https://api.pruff.com/api/clients/datahub/{identifier}/f29"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://api.pruff.com/api/clients/datahub/{identifier}/f29', 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.pruff.com/api/clients/datahub/{identifier}/f29",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.pruff.com/api/clients/datahub/{identifier}/f29"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.pruff.com/api/clients/datahub/{identifier}/f29")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pruff.com/api/clients/datahub/{identifier}/f29")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"main": {
"142": [
{
"year": "2025",
"JAN": 1200000,
"FEB": 950000,
"MAR": 1100000
},
{
"year": "2026",
"JAN": 1300000,
"FEB": 1000000,
"MAR": 1250000
}
],
"538": [
{
"year": "2025",
"JAN": 4200000,
"FEB": 3900000,
"MAR": 4500000
},
{
"year": "2026",
"JAN": 4600000,
"FEB": 4100000,
"MAR": 4800000
}
],
"total": [
{
"year": "2025",
"JAN": 5508000,
"FEB": 4947000,
"MAR": 5712000
},
{
"year": "2026",
"JAN": 5900000,
"FEB": 5100000,
"MAR": 6050000
}
],
"totalIVA": [
{
"year": "2025",
"JAN": 6554520,
"FEB": 5886930,
"MAR": 6797280
},
{
"year": "2026",
"JAN": 7021000,
"FEB": 6069000,
"MAR": 7199500
}
]
},
"accumulative": {
"142": [
{
"year": "2025",
"JAN": 1200000,
"FEB": 2150000,
"MAR": 3250000
},
{
"year": "2026",
"JAN": 1300000,
"FEB": 2300000,
"MAR": 3550000
}
],
"538": [
{
"year": "2025",
"JAN": 4200000,
"FEB": 8100000,
"MAR": 12600000
},
{
"year": "2026",
"JAN": 4600000,
"FEB": 8700000,
"MAR": 13500000
}
],
"total": [
{
"year": "2025",
"JAN": 5508000,
"FEB": 10455000,
"MAR": 16167000
},
{
"year": "2026",
"JAN": 5900000,
"FEB": 11000000,
"MAR": 17050000
}
],
"totalIVA": [
{
"year": "2025",
"JAN": 6554520,
"FEB": 12441450,
"MAR": 19238730
},
{
"year": "2026",
"JAN": 7021000,
"FEB": 13090000,
"MAR": 20289500
}
]
},
"variation": {
"142": [
{
"year": "2025/2026",
"JAN": "8.33%",
"FEB": "6.98%",
"MAR": "9.23%"
}
],
"538": [
{
"year": "2025/2026",
"JAN": "9.52%",
"FEB": "7.41%",
"MAR": "7.14%"
}
],
"total": [
{
"year": "2025/2026",
"JAN": "7.12%",
"FEB": "5.21%",
"MAR": "5.46%"
}
],
"totalIVA": [
{
"year": "2025/2026",
"JAN": "7.12%",
"FEB": "5.21%",
"MAR": "5.46%"
}
]
}
}{
"message": "Unauthorized: Invalid API Key"
}{
"message": "Business not found"
}{
"message": "Rate limit exceeded: 501 requests in the current 60s window, limit is 500. Retry in 12s.",
"displayMessage": "Superaste el límite de 500 solicitudes cada 60 segundos. Vuelve a intentarlo en 12 segundos.",
"data": {
"code": "RATE_LIMIT_EXCEEDED",
"scope": "All API keys of your company share this budget.",
"limit": 500,
"used": 501,
"windowSeconds": 60,
"retryAfterSeconds": 12,
"resetAt": "2026-11-04T15:00:12.000Z",
"hint": "Wait until resetAt (or honor the Retry-After header) before retrying. Avoid repeating identical requests: reuse responses you already fetched, use filters and larger pageSize values instead of one request per item, and cap your client concurrency."
}
}{
"message": "Internal server error"
}{
"message": "request_timeout",
"displayMessage": "La solicitud excedió el tiempo máximo permitido"
}Parámetros de ruta
Respuesta
F29 del cliente.