Empezar a consultar
Cuatro formas de hacer la primera consulta. Las cuatro hacen lo mismo: piden una ficha de RUC, distinguen «no existe» de «no se pudo preguntar» y leen la procedencia del dato.
🔒 El token no va al navegador. Es la primera sorpresa de toda migración:
quien hoy consulta con el token en el front —una variable VITE_… o escrito en
una plantilla— está publicando una credencial. Con la de NexoID expondría su cuota,
su identidad y su auditoría, y cualquiera podría gastar por él.
La integración correcta es un proxy en tu propio backend: tu página llama a tu servidor, y tu servidor llama aquí con el token. Si ese proxy lo consume una página sin sesión, ponle límite por IP.
Antes de la primera llamada
| URL base | https://nexoid.victorllerena.com/id/v1 |
|---|---|
| Autenticación | Authorization: Bearer nxid_live_…, siempre desde tu servidor |
| Scope del ejemplo | ruc.read |
| Versión | 1.29.1 — los cambios aditivos no la suben (§15.7) |
🔒 Un RUC que empieza en 10, 15 o 17 es una
persona natural, y su nombre es identidad: esa consulta exige dni.read
y finalidad declarada aunque la ruta sea /ruc. Con solo ruc.read
recibes un 403, y no es un error de configuración: es la regla.
curl
consulta.sh
# El token sale del entorno: escrito en el guion acaba en el historial y en el repositorio.
curl -s -H "Authorization: Bearer $NEXOID_TOKEN" \
-H "Accept: application/json" \
"https://nexoid.victorllerena.com/id/v1/ruc/20131312955" | jq '.data.nombre, .meta.fecha_dato'
PHP
NexoId.php
<?php
// Laravel. 🔒 En el SERVIDOR: el token no baja al navegador.
use Illuminate\Support\Facades\Http;
$respuesta = Http::withToken(config('services.nexoid.token'))
->acceptJson()
->timeout(5)
->get('https://nexoid.victorllerena.com/id/v1/ruc/20131312955');
if ($respuesta->status() === 404) {
// No está en el padrón. `meta.degradado` distingue «no existe» de
// «no se pudo preguntar»: no son lo mismo y no se tratan igual.
$degradado = (bool) $respuesta->json('meta.degradado');
return $degradado ? null : 'no existe';
}
if ($respuesta->failed()) {
// El `codigo` es estable; el `mensaje` puede cambiar. Programa contra el código.
report(new RuntimeException((string) $respuesta->json('error.codigo')));
}
$nombre = $respuesta->json('data.nombre');
JavaScript / TypeScript
nexoid.ts
// Node, Next.js o cualquier backend. 🔒 Nunca desde el navegador:
// el token expondría tu cuota, tu identidad y tu auditoría.
const respuesta = await fetch('https://nexoid.victorllerena.com/id/v1/ruc/20131312955', {
headers: {
Authorization: `Bearer ${process.env.NEXOID_TOKEN}`,
Accept: 'application/json',
},
});
if (respuesta.status === 404) {
const { meta } = await respuesta.json();
// `degradado: true` = no se pudo preguntar. No lo guardes como «no existe».
return meta.degradado ? null : 'no existe';
}
if (!respuesta.ok) {
const { error } = await respuesta.json();
throw new Error(error.codigo); // el código es estable; el mensaje, no
}
const { data, meta } = await respuesta.json();
console.log(data.nombre, meta.fecha_dato, meta.origen);
Python
nexoid.py
import os
import requests # 🔒 En el servidor. El token no viaja al cliente.
respuesta = requests.get(
"https://nexoid.victorllerena.com/id/v1/ruc/20131312955",
headers={"Authorization": f"Bearer {os.environ['NEXOID_TOKEN']}", "Accept": "application/json"},
timeout=5,
)
if respuesta.status_code == 404:
meta = respuesta.json()["meta"]
# degradado=True: no se pudo preguntar. Distinto de «no existe».
nombre = None if meta.get("degradado") else "no existe"
elif not respuesta.ok:
# El código es estable; el mensaje puede cambiar.
raise RuntimeError(respuesta.json()["error"]["codigo"])
else:
cuerpo = respuesta.json()
nombre = cuerpo["data"]["nombre"]
Qué hacer con cada respuesta
| Estado | Qué significa | Qué hacer |
|---|---|---|
200 |
La ficha, con meta.origen y meta.fecha_dato |
Guarda también la procedencia: es lo que te deja explicar un dato meses después |
404 |
meta.degradado dice si se pudo preguntar |
Con degradado: true, no lo guardes como «no existe» |
403 |
Scope, finalidad o plan | Mira /me: dice cuál de los tres te falta |
429 |
Ritmo, cuota o presupuesto | Reintenta pasado Retry-After; si es cuota, no se arregla esperando: vuelve en
X-Cuota-Reinicio, o antes con una bolsa. Cada respuesta trae X-Cuota-Restante
para verlo venir |
El catálogo completo de errores, con qué hacer ante cada uno, está en la documentación. Y el contrato entero, en OpenAPI 3.1: genera tu cliente de ahí en vez de escribir los tipos a mano.