Un caso representa un vehículo. Aquí defines el `case_id` que vas a usar para adjuntar documentos y consultar resultados.
Autenticación: todos los endpoints de esta página requieren
Authorization: Bearer <token>. Ninguno aceptax-api-key— la serie/v1/casesresuelve la empresa y el usuario a partir del token. Ver Autenticación.
| Método | Ruta | Descripción |
|---|---|---|
GET | /v1/cases | Lista paginada de casos de la empresa autenticada |
POST | /v1/cases | Crea un caso, opcionalmente con documentos iniciales |
GET | /v1/cases/{case_id} | Consulta el caso y sus documentos con OCR |
DELETE | /v1/cases/{case_id} | Da de baja el caso (baja lógica) |
POST | /v1/cases/{case_id}/assign | Asigna el caso a un usuario de tu empresa |
GET | /v1/cases/{case_id}/names | Nombres consolidados detectados en los documentos |
GET | /v1/cases/{case_id}/vins | VIN principal y VINs detectados por documento |
GET | /v1/cases/{case_id}/plates | Placas detectadas en el caso con datos de vigencia |
GET | /v1/cases/{case_id}/chain_plates | Cadena (histórico) de placas del vehículo |
POST | /v1/cases/{case_id}/chain_plates | Genera la cadena de placas del vehículo en background |
GET | /v1/cases/{case_id}/ownership_chain | Cadena de propiedad (histórico de dueños) del vehículo |
POST | /v1/cases/{case_id}/ownership_chain | Genera la cadena de propiedad del vehículo en background |
GET | /v1/cases/{case_id}/repuve | Datos de inscripción REPUVE del vehículo |
GET | /v1/cases/{case_id}/pedimento | Resultado más reciente de consulta de pedimento |
POST | /v1/cases/{case_id}/pedimento | Lanza una nueva consulta de pedimento con datos del OCR |
GET | /v1/cases/{case_id}/rapi | Resultado más reciente de consulta RAPI (FGJCDMX actividad ilícita) |
POST | /v1/cases/{case_id}/rapi | Lanza una consulta RAPI para el VIN principal del caso |
GET | /v1/cases/{case_id}/renapo | Resultado más reciente de validación RENAPO (CURP) |
POST | /v1/cases/{case_id}/renapo | Lanza validación RENAPO del CURP del caso |
GET | /v1/cases/{case_id}/transunion | Resultado más reciente de TransUnion AutoInfo para el caso |
POST | /v1/cases/{case_id}/transunion | Lanza una consulta TransUnion AutoInfo para el VIN principal |
GET | /v1/cases/{case_id}/tickets | Infracciones de todas las placas del caso (solo lectura) |
POST | /v1/cases/{case_id}/tickets | Lanza consulta masiva de infracciones para todas las placas del caso |
POST | /v1/cases/{case_id}/taxes | Lanza consulta masiva de tenencias para todas las placas del caso |
GET | /v1/cases/{case_id}/invoices | Facturas del caso con el resultado de sus cuatro validaciones |
GET | /v1/cases/{case_id}/metadata | Datos de negocio asociados al caso |
POST | /v1/cases/{case_id}/metadata | Agrega una entrada al historial de metadata |
POST | /v1/cases/{case_id}/process | Lanza el procesamiento masivo de los documentos |
GET | /v1/cases/{case_id}/status | Estado del último job de procesamiento |
/v1/cases — Listar casos#Devuelve la lista paginada de casos de la empresa del usuario autenticado, ordenada del más reciente al más antiguo.
| Parámetro | Tipo | Default | Descripción |
|---|---|---|---|
limit | integer | 20 | Tamaño de página (máx 100) |
offset | integer | 0 | Cursor numérico para paginación |
internal_id | string | — | Filtro por internal_id (coincidencia parcial, insensible a mayúsculas) |
vin | string | — | Filtro por VIN (búsqueda parcial en documentos del caso) |
case_type | UUID | — | Filtro por caso de uso de catálogo (n_vehicles.case_id, coincidencia exacta) |
# Todos los casos (primera página)
curl "https://api.nexcar.mx/v1/cases?limit=20&offset=0" \
-H "Authorization: Bearer tu_token_jwt"
# Filtrar por internal_id
curl "https://api.nexcar.mx/v1/cases?internal_id=EXP-2026" \
-H "Authorization: Bearer tu_token_jwt"
# Filtrar por VIN
curl "https://api.nexcar.mx/v1/cases?vin=00000000000000000" \
-H "Authorization: Bearer tu_token_jwt"
# Filtrar por caso de uso de catálogo
curl "https://api.nexcar.mx/v1/cases?case_type=a1b2c3d4-0000-0000-0000-000000000000" \
-H "Authorization: Bearer tu_token_jwt"
{
"data": [
{
"case_id": "00000000-0000-0000-0000-000000000001",
"internal_id": "EXP-2026-0001",
"review_status": "pending",
"use_case_id": "a1b2c3d4-0000-0000-0000-000000000000",
"user_id_added_by": "usr-00000000-0000-0000-0000-000000000001",
"created_by": "usr-00000000-0000-0000-0000-000000000001",
"created_at": "2026-06-08T10:00:00+00:00",
"active": true
}
],
"pagination": {
"limit": 20,
"offset": 0,
"total": 142,
"has_more": true
}
}
| Campo | Tipo | Descripción |
|---|---|---|
case_id | UUID | Identificador del vehículo / caso |
internal_id | string | Tu identificador de referencia |
review_status | string | null | Estado de revisión actual |
use_case_id | UUID | null | Caso de uso de catálogo asignado |
user_id_added_by | UUID | null | Usuario que creó el caso |
created_by | UUID | null | Usuario atribuido como creador |
created_at | string | Fecha de creación en formato ISO 8601 |
active | boolean | true = caso activo |
pagination.total | integer | Total de registros que coinciden |
pagination.has_more | boolean | true si hay más páginas |
| HTTP | Causa |
|---|---|
400 | No se pudo determinar company_id desde el token |
/v1/cases — Crear caso#Crea un caso para un vehículo. Puedes adjuntar documentos en la misma llamada o subirlos después.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
internal_id | string | Sí | Identificador del caso en tu sistema. No puede estar vacío. |
status | string | Sí | Estado inicial del caso (p. ej. processing, nuevo). |
vehicle_origin | string | No | Nacional (default) o Importado. |
initial_status | string | No | Estado inicial alternativo cuando se configuró un catálogo de estatus. |
use_case | UUID | No | Caso de uso del expediente cuando aplique catálogo. |
metadata | object | No | Datos de negocio adicionales (ver más abajo). |
files | array | No | Documentos a cargar de inmediato. |
curl -X POST https://api.nexcar.mx/v1/cases \
-H "Authorization: Bearer tu_token_jwt" \
-H "Content-Type: application/json" \
-d '{
"internal_id": "EXP-2026-0001",
"status": "processing",
"vehicle_origin": "Nacional",
"metadata": {
"numero_siniestro": "000000000",
"tipo_afectado": "TERCERO",
"nombre_afectado": "NOMBRE APELLIDO APELLIDO"
},
"files": [
{
"url": "https://tu-storage.example.com/factura.pdf",
"mime_type": "application/pdf",
"document_type": "factura"
},
{
"url": "https://tu-storage.example.com/ine-titular.jpg",
"mime_type": "image/jpeg",
"document_type": "ine"
}
]
}'
{
"internal_id": "EXP-2026-0001",
"status": "processing",
"vehicle_origin": "Nacional",
"metadata": {
"numero_siniestro": "000000000",
"tipo_afectado": "TERCERO",
"nombre_afectado": "NOMBRE APELLIDO APELLIDO"
},
"files": [
{
"url": "https://tu-storage.example.com/factura.pdf",
"mime_type": "application/pdf",
"document_type": "factura"
},
{
"url": "https://tu-storage.example.com/ine-titular.jpg",
"mime_type": "image/jpeg",
"document_type": "ine"
}
]
}
201 Created — caso creado sin archivos:
{ "case_id": "00000000-0000-0000-0000-000000000001", "status": "completed" }
202 Accepted — caso creado con archivos en procesamiento:
{
"case_id": "00000000-0000-0000-0000-000000000001",
"job_id": "00000000-0000-0000-0000-000000000003",
"total_files": 2,
"status": "processing"
}
| HTTP | Código | Causa |
|---|---|---|
400 | VALIDATION_ERROR | status ausente o internal_id vacío |
400 | DUPLICATE_INTERNAL_ID | Ya existe un caso con ese internal_id y archivos cargados |
422 | INVALID_STATUS | status no está dentro del catálogo configurado |
/v1/cases/{case_id}#Devuelve el caso y todos sus documentos con su OCR (cuando esté disponible).
curl https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555 \
-H "Authorization: Bearer tu_token_jwt"
Por defecto solo devuelve documentos activos; usa ?files=all para incluir también los inactivos.
{
"case_id": "00000000-0000-0000-0000-000000000001",
"internal_id": "EXP-2026-0001",
"review_status": "pending",
"created_at": "2026-06-08T10:00:00+00:00",
"files": [
{
"file_id": "00000000-0000-0000-0000-000000000002",
"created_at": "2026-06-08T10:05:00+00:00",
"document_type": "bank_account",
"document_subtype": null,
"mime_type": "application/pdf",
"active": true,
"url": "https://...nexcar.mx/storage/v1/object/public/vehicles/.../doc.pdf",
"ocr": {}
}
]
}
document_subtype es el subtipo del documento cuando está disponible; de lo contrario null.
/v1/cases/{case_id}#Marca el caso como inactivo. No borra archivos físicamente; deja de aparecer en consultas y reportes.
curl -X DELETE https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555 \
-H "Authorization: Bearer tu_token_jwt"
/v1/cases/{case_id}/assign#Asigna el caso a un usuario de tu empresa: quién queda como responsable de revisarlo. Es el equivalente por API de la asignación que se hace desde la interfaz de Nexcar, y escribe el mismo historial que esa vista muestra.
El historial de asignación registra quién asignó, y ese dato sale del token: por eso este endpoint no podría aceptar una API key aunque la serie lo permitiera — identifica a la integración, no a la persona.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
user_id | string | Sí | Identificador del usuario a asignar. Se acepta tanto su uid (el de autenticación) como su pid (el del perfil). |
No mandes el historial ni la fecha: el servidor los construye. La fecha es la del servidor en UTC y el nombre se resuelve desde el perfil del usuario asignado.
curl -X POST https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/assign \
-H "Authorization: Bearer tu_token_jwt" \
-H "Content-Type: application/json" \
-d '{ "user_id": "usr-00000000-0000-0000-0000-000000000001" }'
{
"case_id": "11111111-2222-3333-4444-555555555555",
"assigned_to": "usr-00000000-0000-0000-0000-000000000001",
"assignment_history": [
{
"date": "2026-08-11T18:42:07.512843+00:00",
"user": "Ana Ramírez",
"pid": "pid-00000000-0000-0000-0000-000000000009",
"label": "Expediente asignado a Ana Ramírez."
}
]
}
| Campo | Tipo | Descripción |
|---|---|---|
case_id | UUID | El caso afectado |
assigned_to | string | El identificador que mandaste en user_id, tal cual |
assignment_history | array | Historial completo, del más antiguo al más reciente. Cada asignación agrega una entrada; ninguna se reemplaza. |
assignment_history[].date | string | Fecha del servidor en UTC, ISO 8601 |
assignment_history[].user | string | Nombre del usuario asignado; su correo si no tiene nombre, y un usuario si no tiene ninguno de los dos |
assignment_history[].pid | string | pid del perfil asignado |
assignment_history[].label | string | Texto listo para mostrar en una bitácora |
Las dos partes deben pertenecer a la empresa dueña del caso:
403.Reasignar es una operación válida y esperada: cada llamada agrega una entrada más al historial, incluso si asignas al mismo usuario que ya lo tenía.
Si tu empresa tiene configurado el webhook v1-assign-analyst, cada asignación lo dispara de forma asíncrona. La asignación se guarda aunque el webhook falle. Para activarlo, escríbele a tu contacto en Nexcar.
| HTTP | Código | Causa |
|---|---|---|
400 | VALIDATION_ERROR | Falta user_id, viene vacío, o el cuerpo no es un objeto JSON |
400 | VALIDATION_ERROR | El usuario indicado no existe |
400 | VALIDATION_ERROR | El caso no tiene empresa asociada, así que no hay contra qué validar la asignación |
400 | VALIDATION_ERROR | El perfil del usuario indicado no tiene pid, así que no se puede asignar |
403 | FORBIDDEN | El usuario a asignar pertenece a otra empresa |
403 | FORBIDDEN | Tu token pertenece a otra empresa que la del caso |
404 | RESOURCE_NOT_FOUND | El caso no existe |
/v1/cases/{case_id}/process#Encola el procesamiento masivo (OCR + extracción) de los documentos del caso. Útil cuando subiste archivos sin tipo y quieres lanzar el flujo en batch.
curl -X POST https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/process \
-H "Authorization: Bearer tu_token_jwt"
{ "job_id": "00000000-0000-0000-0000-000000000003", "status": "processing" }
Consulta el avance con GET /v1/cases/{case_id}/status.
/v1/cases/{case_id}/plates#Devuelve las placas detectadas en los documentos del caso, enriquecidas con NIV, número de motor, nombre del propietario y — para placas emplaçadas en el Estado de México — los datos de vigencia (estatus, fechas de vigencia y placa anterior cuando aplique) consultados al portal oficial.
La lista se construye y persiste automáticamente como parte del pipeline de procesamiento del caso. Este endpoint es de solo lectura.
curl https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/plates \
-H "Authorization: Bearer tu_token_jwt"
{
"case_id": "00000000-0000-0000-0000-000000000001",
"internal_id": "EXP-2026-0001",
"plates": [
{
"plate": "ABC1234",
"entity": "MEX",
"document_type": "vehicle_certificate",
"document_date": "01/09/2025",
"file_id": "00000000-0000-0000-0000-000000000005",
"ocr_id": "00000000-0000-0000-0000-000000000006",
"niv": "00000000000000000",
"motor_number": "00000000000",
"owner_name": null,
"plate_status": "Vigente",
"plate_valid_from": "01/09/2025",
"plate_valid_until": "01/09/2030",
"previous_plate": null,
"previous_plate_lookup_status": null
}
]
}
| Campo | Tipo | Descripción |
|---|---|---|
plate | string | Placa normalizada (mayúsculas, sin separadores) |
entity | string | Código de tres letras del estado (MEX, NLE, JAL, …) |
document_type | string | Documento de origen: certificate_title, tax_payment, alta_vehicular, vehicle_certificate, vehicle_plate, lumo_checklist o repuve |
document_date | string | Fecha asociada al documento de origen (DD/MM/YYYY cuando esté disponible) |
niv | string | null | Número de identificación vehicular (17 caracteres cuando está disponible; parcial en otros casos) |
motor_number | string | null | Número de motor del documento de origen |
owner_name | string | null | Propietario declarado en el documento de origen |
plate_status | string | null | Estatus actual de la placa según el portal: Vigente, Vencida o Inactiva |
plate_valid_from | string | null | Inicio de vigencia de la placa actual (DD/MM/YYYY) |
plate_valid_until | string | null | Fin de vigencia de la placa actual (DD/MM/YYYY) |
previous_plate | string | null | Placa anterior, cuando existió una previa a la actual |
previous_plate_lookup_status | string | null | Estado de la consulta — ver tabla |
previous_plate_lookup_status#| Valor | Significado |
|---|---|
null | La consulta no aplica (placa no emplaçada en MEX) o el portal confirmó que no hay placa anterior |
"pending" | Consulta en curso en background — vuelve a llamar en unos segundos |
"found" | El portal devolvió una placa anterior (poblada en previous_plate) |
"error" | La consulta falló tras los reintentos (portal caído, error de parseo, etc.) |
La misma placa puede aparecer en varios elementos del arreglo cuando se detectó en más de un documento. Todos los elementos con la misma placa comparten plate_status, fechas de vigencia y campos previous_plate_* una vez que el lookup en background termina.
| HTTP | Causa |
|---|---|
404 | Caso no encontrado, inactivo, o aún no se han calculado las placas para este caso |
/v1/cases/{case_id}/chain_plates#Devuelve la cadena de placas del vehículo: el histórico ordenado de placas (Estado de México), cada una con su periodo de vigencia y los documentos que la sustentan. La cadena la calcula el procesamiento del caso y se persiste; este endpoint es de solo lectura.
curl https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/chain_plates \
-H "Authorization: Bearer tu_token_jwt"
{
"case_id": "00000000-0000-0000-0000-000000000001",
"internal_id": "EXP-2026-0001",
"niv": "00000000000000000",
"summary": {
"plate_count": 2,
"current_plate": "NEF076A",
"chain_scope": "edomex_only",
"generated_at": "2026-08-25T14:22:10Z"
},
"chain": [
{
"sequence_index": 0,
"plate": "MEX44J09",
"entity": "MEX",
"period_start": "2023-02-14",
"period_end": "2023-07-04",
"period_precision": "day",
"is_current": false,
"predecessor_plate": null,
"documents": [
{
"file_id": "00000000-0000-0000-0000-000000000005",
"ocr_id": "00000000-0000-0000-0000-000000000006",
"source_kind": "ocr",
"document_type": "vehicle_certificate",
"field_name": "placa_matricula",
"plate": "MEX44J09",
"folio": "0150337",
"issued_at": "2023-02-14",
"date_source": "document_field",
"valid_until": null,
"owner_name": null,
"niv": "00000000000000000",
"niv_matches_case_niv": true,
"file_url": null
}
]
}
],
"status": "completed",
"message": null
}
status | Significado |
|---|---|
completed | La cadena ya está generada — se devuelve en summary + chain |
processing | La cadena se está generando en background — vuelve a llamar en unos segundos |
pending | El caso aún no tiene una cadena generada — lanza el POST |
En processing/pending, summary es null y chain es []; el resto de campos siempre están
presentes.
| Campo | Tipo | Descripción |
|---|---|---|
niv | string | null | VIN del vehículo (del VIN consolidado del caso) |
summary.plate_count | number | Número de placas en la cadena |
summary.current_plate | string | null | Placa vigente |
summary.chain_scope | string | Alcance de la cadena (edomex_only) |
chain[].sequence_index | number | Orden cronológico (0 = más antigua) |
chain[].plate | string | Placa del tramo |
chain[].period_start / period_end | string | null | Vigencia del tramo (YYYY-MM-DD) |
chain[].is_current | boolean | Si es la placa vigente |
chain[].predecessor_plate | string | null | Placa inmediatamente anterior |
chain[].documents | array | Documentos que sustentan el tramo |
| HTTP | Causa |
|---|---|
404 | Caso no encontrado o inactivo |
/v1/cases/{case_id}/chain_plates#Dispara la generación de la cadena de placas del vehículo en background. Es fire-and-forget:
responde de inmediato con status: "processing" y la cadena queda disponible en el GET cuando
termina. No recibe parámetros (solo el case_id de la ruta).
curl -X POST https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/chain_plates \
-H "Authorization: Bearer tu_token_jwt"
{
"case_id": "00000000-0000-0000-0000-000000000001",
"internal_id": "EXP-2026-0001",
"niv": "00000000000000000",
"summary": null,
"chain": [],
"status": "processing",
"message": "La generación de la cadena de placas se está ejecutando en background."
}
| HTTP | Causa |
|---|---|
400 | case_id no es un UUID válido, o se enviaron parámetros en el cuerpo |
404 | Caso no encontrado o inactivo |
/v1/cases/{case_id}/ownership_chain#Devuelve la cadena de propiedad del vehículo: el histórico ordenado de dueños con sus periodos de
tenencia, los documentos que lo sustentan y los huecos (gaps) donde una transferencia no pudo
rastrearse. La cadena la calcula el procesamiento del caso y se persiste; este endpoint es de solo
lectura.
curl https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/ownership_chain \
-H "Authorization: Bearer tu_token_jwt"
{
"case_id": "00000000-0000-0000-0000-000000000001",
"internal_id": "EXP-2026-0001",
"summary": {
"owner_count": 2,
"gap_count": 1,
"current_owner": "JUAN PEREZ",
"chain_pivot": "invoice_original",
"generated_at": "2026-08-27T14:22:10Z"
},
"chain": [
{
"sequence_index": 0,
"display_name": "FÁBRICA SA",
"person_type": "moral",
"role_label": "…",
"is_current": false,
"acquired_at": "2023-02-14",
"transferred_at": "2023-07-04",
"match_status": "matched",
"link_to_previous": null,
"source_document": { "document_type": "invoice", "folio": "…", "file_id": "…" }
}
],
"gaps": [
{
"gap_id": "g1",
"gap_type": "untraceable_transfer",
"from_owner": "…",
"to_owner": "…",
"related_sequence_indexes": [0, 1]
}
],
"status": "completed",
"message": null
}
status | Significado |
|---|---|
completed | La cadena ya está generada — summary + chain + gaps (chain: [] con completed = sin transmisiones rastreables, resultado vacío legítimo). |
processing | Se está generando en background (la cadena, o la consolidación de nombres de la que depende). Vuelve a llamar en unos segundos. |
pending | El caso aún no tiene una cadena generada — lanza el POST. |
En processing/pending, summary es null y chain/gaps son []; el resto de campos siempre
están presentes. No se asuma un set fijo de campos dentro de chain[]/gaps[]: el worker define esa
forma y evoluciona.
| HTTP | Causa |
|---|---|
404 | Caso no encontrado o inactivo |
/v1/cases/{case_id}/ownership_chain#Dispara la generación de la cadena de propiedad en background. Es fire-and-forget: responde de
inmediato con status: "processing" y la cadena queda disponible en el GET cuando termina. No
recibe parámetros (solo el case_id de la ruta). Si el caso aún no tiene nombres consolidados, la
generación incluye primero esa consolidación (ruta más lenta) — dimensiona el polling en consecuencia.
curl -X POST https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/ownership_chain \
-H "Authorization: Bearer tu_token_jwt"
{
"case_id": "00000000-0000-0000-0000-000000000001",
"internal_id": "EXP-2026-0001",
"summary": null,
"chain": [],
"gaps": [],
"status": "processing",
"message": "La generación de la cadena de propiedad se está ejecutando en background."
}
| HTTP | Causa |
|---|---|
400 | case_id no es un UUID válido, o se enviaron parámetros en el cuerpo |
404 | Caso no encontrado o inactivo |
/v1/cases/{case_id}/repuve#Retorna el job de REPUVE más reciente para el caso. Si el job terminó en error pero existe una respuesta válida de placas.info, el endpoint aplica auto-recuperación y devuelve los datos correctos.
curl https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/repuve \
-H "Authorization: Bearer tu_token_jwt"
{
"codigo": "ok",
"info": {
"niv": "00000000000000000",
"placa": "ABC1234",
"marca": "NISSAN",
"modelo": "NP300/NP300 FRONTIER/FRONTIER",
"tipo": "CAB. Y CHASIS ESTACAS",
"clase": "CAMIONETA",
"anio_modelo": 2020,
"entidad_emplacado": "CIUDAD DE MEXICO",
"fecha_inscripcion": "22/09/20",
"fecha_actualizacion": "12/10/24",
"reporte_robo": [
{ "tipo_reporte": "FGJ", "estatus": "SIN REPORTE DE ROBO" },
{ "tipo_reporte": "OCRA", "estatus": "SIN REPORTE DE ROBO" }
],
"robo_usa_can": { "tiene_robo": false },
"aviso_judicial": { "tiene_aviso_judicial": false }
},
"job_id": "00000000-0000-0000-0000-000000000004",
"job_status": "completed"
}
| Campo | Tipo | Descripción |
|---|---|---|
codigo | string | ok — datos de REPUVE disponibles. error — todos los servicios fallaron. processing — job aún en curso. |
info | object | null | Datos de inscripción del vehículo en REPUVE. null cuando el vehículo no está inscrito o el job no ha completado. |
info.niv | string | Número de identificación vehicular (NIV/VIN) |
info.placa | string | null | Placa registrada en REPUVE |
info.marca | string | Marca |
info.modelo | string | Modelo |
info.anio_modelo | integer | Año modelo |
info.entidad_emplacado | string | null | Estado de emplacamiento |
info.fecha_inscripcion | string | null | Fecha de inscripción en REPUVE |
info.fecha_actualizacion | string | null | Fecha de última actualización en REPUVE |
info.reporte_robo | array | Reportes de robo de las fuentes FGJ y OCRA |
info.robo_usa_can | object | Estado de reporte de robo en USA/Canadá |
info.aviso_judicial | object | Estado de aviso judicial |
job_id | UUID | Identificador interno del job |
job_status | string | completed, error, processing o pending |
| HTTP | Causa |
|---|---|
404 | Caso no encontrado, inactivo, o no se ha realizado ninguna consulta REPUVE para este caso |
/v1/cases/{case_id}/pedimento#Devuelve el resultado más reciente de consulta de pedimento para el caso. Los datos se leen de pedimento_responses (pipeline legacy) y processing_jobs (API v1), se deduplican por contenido y se ordenan por fecha.
curl https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/pedimento \
-H "Authorization: Bearer tu_token_jwt"
{
"case_id": "00000000-0000-0000-0000-000000000001",
"job_id": "00000000-0000-0000-0000-000000000004",
"status": "completed",
"source": "processing_jobs",
"result": {
"success": true,
"data": { "pedimento": "00000000000", "aduana": "MANZANILLO", "vin": "00000000000000000" }
}
}
| HTTP | Causa |
|---|---|
404 | Caso no encontrado, inactivo, o no se ha realizado ninguna consulta de pedimento. Llama a POST /v1/cases/{id}/pedimento primero. |
/v1/cases/{case_id}/taxes#Devuelve la información de tenencia del caso en dos bloques independientes, cada uno con envelope {message, status, result}. Es de solo lectura: no dispara consultas nuevas y siempre responde 200 cuando el caso existe — la falta de datos se comunica con result: [] y un message.
status de cada bloque solo tiene dos valores: completed (el bloque llegó a su desenlace: hay con qué construirlo —aunque el contenido sea un error de negocio— o el caso no tiene ninguna placa que consultar) y processing (queda una consulta pendiente: una placa del expediente con la consulta en curso o sin ejecutar).
Cambio de contrato (21 de agosto de 2026). Los dos vacíos por ausencia de placas —
"No se encontraron placas registradas"y"Las placas registradas no corresponden al VIN del expediente"— pasan deprocessingacompleted. No queda ninguna consulta en vuelo, así que reintentar devolvía el mismo envelope indefinidamente; elmessagees el que explica el vacío. Si tu integración reintenta cuando veprocessing, lee elmessagepara saber qué falta. Sigue enprocessingel caso con placas y sin consulta ("Aún no se ha ejecutado ninguna consulta de tenencia para este caso."), que es el que sí se resuelve con unPOST.
Las placas que publica el endpoint son las del expediente, no todo lo que acumuló n_vehicles.parsed_data.plates: se conservan las entradas cuyo niv coincide con el VIN del caso (parsed_data.vin.value — match exacto, o un niv parcial que sea sufijo del VIN) y se descartan las de otro VIN, que son de otro vehículo. Un niv vacío no descalifica (hay documentos que portan placa y no portan VIN). La identidad es el par (placa, entidad): la misma placa emplacada en dos estados son dos consultas distintas y las dos se publican. Entre varias entradas del mismo par gana la de document_date más reciente. Si el caso todavía no tiene VIN consolidado no se filtra nada.
main_tax#La placa principal del caso es la que tiene el document_date más reciente entre las placas extraídas; las placas sin fecha no compiten. Si ninguna tiene fecha, se toma la primera placa legible. El bloque sale completed con result: [] solo cuando ninguna placa del caso es legible.
result es una rejilla fija de 5 ejercicios fiscales (año corriente + 4 hacia atrás, orden descendente). Cada fila cruza dos fuentes para el mismo año:
| Campo | Significa |
|---|---|
fiscal_year | El ejercicio de la ventana |
plate_number | La placa principal |
state | Entidad de la placa (abreviada) |
document | Celda {status, message}: si hay un recibo de tenencia (tax_payment) de esa placa que declara ese ejercicio |
source | Celda {status, message}: qué dice el portal de la entidad sobre ese ejercicio |
payment_date | Del recibo, pareado al ejercicio; null si no hay recibo o no se pudo parear |
total | El del portal cuando reporta el ejercicio con importe; si no, el del recibo |
Celda document:
status | message | Cuándo |
|---|---|---|
success | "Agregado" | Hay recibo de tenencia que cubre el ejercicio |
warning | "Pendiente" | No hay recibo para ese ejercicio |
Celda source: el portal reporta adeudos, no pagos — que un ejercicio aparezca ahí significa que hay una deuda pendiente para ese año, no que se haya pagado.
status | message | Cuándo |
|---|---|---|
warning | "Con adeudo" | El portal reporta ese ejercicio |
success | "Sin adeudo" | El portal respondió pero sin ese ejercicio |
failed | Mensaje del portal tal cual | Motivo útil (p. ej. "Vehículo no encontrado o dado de baja") |
failed | "Hubo un error al obtener la información" | Error de la fuente sin detalle publicable |
failed | "No se pudo ejecutar la consulta de tenencia para esta placa." | La consulta no llegó a ejecutarse |
processing | "Se está procesando la información" | La consulta sigue en curso |
processing | "Aún no se ha consultado la tenencia de esta placa" | La placa nunca se consultó |
Cuando la consulta trajo ejercicios, cada año se resuelve por separado; cuando no trajo ninguno, los 5 años comparten la misma conclusión.
taxes#Las placas del caso (principales + anteriores) menos la principal, que ya se publica con todo su detalle en main_tax. Cada placa se alimenta de las mismas dos fuentes que main_tax —recibo y portal— pero sin rejilla fija (un item por ejercicio que alguna de las dos reportó) y con una sola celda por item.
| Campo | Significa |
|---|---|
plate_number | La placa |
state | Entidad de la placa (abreviada); si no la trae, la del recibo |
fiscal_year | El ejercicio, o null cuando ninguna de las dos fuentes reportó nada de esa placa |
status | Celda {status, message}: lo que dice el portal de ese ejercicio |
payment_date | Del recibo de esa placa, pareado al ejercicio |
total | El del portal cuando reporta el ejercicio con importe; si no, el del recibo |
Celda status — la misma celda que source de main_tax, sin modificar:
status | message | Cuándo |
|---|---|---|
success | "Sin adeudo" | El portal no reporta adeudo para ese ejercicio |
warning | "Con adeudo" | El portal reporta adeudo para ese ejercicio |
failed | El motivo del portal, o un mensaje genérico saneado | Error real: no se pudo determinar si hay adeudo o no |
processing | "Se está procesando la información" / "Aún no se ha consultado la tenencia de esta placa" | La consulta va en vuelo, o la placa aún no se consultó |
Este bloque no trae celda document: el desglose del recibo por ejercicio solo está en main_tax. El recibo de la placa sigue aportando el ejercicio, el payment_date y el total de respaldo.
El recibo cuenta para la placa que declara, no para el caso: un recibo de tenencia cargado en el caso que resulta ser de otra placa aparece aquí, en la suya, y no acredita a la principal.
Un ejercicio puede venir de una sola fuente: el portal reporta adeudo en 2026 sin que haya recibo (payment_date en null), o hay recibo de un año que el portal no reportó (status en success / "Sin adeudo", con su payment_date).
Cuando una placa tiene varias consultas gana la más informativa, no la más reciente: un reintento que falló no tapa un intento anterior que sí trajo los ejercicios.
Si la principal es la única placa del caso, el bloque sale completed con result: [] y el mensaje "El caso no tiene placas adicionales a la principal" — está vacío de forma definitiva, no hay que reconsultar. Lo mismo cuando el caso no tiene placas o ninguna es del VIN del expediente: completed con el message que dice cuál de los dos vacíos es. Si la principal no se pudo determinar, no se excluye ninguna. Si el caso no tiene ninguna consulta de tenencia, el bloque sigue en processing pero publica los recibos que ya existan.
curl https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/taxes \
-H "Authorization: Bearer tu_token_jwt"
{
"main_tax": {
"message": "",
"status": "completed",
"result": [
{
"fiscal_year": 2026,
"plate_number": "ABC1234",
"state": "MEX",
"document": { "status": "success", "message": "Agregado" },
"source": { "status": "warning", "message": "Con adeudo" },
"payment_date": "16/03/2026",
"total": 1779
},
{
"fiscal_year": 2025,
"plate_number": "ABC1234",
"state": "MEX",
"document": { "status": "warning", "message": "Pendiente" },
"source": { "status": "warning", "message": "Con adeudo" },
"payment_date": null,
"total": 2071
},
{
"fiscal_year": 2024,
"plate_number": "ABC1234",
"state": "MEX",
"document": { "status": "success", "message": "Agregado" },
"source": { "status": "success", "message": "Sin adeudo" },
"payment_date": "13/02/2024",
"total": "1,045.00"
},
{
"fiscal_year": 2023,
"plate_number": "ABC1234",
"state": "MEX",
"document": { "status": "warning", "message": "Pendiente" },
"source": { "status": "success", "message": "Sin adeudo" },
"payment_date": null,
"total": null
},
{
"fiscal_year": 2022,
"plate_number": "ABC1234",
"state": "MEX",
"document": { "status": "warning", "message": "Pendiente" },
"source": { "status": "success", "message": "Sin adeudo" },
"payment_date": null,
"total": null
}
]
},
"taxes": {
"message": "",
"status": "completed",
"result": [
{ "plate_number": "XYZ5678", "state": "MEX", "fiscal_year": 2026,
"status": { "status": "warning", "message": "Con adeudo" }, "payment_date": "16/03/2026", "total": 1739.0 },
{ "plate_number": "XYZ5678", "state": "MEX", "fiscal_year": 2025,
"status": { "status": "warning", "message": "Con adeudo" }, "payment_date": null, "total": 2031.0 },
{ "plate_number": "JKL9012", "state": "PUE", "fiscal_year": null,
"status": { "status": "failed", "message": "Vehículo no encontrado o dado de baja" }, "payment_date": null, "total": null }
]
}
}
Cuando el caso todavía no tiene placas extraídas:
{
"main_tax": { "message": "No se encontraron placas registradas", "status": "completed", "result": [] },
"taxes": { "message": "No se encontraron placas registradas", "status": "completed", "result": [] }
}
/v1/cases/{case_id}/taxes#Lanza una consulta masiva de tenencias para todas las placas únicas del caso (placas principales + placas anteriores), usando los datos de GET /v1/cases/:id/plates internamente (sin HTTP). Se crea un registro en processing_jobs por cada placa con su propio job_id, external_payload y external_response. El workflow corre en Temporal (cola invoice-background-queue).
curl -X POST https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/taxes \
-H "Authorization: Bearer tu_token_jwt"
202 Accepted#{
"job_id": "00000000-0000-0000-0000-000000000003",
"plates": ["ABC1234", "XYZ5678"],
"status": "pending"
}
Consulta GET /v1/cases/{case_id}/taxes para ver los resultados por placa a medida que se completan. Antes de que termine el primer job, el bloque taxes de ese GET viene con status: "processing" y result: [].
| HTTP | Causa |
|---|---|
400 | No se encontraron placas para este caso. Llama a POST /v1/cases/{id}/plates primero. |
404 | Caso no encontrado o inactivo |
/v1/cases/{case_id}/pedimento#Inicia una nueva consulta de pedimento usando los datos extraídos del OCR del documento principal del caso (la factura vinculada al VIN principal). Se ejecuta de forma asíncrona en Temporal. Devuelve un job_id inmediatamente; consulta GET /v1/cases/{id}/pedimento para obtener el resultado.
Los parámetros requeridos (aduana, ano_vehiculo) se leen del OCR automáticamente. Si no están disponibles en el documento, el endpoint devuelve un 400 indicando los campos que faltan.
curl -X POST https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/pedimento \
-H "Authorization: Bearer tu_token_jwt"
202 Accepted#{ "job_id": "00000000-0000-0000-0000-000000000004", "status": "pending" }
| HTTP | Causa |
|---|---|
400 | No se encontró VIN principal, o faltan campos OCR requeridos (aduana, ano_vehiculo) |
404 | Caso no encontrado o inactivo |
/v1/cases/{case_id}/rapi#Devuelve el resultado más reciente de consulta RAPI (FGJCDMX — actividad ilícita vehicular) para el caso. Lee de rapi_responses (pipeline legacy) y processing_jobs (API v1), deduplicados por contenido y ordenados por fecha.
curl https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/rapi \
-H "Authorization: Bearer tu_token_jwt"
Todas las respuestas devuelven el mismo conjunto de campos: job_id, result, status y message (message es null cuando no aplica).
{
"case_id": "00000000-0000-0000-0000-000000000001",
"job_id": "00000000-0000-0000-0000-000000000004",
"status": "completed",
"message": null
}
Cuando aún no hay resultado RAPI pero el caso está en procesamiento, la respuesta es 200 con el estado del caso (en vez de 404):
{ "job_id": null, "result": null, "status": "processing", "message": "El caso está en procesamiento; la información de RAPI puede completarse en background." }
{ "job_id": null, "result": null, "status": "pending", "message": "El caso aún no está siendo procesado." }
status posibles: completed, error, processing (caso en proceso, RAPI puede completarse en background) y pending (el caso aún no se procesa).
| HTTP | Causa |
|---|---|
404 | Caso no encontrado o inactivo, o no existe ningún job del caso ni consulta RAPI. Llama a POST /v1/cases/{id}/rapi primero. |
/v1/cases/{case_id}/rapi#Lanza una consulta RAPI para el VIN principal del caso (obtenido de GET /v1/cases/:id/vins). Se ejecuta de forma asíncrona en Temporal (invoice-background-queue). Devuelve un job_id inmediatamente.
curl -X POST https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/rapi \
-H "Authorization: Bearer tu_token_jwt"
202 Accepted#{ "job_id": "00000000-0000-0000-0000-000000000004", "vin": "00000000000000000", "status": "pending" }
| HTTP | Causa |
|---|---|
400 | No se encontró VIN principal. Procesa los documentos con POST /v1/cases/{id}/process primero. |
404 | Caso no encontrado o inactivo |
/v1/cases/{case_id}/renapo#Devuelve el resultado más reciente de validación RENAPO (CURP) para el caso. Retorna 404 si aún no se ha ejecutado ninguna consulta.
curl https://api.nexcar.mx/v1/cases/{case_id}/renapo \
-H "Authorization: Bearer tu_token_jwt"
200 OK#{
"case_id": "00000000-0000-0000-0000-000000000001",
"source": "renapo",
"status": "completed",
"query_count": 1,
"completed_count": 1,
"data": {
"job_id": "00000000-0000-0000-0000-000000000002",
"created_at": "2026-06-01T10:00:00+00:00",
"status": "completed",
"curp": "XXXX800101HDFXXX01",
"probative_doc_url": "https://...",
"person": {
"first_name": "NOMBRE",
"paternal_surname": "APELLIDO1",
"maternal_surname": "APELLIDO2",
"birth_date": "01/01/1980",
"birth_state": "CIUDAD DE MEXICO",
"birth_country": "MEXICO",
"sex": "HOMBRE",
"curp_status": "AN",
"validation_status": "OK",
"validation_code": "00",
"message_code": "0",
"probative_doc": null
},
"probative_doc_data": {
"registration_year": "1980",
"state_key": "09",
"municipality_key": "010",
"state": "CIUDAD DE MEXICO",
"municipality": "ALVARO OBREGON",
"foja": null,
"folio": "123",
"book": null,
"tome": null,
"act_number": "456",
"foreign_registry_number": null
}
}
}
Cuando status es pending o error, los campos person y probative_doc_data dentro de data son null.
| HTTP | Causa |
|---|---|
404 | Caso no encontrado, inactivo, o no se ha ejecutado ninguna consulta RENAPO. Llama a POST /v1/cases/{case_id}/renapo primero. |
/v1/cases/{case_id}/renapo#Inicia una validación RENAPO del CURP detectado en los documentos del caso. La operación es asíncrona: retorna un job_id inmediatamente y el resultado queda disponible en GET /v1/cases/{case_id}/renapo una vez completado.
Requiere que el caso tenga al menos un documento con OCR procesado que contenga un CURP válido.
curl -X POST https://api.nexcar.mx/v1/cases/{case_id}/renapo \
-H "Authorization: Bearer tu_token_jwt"
202 Accepted#{
"job_id": "00000000-0000-0000-0000-000000000002",
"curp": "XXXX800101HDFXXX01",
"status": "pending"
}
Consulta GET /v1/cases/{case_id}/renapo para obtener el resultado una vez completado.
| HTTP | Causa |
|---|---|
400 | No hay CURP disponible en los documentos del caso. Procesa los documentos con POST /v1/cases/{case_id}/process primero. |
404 | Caso no encontrado o inactivo |
/v1/cases/{case_id}/transunion#Devuelve el resultado más reciente de TransUnion para el caso. Retorna 404 si aún no se ha ejecutado ninguna consulta.
curl https://api.nexcar.mx/v1/cases/{case_id}/transunion \
-H "Authorization: Bearer tu_token_jwt"
200 OK#{
"case_id": "00000000-0000-0000-0000-000000000001",
"source": "transunion",
"status": "completed",
"query_count": 1,
"completed_count": 1,
"data": { },
"document": {
"url": "https://...nexcar.mx/storage/v1/object/public/vehicles/.../transunion_report.pdf",
"uuid": "00000000-0000-0000-0000-000000000003"
}
}
data contiene el reporte de TransUnion (presente cuando status es completed; null en otro caso).
document referencia el PDF del reporte AutoVerificación generado.
| HTTP | Causa |
|---|---|
404 | Caso no encontrado, inactivo, o no se ha ejecutado ninguna consulta TransUnion. Llama a POST /v1/cases/{case_id}/transunion primero. |
/v1/cases/{case_id}/transunion#Lanza una consulta TransUnion para el VIN principal del caso y genera el PDF del reporte AutoVerificación a partir del resultado. La operación es asíncrona: retorna un job_id inmediatamente y el resultado queda disponible en GET /v1/cases/{case_id}/transunion una vez completado.
curl -X POST https://api.nexcar.mx/v1/cases/{case_id}/transunion \
-H "Authorization: Bearer tu_token_jwt"
202 Accepted#{ "job_id": "00000000-0000-0000-0000-000000000002", "vin": "00000000000000000", "status": "pending" }
| HTTP | Causa |
|---|---|
400 | No se encontró VIN principal. Procesa los documentos con POST /v1/cases/{case_id}/process primero. |
404 | Caso no encontrado o inactivo |
/v1/cases/{case_id}/tickets#Devuelve las infracciones de las placas del expediente: la placa principal primero y después el resto (incluidas las placas anteriores).
Las placas que publica el endpoint son las del expediente, no todo lo que acumuló n_vehicles.parsed_data.plates: se conservan las entradas cuyo niv coincide con el VIN del caso (parsed_data.vin.value — match exacto, o un niv parcial que sea sufijo del VIN) y se descartan las de otro VIN, que son de otro vehículo. Un niv vacío no descalifica (hay documentos que portan placa y no portan VIN). La identidad es el par (placa, entidad): la misma placa emplacada en dos estados son dos consultas distintas y las dos se publican. Entre varias entradas del mismo par gana la de document_date más reciente. Si el caso todavía no tiene VIN consolidado no se filtra nada.
La placa principal se elige entre esas placas, así que un documento de otro vehículo no puede quedar al frente del result.
Es un endpoint de solo lectura: no dispara consultas nuevas. Para eso está POST /v1/cases/{case_id}/tickets.
200 OK#{
"case_id": "00000000-0000-0000-0000-000000000001",
"status": "completed",
"message": null,
"result": [
{
"plate_number": "ABC123",
"state": "PUE",
"ticket_date": "2024-01-23",
"amount": 1037.4,
"status": "success",
"message": "Pagada"
},
{
"plate_number": "XYZ456",
"state": "MEX",
"ticket_date": null,
"amount": null,
"status": "warning",
"message": "Placa sin adeudos"
}
]
}
Todas las filas de result tienen las mismas seis claves, así que no hay que revisar si existen:
| Campo | Descripción |
|---|---|
plate_number | Placa a la que pertenece la fila |
state | Entidad donde se consultó la placa (null si no se conoce) |
ticket_date | Fecha de la infracción |
amount | Monto tal como lo reporta la fuente |
status | "success", "warning", "processing" o "failed" (ver tabla abajo) |
message | Texto legible de la fila: el estatus de pago cuando es una infracción, o el motivo cuando la placa no aporta infracciones |
status es "success" cuando la infracción está pagada o cuando la placa fue consultada y no tiene adeudos; "processing" mientras la consulta sigue en curso; "warning" únicamente para una infracción encontrada y no pagada; cualquier otro caso —incluido un mensaje de negocio de la fuente o una placa nunca consultada— es "failed":
| Caso | status | message |
|---|---|---|
Infracción con estatus PAGADA en la fuente | success | Pagada |
Infracción con estatus NO PAGADA en la fuente | warning | No Pagada |
Infracción con cualquier otro estatus (PENDIENTE, …) | warning | El texto tal como lo reporta la fuente |
| Placa sin infracciones | success | Placa sin adeudos |
| Consulta en curso | processing | Se está procesando la información |
| Consulta no se pudo ejecutar (fallo de proceso o del proveedor) | failed | Hubo un problema al extraer la información |
| Placa nunca consultada | failed | Aún no se ha consultado esta placa |
La fuente respondió con un motivo propio — p. ej. Entidad aún sin cobertura | failed | (texto de la fuente, no es una lista cerrada) |
Cada infracción es una fila. Una placa que no aporta infracciones ocupa una sola fila con ticket_date y amount en null y su motivo en message.
Una placa se consulta en su entidad de emplacado y en CMX (las multas de CDMX aplican a cualquier placa). Cuando ambas consultas tienen registro, la placa aparece dos veces en result —una por cada state— con sus propias filas; ninguna entidad reemplaza a la otra.
La diferencia entre "no se pudo ejecutar" y un motivo de la fuente: Hubo un problema al extraer la información significa que la consulta no se ejecutó (el proveedor no respondió, rechazó por límite de peticiones, o falló la autenticación) y conviene reintentar. Un motivo de la fuente significa que la consulta sí llegó y el portal explicó por qué no hay datos; reintentar no cambia el resultado.
status raíz#| Valor | Significado |
|---|---|
completed | La lectura llegó a su desenlace: se encontró información de al menos una placa (message es null), o el caso no tiene ninguna placa que consultar (message dice cuál vacío es) |
processing | Queda una consulta pendiente: hay placas del expediente cuya consulta sigue en curso o nunca se ejecutó; message dice por qué |
completed no significa "todo salió bien": basta con que exista un registro de alguna placa, tenga infracciones, esté sin adeudos, haya fallado o siga en curso. El detalle de cada placa se lee en el message de su fila.
Cuando el result viene vacío, message es uno de:
message | status | Significado |
|---|---|---|
No se encontraron placas registradas | completed | El caso no tiene placas. Llama a POST /v1/cases/{case_id}/plates |
Las placas registradas no corresponden al VIN del expediente | completed | El caso tiene placas, pero ninguna pertenece al VIN del expediente (p. ej. el recibo cargado es de otro vehículo). Revisa los documentos del caso o el VIN consolidado |
Aún no se ha ejecutado ninguna consulta de infracciones para este caso | processing | Hay placas pero nunca se consultaron. Llama a POST /v1/cases/{case_id}/tickets |
Cambio de contrato (21 de agosto de 2026). Los dos vacíos por ausencia de placas pasan de
processingacompleted: sin placas no hay consulta en vuelo y reintentar devolvía el mismo envelope indefinidamente.statusdice si la lectura llegó a su desenlace, no si hay datos — el motivo del vacío está en elmessage.
| HTTP | Causa |
|---|---|
400 | El case_id no es un UUID válido |
404 | Caso no encontrado o inactivo |
La ausencia de placas o de consultas no es un error: responde 200 con result: [] y el message que lo explica — completed cuando no hay placas que consultar, processing cuando hay placas y falta la consulta.
/v1/cases/{case_id}/tickets#Lanza una consulta de infracciones para todas las placas del caso (placas principales y placas anteriores). La operación es asíncrona: retorna un job_id inmediatamente y los resultados quedan disponibles en GET /v1/cases/{case_id}/tickets a medida que se completan.
Requiere que el caso tenga placas calculadas. Si no las tiene, llama primero a POST /v1/cases/{case_id}/plates.
curl -X POST https://api.nexcar.mx/v1/cases/{case_id}/tickets \
-H "Authorization: Bearer tu_token_jwt"
202 Accepted#{
"job_id": "00000000-0000-0000-0000-000000000002",
"plates": ["ABC123", "XYZ456"],
"status": "pending"
}
Consulta GET /v1/cases/{case_id}/tickets para ver los resultados por placa a medida que se completan.
| HTTP | Causa |
|---|---|
400 | No hay placas calculadas para este caso. Llama a POST /v1/cases/{case_id}/plates primero. |
404 | Caso no encontrado o inactivo |
/v1/cases/{case_id}/invoices#Devuelve un elemento por cada documento de factura (document_type = invoice) del caso, activos e inactivos, ordenados por created_at descendente. Cada elemento trae los datos que el OCR extrajo del documento y el resultado de cuatro validaciones:
| Clave | Qué valida |
|---|---|
validate_invoice | Que el CFDI esté registrado ante el SAT |
consulta_pedimento | El pedimento aduanal del vehículo ante el SAT |
amda_invoice | Si el documento es una factura AMDA y qué datos del vehículo trae |
amis | Historial de pólizas de seguro del vehículo (AMIS) |
Las cuatro claves siempre están presentes (nunca null) y siempre tienen la misma forma:
{ "status": "processing" | "completed", "message": string|null, "result": object|null, "updated_at": string|null }
message y result son excluyentes: si hay result (la validación encontró información), message es null; si no hay result, message explica por qué.
Las validaciones corren en segundo plano al procesar el caso, así que este endpoint puede devolver resultados parciales. No está paginado; devuelve invoices: [] cuando el caso no tiene documentos de factura.
status#status | Significa |
|---|---|
processing | La validación todavía no se ha ejecutado para esa factura. message trae "Consulta en procesamiento" y updated_at es null |
completed | Ya hay respuesta. Cubre tres desenlaces: encontró (viene result), no encontró (viene message) y la consulta falló (viene message con el motivo) |
status describe la información encontrada, no la ejecución interna del job: un job que terminó en error se publica como completed con el motivo en message. Los casos "no encontró" y "falló" se distinguen por el texto de message, no por el status.
curl https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/invoices \
-H "Authorization: Bearer $TOKEN"
200 OK#{
"case_id": "00000000-0000-0000-0000-000000000001",
"invoices": [
{
"consulta_pedimento": {
"status": "completed",
"message": "El vehículo es de procedencia nacional",
"result": null,
"updated_at": "2026-07-30T22:22:52.573318"
},
"amis": {
"status": "completed",
"message": null,
"result": {
"info": [
{
"marca": "VOLKSWAGEN",
"submarca": "JETTA",
"anio_modelo": 2012,
"poliza": "******123",
"cancelable": "SI",
"inicio_vigencia": "2026-04-28",
"fin_vigencia": "2027-04-28"
}
]
},
"updated_at": "2026-07-30T22:23:23.227505"
},
"amda_invoice": {
"status": "processing",
"message": "Consulta en procesamiento",
"result": null,
"updated_at": null
},
"validate_invoice": {
"status": "completed",
"message": null,
"result": {
"claveMensaje": "0",
"codigoValidacion": "fd1700000000.1234567",
"efectoComprobante": "ingreso",
"estadoCFDI": "Vigente",
"estatusCancelacion": "Cancelable con aceptación",
"fechaCertificacion": "2013-03-26T16:05:02",
"fechaEmision": "2013-03-26T15:58:18",
"folioFiscal": "3F1A2B3C-0000-0000-0000-000000000000",
"nombreEmisor": "DISTRIBUIDORA DEMO, S.A. DE C.V.",
"nombreReceptor": "JUAN PEREZ LOPEZ",
"rfcEmisor": "AAA010101AAA",
"rfcPac": "PAC0807172W8",
"rfcReceptor": "BBB020202BBB",
"totalCfdi": "$113,400.00"
},
"updated_at": "2026-07-30T22:22:52.602585+00:00"
},
"data": {
"folio_fiscal": { "db_field": "fiscal_number", "label": "Folio fiscal", "text": "3F1A2B3C-0000-0000-0000-000000000000" },
"rfc_emisor": { "db_field": "issuer_rfc", "label": "RFC emisor", "text": "AAA010101AAA" },
"rfc_receptor": { "db_field": "receiver_rfc", "label": "RFC receptor", "text": "BBB020202BBB" }
},
"updated_at": "2026-07-30T22:22:17.453961+00:00",
"file_id": "00000000-0000-0000-0000-000000000001",
"file_url": "https://…/storage/v1/object/public/vehicles/…/factura.pdf"
}
]
}
200 OK — validaciones aún sin ejecutar#Una factura recién cargada, o una cuyo procesamiento aún no ha corrido, devuelve las cuatro fuentes en processing:
{
"case_id": "00000000-0000-0000-0000-000000000001",
"invoices": [
{
"consulta_pedimento": { "status": "processing", "message": "Consulta en procesamiento", "result": null, "updated_at": null },
"amis": { "status": "processing", "message": "Consulta en procesamiento", "result": null, "updated_at": null },
"amda_invoice": { "status": "processing", "message": "Consulta en procesamiento", "result": null, "updated_at": null },
"validate_invoice": { "status": "processing", "message": "Consulta en procesamiento", "result": null, "updated_at": null },
"data": null,
"updated_at": null,
"file_id": "00000000-0000-0000-0000-000000000002",
"file_url": "https://…/factura_2.pdf"
}
]
}
200 OK — caso sin facturas#{
"case_id": "00000000-0000-0000-0000-000000000001",
"invoices": []
}
| Campo | Tipo | Descripción |
|---|---|---|
case_id | UUID | Identificador del caso / vehículo |
invoices | array | Un elemento por cada documento de factura encontrado en el caso |
invoices[].file_id | UUID | Identificador del archivo de factura |
invoices[].file_url | string | null | URL pública del archivo de factura |
invoices[].data | object | null | Campos OCR sanitizados extraídos de la factura (null si no hay OCR disponible). Cada campo trae db_field, label y text |
invoices[].updated_at | string | null | Última actualización del OCR de esa factura (ISO 8601) |
invoices[].validate_invoice | object | Validación del CFDI ante el SAT |
invoices[].consulta_pedimento | object | Consulta del pedimento aduanal |
invoices[].amda_invoice | object | Consulta AMDA |
invoices[].amis | object | Historial de seguros AMIS. Es del vehículo, así que se repite igual en todas las facturas del caso |
Campos de cada objeto de validación:
| Campo | Tipo | Descripción |
|---|---|---|
status | string | processing o completed (ver tabla arriba) |
message | string | null | Texto del resultado cuando no hay result. Excluyente con result |
result | object | null | Información encontrada. Solo trae las claves con dato: las vacías no se publican |
updated_at | string | null | Fecha del resultado publicado. null mientras status es processing |
| Validación | result cuando encontró | message cuando no |
|---|---|---|
validate_invoice | Respuesta del SAT: estadoCFDI (Vigente / Cancelado), folioFiscal, rfcEmisor, nombreEmisor, rfcReceptor, nombreReceptor, totalCfdi, fechaEmision, estatusCancelacion | "Este comprobante no se encuentra registrado en los controles del Servicio de Administracion Tributaria…" |
consulta_pedimento | Tablas del SAT con datos: vehiculo_importado, situacion_pedimentos, importacion_vehiculos | "El vehículo es de procedencia nacional" (la factura no tiene datos de importación: es un resultado válido) · "No se encontró información" · "Servicio no disponible." (el sitio del SAT no respondió) |
amda_invoice | amda_code y vehicle_details (vin, brand, model, dealer_name, …) | "No se encontró información" · el motivo del proveedor, p. ej. "No se encontraron los indicadores de una Factura AMDA…" · "Hubo un error al procesar la información" |
amis | Lista de pólizas en info o en data según el proceso que generó la consulta: lee ambas claves | "Sin datos" · "No se encontró información" · el motivo del proveedor, p. ej. "Longitud incorrecta (se esperan 17 caracteres)" cuando el VIN del caso es inválido |
validate_invoice y consulta_pedimento se resuelven por factura: la primera se empareja por datos fiscales (folio_fiscal del CFDI, luego el par RFC emisor/receptor) y la segunda por el archivo que originó la consulta y por el número de pedimento del OCR. En un caso con varias facturas, cada una trae su propio resultado.
La respuesta incluye facturas activas e inactivas y no indica cuál es la vigente.
| HTTP | Causa |
|---|---|
400 | id no es un UUID válido |
401 | Falta Authorization: Bearer <token>, o el token es inválido o expiró |
404 | Caso no encontrado |
Estos endpoints validan una credencial de elector (INE/IFE) mediante lectura OCR del frente y reverso de la imagen. La operación es asíncrona: el POST retorna un job_id inmediatamente y el resultado queda disponible vía GET una vez que el procesamiento termina.
| Método | Ruta | Descripción |
|---|---|---|
POST | /documents/ine | Envía una credencial INE para validación |
GET | /documents/ine/{job_id} | Consulta el resultado de la validación |
/documents/ine#Envía una credencial INE para extracción OCR. El proceso corre en segundo plano; usa GET /documents/ine/{job_id} para consultar el resultado.
Cada campo acepta una URL pública o el archivo en base64 (con o sin prefijo data:).
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
front | string | Sí | Frente de la credencial: URL o base64 |
back | string | No | Reverso de la credencial: URL o base64 (mejora la extracción) |
curl -X POST https://api.nexcar.mx/documents/ine \
-H "Authorization: Bearer tu_token_jwt" \
-H "Content-Type: application/json" \
-d '{
"front": "https://tu-storage.example.com/ine-frente.jpg",
"back": "https://tu-storage.example.com/ine-reverso.jpg"
}'
curl -X POST https://api.nexcar.mx/documents/ine \
-H "Authorization: Bearer tu_token_jwt" \
-H "Content-Type: application/json" \
-d '{
"front": "data:image/jpeg;base64,<...>",
"back": "data:image/jpeg;base64,<...>"
}'
202 Accepted#{
"job_id": "00000000-0000-0000-0000-000000000001",
"status": "processing"
}
Consulta GET /documents/ine/{job_id} para obtener el resultado una vez listo.
| HTTP | Código | Causa |
|---|---|---|
400 | MISSING_PARAMETER | front está ausente o vacío |
401 | — | API key inválida o ausente |
/documents/ine/{job_id}#Retorna el resultado de una validación INE previamente enviada.
curl https://api.nexcar.mx/documents/ine/00000000-0000-0000-0000-000000000001 \
-H "Authorization: Bearer tu_token_jwt"
200 OK — completada#{
"status": "completed",
"data": {
"names": "NOMBRE",
"first_last_name": "APELLIDO1",
"second_last_name": "APELLIDO2",
"birth_date": "01/01/1990",
"gender": "HOMBRE",
"curp": "XXXX900101HDFXXX01",
"elector_key": "XXXXXX000000000000",
"state": "CIUDAD DE MEXICO",
"municipality": "ALCALDIA EJEMPLO",
"section": "1234",
"emission": "01",
"validity": "2030",
"cic": "000000000",
"ocr": "000000000000",
"citizen_identifier": "000000000000000000000000000"
}
}
200 OK — en procesamiento#{ "status": "processing", "data": null }
200 OK — con error#{ "status": "error", "data": null }
status#| Valor | Significado |
|---|---|
processing | Validación en curso — reintenta en unos segundos |
completed | Validación completada; data contiene los campos extraídos |
error | La validación falló; data es null |
data)#| Campo | Tipo | Descripción |
|---|---|---|
names | string | Nombre(s) |
first_last_name | string | Primer apellido |
second_last_name | string | Segundo apellido |
birth_date | string | Fecha de nacimiento (DD/MM/YYYY) |
gender | string | Género (HOMBRE / MUJER) |
curp | string | CURP |
elector_key | string | Clave de elector |
state | string | Estado de registro |
municipality | string | Municipio de registro |
locality | string | null | Localidad de registro |
section | string | Sección electoral |
emission | string | Número de emisión |
validity | string | Año hasta el que es válida la credencial |
cic | string | null | Identificador de la credencial |
ocr | string | null | Número OCR de la credencial |
citizen_identifier | string | null | Identificador ciudadano |
type | string | null | Tipo de credencial (p.ej. C, D) |
issue_date | string | null | Fecha de expedición (DD/MM/YYYY) |
expiry_date | string | null | Fecha de caducidad (DD/MM/YYYY) |
street | string | null | Calle del domicilio |
neighborhood | string | null | Colonia |
city | string | null | Ciudad |
Todos los campos en data aparecen únicamente cuando son legibles en el documento. Los campos no detectados en la credencial se omiten de la respuesta.
| HTTP | Código | Causa |
|---|---|---|
404 | NOT_FOUND | job_id no encontrado |
401 | — | API key inválida o ausente |
Valida una credencial de elector (INE/IFE) a partir de su cic y citizen_identifier y confirma si está vigente como medio de identificación. La operación es asíncrona: el POST retorna un job_id inmediatamente y el resultado queda disponible vía GET una vez que la validación termina.
| Método | Ruta | Descripción |
|---|---|---|
POST | /validate/ine | Envía una credencial INE a validar |
GET | /validate/ine/{job_id} | Consulta el resultado de la validación |
/validate/ine#Inicia la validación de una credencial INE. Retorna un job_id para consultar el resultado.
Todos los campos son opcionales, pero debes enviar al menos uno. Qué campos son obligatorios depende del tipo de credencial:
ocr + elector_key + emission_numbercic + ocrcic + citizen_identifier| Campo | Tipo | Descripción |
|---|---|---|
cic | string | CIC impreso en la credencial |
citizen_identifier | string | Identificador del ciudadano de la credencial |
elector_key | string | Clave de elector |
ocr | string | Número OCR de la credencial |
emission_number | string | Número de emisión de la credencial |
curl -X POST https://api.nexcar.mx/validate/ine \
-H "Authorization: Bearer TU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"cic": "000000000",
"citizen_identifier": "000000000"
}'
202 Accepted#{
"job_id": "00000000-0000-0000-0000-000000000001",
"status": "processing"
}
Consulta el resultado con GET /validate/ine/{job_id}.
/validate/ine/{job_id}#Devuelve el estado y el resultado de una validación de INE.
curl https://api.nexcar.mx/validate/ine/00000000-0000-0000-0000-000000000001 \
-H "Authorization: Bearer TU_TOKEN"
200 OK#{
"status": "completed",
"data": {
"status": "OK",
"message": "Esta vigente como medio de identificacion y puede votar",
"validity": "31 de diciembre de 2027",
"emission_year": "2017",
"registration_year": "1996",
"emission_number": "2",
"cic": "000000000",
"elector_key": "XXXXXX00000000X000",
"message_code": "3",
"ocr": "0000000000000",
"federal_district": "00",
"local_district": "00"
}
}
Cuando status es processing o error, data es null.
status#| Valor | Significado |
|---|---|
processing | La validación sigue en curso. Vuelve a consultar en unos segundos. |
completed | La validación terminó. data contiene el resultado. |
error | La validación no pudo completarse. |
| HTTP | Causa |
|---|---|
400 | No se envió ningún campo (se requiere al menos uno) |
404 | Job no encontrado |