curl --request GET \
--url https://api.tupana.ai/v1/credentials/enrollments/{enrollment_id} \
--header 'Authorization: <api-key>'import requests
url = "https://api.tupana.ai/v1/credentials/enrollments/{enrollment_id}"
headers = {"Authorization": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: '<api-key>'}};
fetch('https://api.tupana.ai/v1/credentials/enrollments/{enrollment_id}', 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/v1/credentials/enrollments/{enrollment_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: <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.tupana.ai/v1/credentials/enrollments/{enrollment_id}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "<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.tupana.ai/v1/credentials/enrollments/{enrollment_id}")
.header("Authorization", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tupana.ai/v1/credentials/enrollments/{enrollment_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"enrollment_id": "cenr_3940730445066399260",
"status": "valid",
"user_rut": "12345678-9",
"error": null,
"credential": {
"id": "cred_3940730445066399260",
"user": "12345678-9",
"status": "VALID"
},
"ws_channel": "cred-validation-129816",
"created_at": "2026-09-17T11:20:20.429990-03:00",
"finished_at": "2026-09-17T11:20:34.493000-03:00"
}{
"error": "VALIDATION_ERROR",
"message": "<string>"
}{
"error": "VALIDATION_ERROR",
"message": "<string>"
}Estado del Enrolamiento
Devuelve el estado del enrolamiento iniciado con POST /credentials. Se consulta hasta que status deja de ser pending: el login contra el SII demora del orden de 15 segundos, así que basta con consultar cada 2-3 segundos.
curl --request GET \
--url https://api.tupana.ai/v1/credentials/enrollments/{enrollment_id} \
--header 'Authorization: <api-key>'import requests
url = "https://api.tupana.ai/v1/credentials/enrollments/{enrollment_id}"
headers = {"Authorization": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: '<api-key>'}};
fetch('https://api.tupana.ai/v1/credentials/enrollments/{enrollment_id}', 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/v1/credentials/enrollments/{enrollment_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: <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.tupana.ai/v1/credentials/enrollments/{enrollment_id}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "<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.tupana.ai/v1/credentials/enrollments/{enrollment_id}")
.header("Authorization", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tupana.ai/v1/credentials/enrollments/{enrollment_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"enrollment_id": "cenr_3940730445066399260",
"status": "valid",
"user_rut": "12345678-9",
"error": null,
"credential": {
"id": "cred_3940730445066399260",
"user": "12345678-9",
"status": "VALID"
},
"ws_channel": "cred-validation-129816",
"created_at": "2026-09-17T11:20:20.429990-03:00",
"finished_at": "2026-09-17T11:20:34.493000-03:00"
}{
"error": "VALIDATION_ERROR",
"message": "<string>"
}{
"error": "VALIDATION_ERROR",
"message": "<string>"
}Que hace
- Devuelve el estado del enrolamiento iniciado con
POST /credentials - Entrega la credencial cuando el SII ya validó la clave
- Distingue una clave rechazada por el SII de una falla temporal reintentable
Por que existe
El login contra el SII se hace con un navegador real, fuera del request HTTP. Por esoPOST /credentials no puede devolver la credencial: responde 202 con
un enrollment_id y este endpoint entrega el resultado cuando está listo.
Estados
status | Significado | Que hacer |
|---|---|---|
pending | El login contra el SII sigue en curso | Volver a consultar en 2-3 segundos |
valid | La credencial quedó enrolada | Leer credential en la respuesta |
invalid | El SII rechazó la clave | Mostrar error al usuario y pedir la clave de nuevo |
error | No se pudo preguntarle al SII (falla temporal) | Reintentar el enrolamiento más tarde; la clave NO fue rechazada |
Cuanto tarda
El login demora del orden de 15 segundos. Consultar cada 2-3 segundos es suficiente; no es necesario consultar más seguido.Ejemplo
curl https://api.tupana.ai/v1/credentials/enrollments/cenr_3940730445066399260/ \
-H "Authorization: Api-Key TU_API_KEY"
{
"enrollment_id": "cenr_3940730445066399260",
"status": "valid",
"user_rut": "12345678-9",
"error": null,
"credential": {
"id": "cred_3940730445066399260",
"user": "12345678-9",
"status": "VALID"
},
"created_at": "2026-09-17T11:20:20.429990-03:00",
"finished_at": "2026-09-17T11:20:34.493000-03:00"
}
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)
Path Parameters
Identificador devuelto por POST /credentials
Response
Estado del enrolamiento
Identificador del enrolamiento
"cenr_3940730445066399260"
pending: el login sigue en curso. valid: la credencial quedó enrolada. invalid: el SII rechazó la clave. error: no se pudo preguntarle al SII (reintentable).
pending, valid, invalid, error "pending"
RUT de la credencial que se está enrolando
"12345678-9"
Mensaje del SII cuando status es invalid o error
null
La credencial creada; sólo viene cuando status es valid
Canal WebSocket con el avance en vivo (lo usa el frontend)
"cred-validation-129816"
