NexoID · API de RUC y DNI
Resuelve RUC y DNI peruanos desde fuentes oficiales, con la procedencia de cada dato en la respuesta. Sin caché de borde: cada consulta llega al origen y queda auditada.
El alta autoservicio todavía no está abierta. La documentación y el contrato de la API son públicos; para una cuenta, escríbenos.
Empezar
La base es https://nexoid.victorllerena.com/id/v1 y la autenticación es un
bearer token. Los tokens empiezan por nxid_live_ o
nxid_test_; los de pruebas no consumen cuota.
curl -H "Authorization: Bearer nxid_test_…" \
https://nexoid.victorllerena.com/id/v1/ruc/20131312955
🔒 La sorpresa que se lleva todo el mundo al migrar.
Un RUC que empieza por 10, 15 o 17
es una persona natural: su campo nombre es el nombre de
alguien, y por eso GET /ruc/10724923530 entrega lo mismo que
GET /dni/72492353. Ese es el documento del titular del servicio, publicado con su
consentimiento: un número inventado casi siempre es el DNI de otra persona.
El régimen lo decide el contenido, no la ruta. Un token con solo
ruc.read recibe 403 scope_insuficiente al
consultarlo, la respuesta va private, no-store y la auditoría guarda el
documento hasheado. Si vienes de otro proveedor, este es el primer 403 que verás.
Los datos de identidad exigen además finalidad declarada, base legal y anexo de tratamiento firmado. No se activan desde la web: se tramitan con nosotros.
Endpoints
| Endpoint | Scopes | Cuota |
|---|---|---|
GET /calendario/feriados/{anio}Feriados del Perú de un año |
— | no |
GET /calendario/plazoEn qué fecha vence un plazo de N días hábiles |
— | no |
GET /calendario/{fecha}Si una fecha es día hábil |
— | no |
GET /demo/ruc/{ruc}La demo de la landing: un RUC 20, sin token |
ruc.read |
no |
GET /demo/tipo-cambioLa demo de la landing: el tipo de cambio del día, sin token |
tc.read |
no |
POST /dni/batchHasta 100 DNIs de una vez |
batchdni.read |
sí |
GET /dni/{dni}Identidad de una persona natural por DNI |
dni.read |
sí |
GET /healthEstado del servicio y frescura del padrón |
público | no |
GET /meQué es este token y qué puede hacer |
— | no |
GET /openapi.jsonEsta misma especificación |
público | no |
GET /proveedor/{ruc}El alta de proveedor: ficha, padrones de SUNAT, sanciones y vigilancia |
ruc.read |
sí |
POST /ruc/batchHasta 100 RUCs de una vez |
batchruc.read |
sí |
GET /ruc/buscarBúsqueda por razón social |
ruc.search |
sí |
GET /ruc/{ruc}Ficha de contribuyente por RUC |
ruc.read |
sí |
GET /tipo-cambioTipo de cambio de hoy |
tc.read |
no |
GET /tipo-cambio/mes/{periodo}Tipo de cambio de un mes |
tc.read |
no |
GET /tipo-cambio/rangoSerie histórica de tipo de cambio |
tc.read |
no |
GET /tipo-cambio/{fecha}Tipo de cambio de una fecha |
tc.read |
no |
GET /ubigeo/{codigo}Departamento, provincia y distrito de un código INEI |
— | no |
GET /usoConsumo del periodo, desglosado |
— | no |
GET /vencimientos/proximosLos próximos vencimientos SUNAT de un dígito |
— | no |
GET /vencimientos/{anio}El cronograma de vencimientos SUNAT de un año |
— | no |
GET /watch/eventosHistorial de cambios detectados |
watch.manage |
no |
GET /watch/listasListar watchlists |
watch.manage |
no |
POST /watch/listasCrear una watchlist |
watch.manage |
no |
POST /watch/listas/{lista}/rucsAgregar RUCs a una watchlist |
watch.manage |
no |
DELETE /watch/listas/{lista}/rucsQuitar RUCs de una watchlist |
watch.manage |
no |
GET /watch/webhooksListar endpoints de webhook |
watch.manage |
no |
POST /watch/webhooksRegistrar un endpoint de webhook |
watch.manage |
no |
POST /watch/webhooks/{endpoint}/probarEnviar una entrega de prueba |
watch.manage |
no |
El contrato completo, con parámetros y descripciones, está en OpenAPI 3.1 — generado de la tabla de rutas en cada petición, así que describe este despliegue.
Probar ahora
Pega tu token de pruebas y lanza una consulta de verdad contra esta misma instalación.
🔒 Solo tokens nxid_test_. Con uno de producción esta
página gastaría tu cuota, y la petición saldría con nuestra IP — saltándose
la allowlist que tú configuraste. Tu token no se guarda en ningún sitio.
Catálogo de errores
Toda respuesta de error trae un error.codigo estable. Ramifica por él, nunca
por el mensaje ni por el status: dos códigos distintos pueden compartir status y significar
cosas opuestas.
| Código | Qué hacer |
|---|---|
token_invalido |
Revisa la cabecera Authorization: Bearer. El token pudo expirar o ser revocado. |
ip_no_permitida |
El token tiene allowlist de IPs y la petición no sale de ninguna. Se cambia desde el panel. |
scope_insuficiente |
El scope efectivo es la intersección del token con el plan: mira scopes_efectivos en /me para saber cuál de los dos falta. |
finalidad_no_declarada |
Faltan finalidad, base legal o el anexo de tratamiento firmado. Es requisito para servir identidad y se resuelve con nosotros, no en el código. |
tenant_suspendido |
La cuenta está suspendida. Contacta con soporte. |
sin_plan_vigente |
La cuenta no tiene suscripción vigente. Sin plan no hay scopes, así que esto no se arregla esperando. |
documento_invalido |
El RUC o el DNI no pasan la validación de formato o de dígito verificador. Valídalo en tu lado y ahorras la llamada. |
rate_limit_excedido |
Vas demasiado rápido. Reintenta pasado lo que diga Retry-After. |
presupuesto_agotado |
El presupuesto mensual de consultas a fuentes externas se agotó. El documento podría existir; no es un 404. |
cuota_agotada |
La cuota del periodo se acabó y el plan no permite excedente. Se arregla subiendo de plan. |
tope_excedente_alcanzado |
El plan sí permite excedente, pero se alcanzó el tope de gasto configurado para tu cuenta. Se arregla subiendo el tope, no el plan. |
tope_de_pruebas_alcanzado |
Un token de prueba admite un número de consultas al día, y ya se usaron. Se reinicia a medianoche (hora de Lima); para más, usa un token live, que gasta tu cuota. |
no_disponible_en_sandbox |
Un token de prueba responde con el sandbox, un conjunto fijo y sintético, y esta operación solo tiene sentido con datos reales. Usa un token live. |
tope_watch_alcanzado |
El plan no admite más listas de vigilancia o más RUC vigilados. No es un problema del documento: se arregla subiendo de plan, o dejando de vigilar lo que ya no interesa. |
intentos_agotados |
Ya se verificó ese documento las veces que se permiten en la ventana. Es una protección: probar nombres contra un documento sería la forma de averiguarlo. Vuelve pasado lo que diga Retry-After, con el nombre que te dio el titular. |
servicio_no_disponible |
Una pieza del servicio que esta operación necesita no responde, y por seguridad no se responde sin ella. Es nuestro, no de tu petición: reintenta en unos segundos. |
credencial_sol_no_configurada |
Para validar comprobantes hacen falta tus credenciales de la API de la SUNAT (client_id y client_secret, que generas en SOL). Se cargan con nosotros: nunca se usan las de otro. |
credencial_sol_rechazada |
La SUNAT no acepta tus credenciales de SOL. Genera unas nuevas en SUNAT Operaciones en Línea y cárgalas otra vez: esperar no lo arregla. |
fuente_no_disponible |
La fuente oficial no respondió a tiempo. No es tu petición ni se cobra: reintenta en unos segundos. |
Lo que NexoID no hace
- No hay búsqueda de personas naturales por nombre. La búsqueda por razón social devuelve solo RUC tipo 20.
- No hay exportación ni descarga masiva, ni endpoints que devuelvan poblaciones.
- No hay scoring, inferencias, datos sensibles ni biometría.
- No hay caché de borde: cada consulta llega al origen y queda registrada.
No es una lista de funciones pendientes: es el diseño. Un servicio que resuelve identidad y además deja barrerla no es lo mismo con más funciones — es otra cosa.