Nexcar

Casos

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 acepta x-api-key — la serie /v1/cases resuelve la empresa y el usuario a partir del token. Ver Autenticación.

Endpoints#

MétodoRutaDescripción
GET/v1/casesLista paginada de casos de la empresa autenticada
POST/v1/casesCrea 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}/assignAsigna el caso a un usuario de tu empresa
GET/v1/cases/{case_id}/namesNombres consolidados detectados en los documentos
GET/v1/cases/{case_id}/vinsVIN principal y VINs detectados por documento
GET/v1/cases/{case_id}/platesPlacas detectadas en el caso con datos de vigencia
GET/v1/cases/{case_id}/chain_platesCadena (histórico) de placas del vehículo
POST/v1/cases/{case_id}/chain_platesGenera la cadena de placas del vehículo en background
GET/v1/cases/{case_id}/ownership_chainCadena de propiedad (histórico de dueños) del vehículo
POST/v1/cases/{case_id}/ownership_chainGenera la cadena de propiedad del vehículo en background
GET/v1/cases/{case_id}/repuveDatos de inscripción REPUVE del vehículo
GET/v1/cases/{case_id}/pedimentoResultado más reciente de consulta de pedimento
POST/v1/cases/{case_id}/pedimentoLanza una nueva consulta de pedimento con datos del OCR
GET/v1/cases/{case_id}/rapiResultado más reciente de consulta RAPI (FGJCDMX actividad ilícita)
POST/v1/cases/{case_id}/rapiLanza una consulta RAPI para el VIN principal del caso
GET/v1/cases/{case_id}/renapoResultado más reciente de validación RENAPO (CURP)
POST/v1/cases/{case_id}/renapoLanza validación RENAPO del CURP del caso
GET/v1/cases/{case_id}/transunionResultado más reciente de TransUnion AutoInfo para el caso
POST/v1/cases/{case_id}/transunionLanza una consulta TransUnion AutoInfo para el VIN principal
GET/v1/cases/{case_id}/ticketsInfracciones de todas las placas del caso (solo lectura)
POST/v1/cases/{case_id}/ticketsLanza consulta masiva de infracciones para todas las placas del caso
POST/v1/cases/{case_id}/taxesLanza consulta masiva de tenencias para todas las placas del caso
GET/v1/cases/{case_id}/invoicesFacturas del caso con el resultado de sus cuatro validaciones
GET/v1/cases/{case_id}/metadataDatos de negocio asociados al caso
POST/v1/cases/{case_id}/metadataAgrega una entrada al historial de metadata
POST/v1/cases/{case_id}/processLanza el procesamiento masivo de los documentos
GET/v1/cases/{case_id}/statusEstado del último job de procesamiento

GET /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.

Query parameters#

ParámetroTipoDefaultDescripción
limitinteger20Tamaño de página (máx 100)
offsetinteger0Cursor numérico para paginación
internal_idstring—Filtro por internal_id (coincidencia parcial, insensible a mayúsculas)
vinstring—Filtro por VIN (búsqueda parcial en documentos del caso)
case_typeUUID—Filtro por caso de uso de catálogo (n_vehicles.case_id, coincidencia exacta)

Ejemplos con curl#

# 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"

Respuesta#

{
  "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
  }
}

Referencia de campos#

CampoTipoDescripción
case_idUUIDIdentificador del vehículo / caso
internal_idstringTu identificador de referencia
review_statusstring | nullEstado de revisión actual
use_case_idUUID | nullCaso de uso de catálogo asignado
user_id_added_byUUID | nullUsuario que creó el caso
created_byUUID | nullUsuario atribuido como creador
created_atstringFecha de creación en formato ISO 8601
activebooleantrue = caso activo
pagination.totalintegerTotal de registros que coinciden
pagination.has_morebooleantrue si hay más páginas

Errores comunes#

HTTPCausa
400No se pudo determinar company_id desde el token

POST /v1/cases — Crear caso#

Crea un caso para un vehículo. Puedes adjuntar documentos en la misma llamada o subirlos después.

Cuerpo#

CampoTipoRequeridoDescripción
internal_idstringSíIdentificador del caso en tu sistema. No puede estar vacío.
statusstringSíEstado inicial del caso (p. ej. processing, nuevo).
vehicle_originstringNoNacional (default) o Importado.
initial_statusstringNoEstado inicial alternativo cuando se configuró un catálogo de estatus.
use_caseUUIDNoCaso de uso del expediente cuando aplique catálogo.
metadataobjectNoDatos de negocio adicionales (ver más abajo).
filesarrayNoDocumentos a cargar de inmediato.

Ejemplo con curl#

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"
      }
    ]
  }'

Cuerpo del request#

{
  "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"
    }
  ]
}

Respuestas#

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"
}

Errores comunes#

HTTPCódigoCausa
400VALIDATION_ERRORstatus ausente o internal_id vacío
400DUPLICATE_INTERNAL_IDYa existe un caso con ese internal_id y archivos cargados
422INVALID_STATUSstatus no está dentro del catálogo configurado

GET /v1/cases/{case_id}#

Devuelve el caso y todos sus documentos con su OCR (cuando esté disponible).

Ejemplo con curl#

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.

Respuesta#

{
  "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.

DELETE /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"

POST /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.

Cuerpo#

CampoTipoRequeridoDescripción
user_idstringSí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.

Ejemplo con curl#

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" }'

Respuesta#

{
  "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."
    }
  ]
}

Referencia de campos#

CampoTipoDescripción
case_idUUIDEl caso afectado
assigned_tostringEl identificador que mandaste en user_id, tal cual
assignment_historyarrayHistorial completo, del más antiguo al más reciente. Cada asignación agrega una entrada; ninguna se reemplaza.
assignment_history[].datestringFecha del servidor en UTC, ISO 8601
assignment_history[].userstringNombre del usuario asignado; su correo si no tiene nombre, y un usuario si no tiene ninguno de los dos
assignment_history[].pidstringpid del perfil asignado
assignment_history[].labelstringTexto listo para mostrar en una bitácora

Reglas de pertenencia#

Las dos partes deben pertenecer a la empresa dueña del caso:

  • Quien llama. Si tu token es de otra empresa, la petición no llega al endpoint: se rechaza con 403.
  • Quien es asignado. Se valida contra la empresa del caso. Sin esta regla el caso quedaría a nombre de alguien que no puede abrirlo y desaparecería de todas las bandejas.

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.

Webhook#

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.

Errores comunes#

HTTPCódigoCausa
400VALIDATION_ERRORFalta user_id, viene vacío, o el cuerpo no es un objeto JSON
400VALIDATION_ERROREl usuario indicado no existe
400VALIDATION_ERROREl caso no tiene empresa asociada, así que no hay contra qué validar la asignación
400VALIDATION_ERROREl perfil del usuario indicado no tiene pid, así que no se puede asignar
403FORBIDDENEl usuario a asignar pertenece a otra empresa
403FORBIDDENTu token pertenece a otra empresa que la del caso
404RESOURCE_NOT_FOUNDEl caso no existe

POST /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.

GET /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.

Ejemplo con curl#

curl https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/plates \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta#

{
  "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
    }
  ]
}

Referencia de campos#

CampoTipoDescripción
platestringPlaca normalizada (mayúsculas, sin separadores)
entitystringCódigo de tres letras del estado (MEX, NLE, JAL, …)
document_typestringDocumento de origen: certificate_title, tax_payment, alta_vehicular, vehicle_certificate, vehicle_plate, lumo_checklist o repuve
document_datestringFecha asociada al documento de origen (DD/MM/YYYY cuando esté disponible)
nivstring | nullNúmero de identificación vehicular (17 caracteres cuando está disponible; parcial en otros casos)
motor_numberstring | nullNúmero de motor del documento de origen
owner_namestring | nullPropietario declarado en el documento de origen
plate_statusstring | nullEstatus actual de la placa según el portal: Vigente, Vencida o Inactiva
plate_valid_fromstring | nullInicio de vigencia de la placa actual (DD/MM/YYYY)
plate_valid_untilstring | nullFin de vigencia de la placa actual (DD/MM/YYYY)
previous_platestring | nullPlaca anterior, cuando existió una previa a la actual
previous_plate_lookup_statusstring | nullEstado de la consulta — ver tabla

Valores de previous_plate_lookup_status#

ValorSignificado
nullLa 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.

Errores comunes#

HTTPCausa
404Caso no encontrado, inactivo, o aún no se han calculado las placas para este caso

GET /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.

Ejemplo con curl#

curl https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/chain_plates \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta#

{
  "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
}

Estados#

statusSignificado
completedLa cadena ya está generada — se devuelve en summary + chain
processingLa cadena se está generando en background — vuelve a llamar en unos segundos
pendingEl 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.

Referencia de campos#

CampoTipoDescripción
nivstring | nullVIN del vehículo (del VIN consolidado del caso)
summary.plate_countnumberNúmero de placas en la cadena
summary.current_platestring | nullPlaca vigente
summary.chain_scopestringAlcance de la cadena (edomex_only)
chain[].sequence_indexnumberOrden cronológico (0 = más antigua)
chain[].platestringPlaca del tramo
chain[].period_start / period_endstring | nullVigencia del tramo (YYYY-MM-DD)
chain[].is_currentbooleanSi es la placa vigente
chain[].predecessor_platestring | nullPlaca inmediatamente anterior
chain[].documentsarrayDocumentos que sustentan el tramo

Errores comunes#

HTTPCausa
404Caso no encontrado o inactivo

POST /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).

Ejemplo con curl#

curl -X POST https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/chain_plates \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta#

{
  "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."
}

Errores comunes#

HTTPCausa
400case_id no es un UUID válido, o se enviaron parámetros en el cuerpo
404Caso no encontrado o inactivo

GET /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.

Ejemplo con curl#

curl https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/ownership_chain \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta#

{
  "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
}

Estados#

statusSignificado
completedLa cadena ya está generada — summary + chain + gaps (chain: [] con completed = sin transmisiones rastreables, resultado vacío legítimo).
processingSe está generando en background (la cadena, o la consolidación de nombres de la que depende). Vuelve a llamar en unos segundos.
pendingEl 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.

Errores comunes#

HTTPCausa
404Caso no encontrado o inactivo

POST /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.

Ejemplo con curl#

curl -X POST https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/ownership_chain \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta#

{
  "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."
}

Errores comunes#

HTTPCausa
400case_id no es un UUID válido, o se enviaron parámetros en el cuerpo
404Caso no encontrado o inactivo

GET /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.

Ejemplo con curl#

curl https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/repuve \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta#

{
  "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"
}

Referencia de campos#

CampoTipoDescripción
codigostringok — datos de REPUVE disponibles. error — todos los servicios fallaron. processing — job aún en curso.
infoobject | nullDatos de inscripción del vehículo en REPUVE. null cuando el vehículo no está inscrito o el job no ha completado.
info.nivstringNúmero de identificación vehicular (NIV/VIN)
info.placastring | nullPlaca registrada en REPUVE
info.marcastringMarca
info.modelostringModelo
info.anio_modelointegerAño modelo
info.entidad_emplacadostring | nullEstado de emplacamiento
info.fecha_inscripcionstring | nullFecha de inscripción en REPUVE
info.fecha_actualizacionstring | nullFecha de última actualización en REPUVE
info.reporte_roboarrayReportes de robo de las fuentes FGJ y OCRA
info.robo_usa_canobjectEstado de reporte de robo en USA/Canadá
info.aviso_judicialobjectEstado de aviso judicial
job_idUUIDIdentificador interno del job
job_statusstringcompleted, error, processing o pending

Errores comunes#

HTTPCausa
404Caso no encontrado, inactivo, o no se ha realizado ninguna consulta REPUVE para este caso

GET /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.

Ejemplo con curl#

curl https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/pedimento \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta#

{
  "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" }
  }
}

Errores comunes#

HTTPCausa
404Caso no encontrado, inactivo, o no se ha realizado ninguna consulta de pedimento. Llama a POST /v1/cases/{id}/pedimento primero.

GET /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 de processing a completed. No queda ninguna consulta en vuelo, así que reintentar devolvía el mismo envelope indefinidamente; el message es el que explica el vacío. Si tu integración reintenta cuando ve processing, lee el message para saber qué falta. Sigue en processing el 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 un POST.

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.

Bloque 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:

CampoSignifica
fiscal_yearEl ejercicio de la ventana
plate_numberLa placa principal
stateEntidad de la placa (abreviada)
documentCelda {status, message}: si hay un recibo de tenencia (tax_payment) de esa placa que declara ese ejercicio
sourceCelda {status, message}: qué dice el portal de la entidad sobre ese ejercicio
payment_dateDel recibo, pareado al ejercicio; null si no hay recibo o no se pudo parear
totalEl del portal cuando reporta el ejercicio con importe; si no, el del recibo

Celda document:

statusmessageCuá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.

statusmessageCuándo
warning"Con adeudo"El portal reporta ese ejercicio
success"Sin adeudo"El portal respondió pero sin ese ejercicio
failedMensaje del portal tal cualMotivo ú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.

Bloque 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.

CampoSignifica
plate_numberLa placa
stateEntidad de la placa (abreviada); si no la trae, la del recibo
fiscal_yearEl ejercicio, o null cuando ninguna de las dos fuentes reportó nada de esa placa
statusCelda {status, message}: lo que dice el portal de ese ejercicio
payment_dateDel recibo de esa placa, pareado al ejercicio
totalEl 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:

statusmessageCuándo
success"Sin adeudo"El portal no reporta adeudo para ese ejercicio
warning"Con adeudo"El portal reporta adeudo para ese ejercicio
failedEl motivo del portal, o un mensaje genérico saneadoError 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.

Ejemplo con curl#

curl https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/taxes \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta#

{
  "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": [] }
}

POST /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).

Ejemplo con curl#

curl -X POST https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/taxes \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta 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: [].

Errores comunes#

HTTPCausa
400No se encontraron placas para este caso. Llama a POST /v1/cases/{id}/plates primero.
404Caso no encontrado o inactivo

POST /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.

Ejemplo con curl#

curl -X POST https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/pedimento \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta 202 Accepted#

{ "job_id": "00000000-0000-0000-0000-000000000004", "status": "pending" }

Errores comunes#

HTTPCausa
400No se encontró VIN principal, o faltan campos OCR requeridos (aduana, ano_vehiculo)
404Caso no encontrado o inactivo

GET /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.

Ejemplo con curl#

curl https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/rapi \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta#

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).

Errores comunes#

HTTPCausa
404Caso no encontrado o inactivo, o no existe ningún job del caso ni consulta RAPI. Llama a POST /v1/cases/{id}/rapi primero.

POST /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.

Ejemplo con curl#

curl -X POST https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/rapi \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta 202 Accepted#

{ "job_id": "00000000-0000-0000-0000-000000000004", "vin": "00000000000000000", "status": "pending" }

Errores comunes#

HTTPCausa
400No se encontró VIN principal. Procesa los documentos con POST /v1/cases/{id}/process primero.
404Caso no encontrado o inactivo

GET /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.

Ejemplo con curl#

curl https://api.nexcar.mx/v1/cases/{case_id}/renapo \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta 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.

Errores comunes#

HTTPCausa
404Caso no encontrado, inactivo, o no se ha ejecutado ninguna consulta RENAPO. Llama a POST /v1/cases/{case_id}/renapo primero.

POST /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.

Ejemplo con curl#

curl -X POST https://api.nexcar.mx/v1/cases/{case_id}/renapo \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta 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.

Errores comunes#

HTTPCausa
400No hay CURP disponible en los documentos del caso. Procesa los documentos con POST /v1/cases/{case_id}/process primero.
404Caso no encontrado o inactivo

GET /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.

Ejemplo con curl#

curl https://api.nexcar.mx/v1/cases/{case_id}/transunion \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta 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.

Errores comunes#

HTTPCausa
404Caso no encontrado, inactivo, o no se ha ejecutado ninguna consulta TransUnion. Llama a POST /v1/cases/{case_id}/transunion primero.

POST /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.

Ejemplo con curl#

curl -X POST https://api.nexcar.mx/v1/cases/{case_id}/transunion \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta 202 Accepted#

{ "job_id": "00000000-0000-0000-0000-000000000002", "vin": "00000000000000000", "status": "pending" }

Errores comunes#

HTTPCausa
400No se encontró VIN principal. Procesa los documentos con POST /v1/cases/{case_id}/process primero.
404Caso no encontrado o inactivo

GET /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.

Respuesta 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:

CampoDescripción
plate_numberPlaca a la que pertenece la fila
stateEntidad donde se consultó la placa (null si no se conoce)
ticket_dateFecha de la infracción
amountMonto tal como lo reporta la fuente
status"success", "warning", "processing" o "failed" (ver tabla abajo)
messageTexto 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":

Casostatusmessage
Infracción con estatus PAGADA en la fuentesuccessPagada
Infracción con estatus NO PAGADA en la fuentewarningNo Pagada
Infracción con cualquier otro estatus (PENDIENTE, …)warningEl texto tal como lo reporta la fuente
Placa sin infraccionessuccessPlaca sin adeudos
Consulta en cursoprocessingSe está procesando la información
Consulta no se pudo ejecutar (fallo de proceso o del proveedor)failedHubo un problema al extraer la información
Placa nunca consultadafailedAún no se ha consultado esta placa
La fuente respondió con un motivo propio — p. ej. Entidad aún sin coberturafailed(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.

Valores de status raíz#

ValorSignificado
completedLa 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)
processingQueda 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:

messagestatusSignificado
No se encontraron placas registradascompletedEl caso no tiene placas. Llama a POST /v1/cases/{case_id}/plates
Las placas registradas no corresponden al VIN del expedientecompletedEl 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 casoprocessingHay 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 processing a completed: sin placas no hay consulta en vuelo y reintentar devolvía el mismo envelope indefinidamente. status dice si la lectura llegó a su desenlace, no si hay datos — el motivo del vacío está en el message.

Errores comunes#

HTTPCausa
400El case_id no es un UUID válido
404Caso 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.

POST /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.

Ejemplo con curl#

curl -X POST https://api.nexcar.mx/v1/cases/{case_id}/tickets \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta 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.

Errores comunes#

HTTPCausa
400No hay placas calculadas para este caso. Llama a POST /v1/cases/{case_id}/plates primero.
404Caso no encontrado o inactivo

GET /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:

ClaveQué valida
validate_invoiceQue el CFDI esté registrado ante el SAT
consulta_pedimentoEl pedimento aduanal del vehículo ante el SAT
amda_invoiceSi el documento es una factura AMDA y qué datos del vehículo trae
amisHistorial 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.

Valores de status#

statusSignifica
processingLa validación todavía no se ha ejecutado para esa factura. message trae "Consulta en procesamiento" y updated_at es null
completedYa 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.

Ejemplo con curl#

curl https://api.nexcar.mx/v1/cases/11111111-2222-3333-4444-555555555555/invoices \
  -H "Authorization: Bearer $TOKEN"

Respuesta 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"
    }
  ]
}

Respuesta 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"
    }
  ]
}

Respuesta 200 OK — caso sin facturas#

{
  "case_id": "00000000-0000-0000-0000-000000000001",
  "invoices": []
}

Referencia de campos#

CampoTipoDescripción
case_idUUIDIdentificador del caso / vehículo
invoicesarrayUn elemento por cada documento de factura encontrado en el caso
invoices[].file_idUUIDIdentificador del archivo de factura
invoices[].file_urlstring | nullURL pública del archivo de factura
invoices[].dataobject | nullCampos OCR sanitizados extraídos de la factura (null si no hay OCR disponible). Cada campo trae db_field, label y text
invoices[].updated_atstring | nullÚltima actualización del OCR de esa factura (ISO 8601)
invoices[].validate_invoiceobjectValidación del CFDI ante el SAT
invoices[].consulta_pedimentoobjectConsulta del pedimento aduanal
invoices[].amda_invoiceobjectConsulta AMDA
invoices[].amisobjectHistorial 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:

CampoTipoDescripción
statusstringprocessing o completed (ver tabla arriba)
messagestring | nullTexto del resultado cuando no hay result. Excluyente con result
resultobject | nullInformación encontrada. Solo trae las claves con dato: las vacías no se publican
updated_atstring | nullFecha del resultado publicado. null mientras status es processing

Contenido por validación#

Validaciónresult cuando encontrómessage cuando no
validate_invoiceRespuesta 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_pedimentoTablas 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_invoiceamda_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"
amisLista 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.

Errores comunes#

HTTPCausa
400id no es un UUID válido
401Falta Authorization: Bearer <token>, o el token es inválido o expiró
404Caso no encontrado

Validación de credencial INE#

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étodoRutaDescripción
POST/documents/ineEnvía una credencial INE para validación
GET/documents/ine/{job_id}Consulta el resultado de la validación

POST /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.

Cuerpo#

Cada campo acepta una URL pública o el archivo en base64 (con o sin prefijo data:).

CampoTipoRequeridoDescripción
frontstringSíFrente de la credencial: URL o base64
backstringNoReverso de la credencial: URL o base64 (mejora la extracción)

Ejemplo con curl (URL)#

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"
  }'

Ejemplo con curl (base64)#

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,<...>"
  }'

Respuesta 202 Accepted#

{
  "job_id": "00000000-0000-0000-0000-000000000001",
  "status": "processing"
}

Consulta GET /documents/ine/{job_id} para obtener el resultado una vez listo.

Errores comunes#

HTTPCódigoCausa
400MISSING_PARAMETERfront está ausente o vacío
401—API key inválida o ausente

GET /documents/ine/{job_id}#

Retorna el resultado de una validación INE previamente enviada.

Ejemplo con curl#

curl https://api.nexcar.mx/documents/ine/00000000-0000-0000-0000-000000000001 \
  -H "Authorization: Bearer tu_token_jwt"

Respuesta 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"
  }
}

Respuesta 200 OK — en procesamiento#

{ "status": "processing", "data": null }

Respuesta 200 OK — con error#

{ "status": "error", "data": null }

Valores de status#

ValorSignificado
processingValidación en curso — reintenta en unos segundos
completedValidación completada; data contiene los campos extraídos
errorLa validación falló; data es null

Referencia de campos (data)#

CampoTipoDescripción
namesstringNombre(s)
first_last_namestringPrimer apellido
second_last_namestringSegundo apellido
birth_datestringFecha de nacimiento (DD/MM/YYYY)
genderstringGénero (HOMBRE / MUJER)
curpstringCURP
elector_keystringClave de elector
statestringEstado de registro
municipalitystringMunicipio de registro
localitystring | nullLocalidad de registro
sectionstringSección electoral
emissionstringNúmero de emisión
validitystringAño hasta el que es válida la credencial
cicstring | nullIdentificador de la credencial
ocrstring | nullNúmero OCR de la credencial
citizen_identifierstring | nullIdentificador ciudadano
typestring | nullTipo de credencial (p.ej. C, D)
issue_datestring | nullFecha de expedición (DD/MM/YYYY)
expiry_datestring | nullFecha de caducidad (DD/MM/YYYY)
streetstring | nullCalle del domicilio
neighborhoodstring | nullColonia
citystring | nullCiudad

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.

Errores comunes#

HTTPCódigoCausa
404NOT_FOUNDjob_id no encontrado
401—API key inválida o ausente

Validación de vigencia de credencial INE#

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étodoRutaDescripción
POST/validate/ineEnvía una credencial INE a validar
GET/validate/ine/{job_id}Consulta el resultado de la validación

POST /validate/ine#

Inicia la validación de una credencial INE. Retorna un job_id para consultar el resultado.

Cuerpo#

Todos los campos son opcionales, pero debes enviar al menos uno. Qué campos son obligatorios depende del tipo de credencial:

  • Tipo C: ocr + elector_key + emission_number
  • Tipo D: cic + ocr
  • Tipos E/F/G/H: cic + citizen_identifier
CampoTipoDescripción
cicstringCIC impreso en la credencial
citizen_identifierstringIdentificador del ciudadano de la credencial
elector_keystringClave de elector
ocrstringNúmero OCR de la credencial
emission_numberstringNúmero de emisión de la credencial

Ejemplo con curl#

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"
  }'

Respuesta 202 Accepted#

{
  "job_id": "00000000-0000-0000-0000-000000000001",
  "status": "processing"
}

Consulta el resultado con GET /validate/ine/{job_id}.

GET /validate/ine/{job_id}#

Devuelve el estado y el resultado de una validación de INE.

Ejemplo con curl#

curl https://api.nexcar.mx/validate/ine/00000000-0000-0000-0000-000000000001 \
  -H "Authorization: Bearer TU_TOKEN"

Respuesta 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.

Valores de status#

ValorSignificado
processingLa validación sigue en curso. Vuelve a consultar en unos segundos.
completedLa validación terminó. data contiene el resultado.
errorLa validación no pudo completarse.

Errores comunes#

HTTPCausa
400No se envió ningún campo (se requiere al menos uno)
404Job no encontrado