Intro Auth Base URL POST /users POST /tramites Documentos GET /tramites Pago Webhooks Errores Limite Flujo Contacto

Introduccion

CertiVeh Partner API · Integra CertiVeh en tu aplicacion para que tus usuarios obtengan su certificado UPME sin salir de tu plataforma.

Esta API REST permite crear usuarios, iniciar tramites de certificacion UPME, subir documentos, procesar pagos y consultar el estado de cada tramite de forma programatica.

i Flujo tipico: Tu plataforma recopila los datos del usuario y su vehiculo, los envia a la API, sube los documentos, y procesa el pago via Wompi. Desde ese momento, CertiVeh gestiona todo el tramite ante la UPME de forma automatizada. Tu plataforma puede consultar el estado en cualquier momento via polling o recibir notificaciones via webhook.

Autenticacion

Todas las solicitudes requieren el header X-API-Key con tu clave de partner.

Header
X-API-Key: pk_live_xxxxxxxxxxxxx
i Contacta contacto@certiveh.co para solicitar tu API key.

Base URL

Produccion
https://ykolfdgnlaxahtbuurgj.supabase.co/functions/v1/partner-api

POST /users

Registra un nuevo usuario asociado a tu cuenta de partner.

Cuerpo de la solicitud · Persona Natural

CampoTipoDescripcion
emailrequiredstringEmail del usuario
phoneoptionalstringTelefono formato E.164 (ej: +573001234567)
person_typerequiredstring"natural" o "juridica"
first_namesrequiredstringNombres
last_namesrequiredstringApellidos
cedula_numberrequiredstringNumero de cedula (solo digitos)
date_of_birthoptionalstringFecha nacimiento AAAA-MM-DD
expedition_dateoptionalstringFecha expedicion cedula AAAA-MM-DD
ciiu_codeoptionalstringCodigo CIIU 4 digitos
departmentrequiredstringDepartamento (ej: "ANTIOQUIA")
municipalityrequiredstringMunicipio (ej: "MEDELLIN")
addressrequiredstringDireccion de residencia

Campos adicionales · Persona Juridica

CampoTipoDescripcion
company_namerequiredstringRazon social
nitrequiredstringNIT sin digito verificacion (9 digitos)
nit_dvoptionalstringDigito de verificacion (1 digito)
legal_rep_namerequiredstringNombre representante legal
legal_rep_idrequiredstringCedula representante legal
company_addressoptionalstringDireccion empresa

Ejemplo de solicitud

cURL
curl -X POST \
  https://ykolfdgnlaxahtbuurgj.supabase.co/functions/v1/partner-api/users \
  -H "X-API-Key: pk_live_xxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "usuario@ejemplo.com",
    "phone": "+573001234567",
    "person_type": "natural",
    "first_names": "JUAN CARLOS",
    "last_names": "GARCIA LOPEZ",
    "cedula_number": "1020304050",
    "date_of_birth": "1990-05-15",
    "expedition_date": "2010-03-20",
    "ciiu_code": "4511",
    "department": "CUNDINAMARCA",
    "municipality": "BOGOTA D.C.",
    "address": "Calle 100 #15-20 Apto 501"
  }'

Respuesta 201

JSON
{
  "user_id": "uuid-del-usuario",
  "status": "created"
}
i Idempotente: Si el email ya existe en CertiVeh, la API retorna el user_id existente y actualiza el perfil con los datos enviados. No se crea un usuario duplicado. Esto permite reintentos seguros.

POST /tramites

Crea un tramite de certificacion UPME con los datos del vehiculo. Retorna el desglose de costos.

Cuerpo de la solicitud

CampoTipoDescripcion
user_idrequiredstringUUID del usuario (obtenido de POST /users)
platerequiredstringPlaca, formato ABC123 o ABC12D (3 letras + 2 digitos + 1 alfanumerico)
vinrequiredstringVIN (exactamente 17 caracteres, no puede contener I, O, Q)
brandrequiredstringMarca (ej: "KIA")
linerequiredstringLinea/modelo (ej: "NIRO DESIRE")
yearrequirednumberAno del modelo
engine_numberoptionalstringNumero de motor (no aplica para electricos puros)
displacement_kwoptionalstringPotencia en kW (ej: "150")
propulsion_typerequiredstring"Electrico" o "Hibrido"
owner_namerequiredstringNombre propietario registrado
owner_idrequiredstringCedula/NIT propietario
purchase_value_coprequirednumberValor del vehiculo en COP antes de IVA (minimo 1.000.000)
purchase_daterequiredstringFecha compra AAAA-MM-DD
dealer_namerequiredstringNombre concesionario
invoice_numberrequiredstringNumero factura
buyer_namerequiredstringNombre comprador en factura
person_typeoptionalstring"natural" o "juridica". Default: "natural". Debe coincidir con el tipo usado en POST /users.

Ejemplo de solicitud

cURL
curl -X POST \
  https://ykolfdgnlaxahtbuurgj.supabase.co/functions/v1/partner-api/tramites \
  -H "X-API-Key: pk_live_xxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "uuid-del-usuario",
    "plate": "QMX060",
    "vin": "KNACP81EGT5328961",
    "brand": "KIA",
    "line": "NIRO DESIRE",
    "year": 2025,
    "propulsion_type": "Hibrido",
    "owner_name": "JUAN CARLOS GARCIA LOPEZ",
    "owner_id": "1020304050",
    "purchase_value_cop": 116805309,
    "purchase_date": "2025-08-10",
    "dealer_name": "KIA MOTORS BOGOTA",
    "invoice_number": "FV-2025-001234",
    "buyer_name": "JUAN CARLOS GARCIA LOPEZ"
  }'

Respuesta 201

JSON
{
  "case_id": "uuid-del-tramite",
  "amount_cop": 1415800,
  "amount_cents": 141580000,
  "breakdown": {
    "costo_upme": 701812,
    "honorarios": 599990,
    "iva": 113998,
    "discount": 0,
    "total": 1415800
  }
}

POST /tramites/{'{'+'case_id}'}/documents

Sube documentos requeridos. Cada documento se procesa automaticamente con IA.

! Content-Type debe ser multipart/form-data. Archivos soportados: JPG, PNG o PDF, max 10 MB.

Campos del formulario

CampoTipoDescripcion
typerequiredstringTipo de documento (ver tabla abajo)
filerequiredfileArchivo (JPG, PNG o PDF, max 10MB)

Tipos de documento

Valor de typeDescripcion
cedula-frenteCedula ciudadania (frente)
cedula-reversoCedula ciudadania (reverso)
rutRUT (persona natural)
tarjeta-propiedad-frenteTarjeta propiedad vehiculo (frente)
tarjeta-propiedad-reversoTarjeta propiedad vehiculo (reverso)
facturaFactura compra vehiculo
i Documentos obligatorios: Para que el tramite avance despues del pago, se necesitan minimo 5 documentos: cedula-frente, cedula-reverso, tarjeta-propiedad-frente, tarjeta-propiedad-reverso y factura. El rut es opcional pero recomendado.

Ejemplo de solicitud

cURL
curl -X POST \
  https://ykolfdgnlaxahtbuurgj.supabase.co/functions/v1/partner-api/tramites/uuid-del-tramite/documents \
  -H "X-API-Key: pk_live_xxxxxxxxxxxxx" \
  -F "type=factura" \
  -F "file=@/path/to/factura.pdf"

Respuesta 200

JSON
// Documentos del vehiculo (factura, tarjeta-propiedad-*)
{
  "case_id": "uuid",
  "type": "factura",
  "ocr_status": "pending"
}

// Documentos personales (cedula-frente, cedula-reverso, rut)
{
  "document_id": "uuid",
  "type": "cedula-frente",
  "ocr_status": "pending"
}
i Procesamiento OCR asincrono: Cada documento se procesa automaticamente con IA para extraer datos. El campo ocr_status inicia en "pending" y cambia a "done" cuando la extraccion finaliza (normalmente 5-15 segundos). Puedes verificar el estado consultando GET /tramites/:id y revisando el array documents.

GET /tramites/{'{'+'case_id}'}

Retorna el estado actual y detalles de un tramite.

Ejemplo de solicitud

cURL
curl -X GET \
  https://ykolfdgnlaxahtbuurgj.supabase.co/functions/v1/partner-api/tramites/uuid-del-tramite \
  -H "X-API-Key: pk_live_xxxxxxxxxxxxx"

Respuesta 200

JSON
{
  "case_id": "uuid",
  "status": "IN_PROGRESS",
  "step": 5,          // 1-7
  "progress_pct": 67,   // 0-100, basado en 7 pasos
  "paid_at": "2026-05-20T...",
  "created_at": "2026-05-15T...",
  "updated_at": "2026-05-20T...",
  "vehicle": {
    "brand": "KIA",
    "line": "NIRO DESIRE",
    "year": 2025,
    "plate": "QMX060",
    "vin": "KNACP81EGT5328961",
    "propulsion_type": "Hibrido",
    "purchase_value_cop": 116805309
  },
  "documents": [
    { "type": "factura", "ocr_status": "done" },
    { "type": "tarjeta-propiedad-frente", "ocr_status": "done" }
  ],
  "payment": {
    "status": "APPROVED",
    "amount_cents": 141580000,
    "reference": "CERTIVEH-xxx-xxx",
    "created_at": "2026-05-20T14:00:00Z"
  }
}

Pasos del pipeline (1–7)

PasoEtapaStatus en DB
1En borradorDRAFT
2Solicitud enviadaDOCUMENT_REVIEW
3Registro en UPMEIN_PROGRESS (UPME_REGISTER)
4Esperando ventana UPMEIN_PROGRESS (WAITING_WINDOW)
5Tramite en UPMEIN_PROGRESS (FILL_TRAMITE)
6Espera de certificadoFILED, APPROVED, o REJECTED
7Certificado emitidoCOMPLETED

Estados del tramite

StatusDescripcion
DRAFTTramite creado, pendiente de pago (step 1)
DOCUMENT_REVIEWPago recibido, documentos en revision (step 2)
IN_PROGRESSEn tramite ante la UPME (steps 3–5)
FILEDSolicitud de certificado enviada a UPME (step 6)
APPROVEDUPME aprobo la solicitud (step 6)
ACTION_REQUIREDSe necesita una accion del usuario (se resuelve al step donde estaba)
COMPLETEDCertificado emitido (step 7)
REJECTEDSolicitud rechazada por la UPME (step 6)

POST /tramites/{'{'+'case_id}'}/payment

Inicializa una sesion de pago y retorna los datos de integracion con Wompi.

Ejemplo de solicitud

cURL
curl -X POST \
  https://ykolfdgnlaxahtbuurgj.supabase.co/functions/v1/partner-api/tramites/uuid-del-tramite/payment \
  -H "X-API-Key: pk_live_xxxxxxxxxxxxx"

Respuesta 200

JSON
{
  "reference": "CERTIVEH-xxx-xxx",
  "amount_cents": 141580000,
  "amount_cop": 1415800,
  "currency": "COP",
  "public_key": "pub_prod_xxx",
  "signature": "sha256-hash",
  "redirect_url": "https://portal.certiveh.co/tramite/confirmacion?ref=xxx"
}

Integracion Widget Wompi

Usa los valores de la respuesta para renderizar el boton de pago de Wompi:

HTML
<script src="https://checkout.wompi.co/widget.js"
  data-render="button"
  data-public-key="{'{'+'public_key}'}"
  data-currency="{'{'+'currency}'}"
  data-amount-in-cents="{'{'+'amount_cents}'}"
  data-reference="{'{'+'reference}'}"
  data-redirect-url="{'{'+'redirect_url}'}"
  data-signature:integrity="{'{'+'signature}'}">
</script>
i Despues del pago: Cuando el usuario completa el pago en Wompi, CertiVeh recibe un webhook automatico de Wompi y cambia el estado del tramite de DRAFT a DOCUMENT_REVIEW. No necesitas hacer nada adicional. Tu plataforma puede confirmar el pago consultando GET /tramites/:id y verificando que payment.status sea "APPROVED" y que paid_at no sea null.
! redirect_url: Despues del pago, Wompi redirige al usuario a portal.certiveh.co. Si necesitas redirigir a una URL propia de tu plataforma, contacta al equipo para configurarlo.

POST /tramites/{'{'+'case_id}'}/simulate-payment

Simula la aprobacion de un pago sin realizar un cobro real. Solo disponible en modo sandbox.

! Solo sandbox: Este endpoint solo funciona con tu API key de sandbox (sk_sandbox_xxx). Retorna 403 si se usa con la API key de produccion.

Ejemplo de solicitud

cURL
curl -X POST \
  https://ykolfdgnlaxahtbuurgj.supabase.co/functions/v1/partner-api/tramites/uuid-del-tramite/simulate-payment \
  -H "X-API-Key: sk_sandbox_xxxxxxxxxxxxx"

Respuesta 200

JSON
{
  "case_id": "uuid-del-tramite",
  "payment_id": "uuid-del-pago",
  "status": "APPROVED",
  "case_status": "DOCUMENT_REVIEW",
  "sandbox": true,
  "message": "Payment simulated successfully. No real charge was made."
}
i Requisito previo: Debes haber llamado POST /tramites/:id/payment antes para crear el registro de pago PENDING. Este endpoint toma ese pago pendiente y lo marca como APPROVED, avanzando el caso a DOCUMENT_REVIEW. Si tienes un webhook URL configurado, recibiras la notificacion tramite.payment_confirmed con sandbox: true.

Webhooks

CertiVeh envia notificaciones HTTP POST a tu webhook URL cuando el estado de un tramite cambia. Proporciona tu webhook URL al solicitar tu API key.

Payload

JSON · POST a tu webhook URL
{
  "event": "tramite.status_changed",
  "case_id": "uuid",
  "status": "DOCUMENT_REVIEW",
  "timestamp": "2026-05-20T15:30:00Z"
}

Transiciones de estado tipicas

TransicionEventoSignificado
DRAFT → DOCUMENT_REVIEWPago recibidoWompi confirmo el pago exitosamente
DOCUMENT_REVIEW → IN_PROGRESSDocumentos aprobadosCertiVeh inicio el tramite ante la UPME
IN_PROGRESS → FILEDSolicitud radicadaSe radico la solicitud en el portal UPME
FILED → APPROVEDSolicitud aprobadaLa UPME aprobo la solicitud, certificado en emision
APPROVED → COMPLETEDCertificado emitidoEl certificado UPME fue emitido y esta disponible
* → ACTION_REQUIREDAccion requeridaEl usuario debe corregir algo (ej: documento ilegible)
FILED → REJECTEDSolicitud rechazadaLa UPME rechazo la solicitud
! Recomendacion: Aunque los webhooks notifican los cambios de estado, te recomendamos implementar un polling periodico con GET /tramites/:id como respaldo en caso de que un webhook falle.

Errores

Todas las respuestas de error siguen un formato consistente:

Respuesta de error
{
  "error": "Description"
}

Codigos HTTP


Limite de tasa

Todos los endpoints estan limitados a 100 solicitudes por minuto por API key.

Header de respuestaDescripcion
X-RateLimit-LimitMaximo de solicitudes por minuto (100)
X-RateLimit-RemainingSolicitudes restantes en la ventana actual

Cuando se excede el limite, la API retorna 429 Too Many Requests. Espera a que la ventana se reinicie antes de reintentar.


Seguridad

Todas las solicitudes a la API se registran automaticamente incluyendo direccion IP, user-agent y codigo de respuesta para auditoria y seguridad.


Descuentos de partner

Los precios retornados por POST /tramites y POST /tramites/:id/payment aplican automaticamente cualquier descuento configurado para tu cuenta de partner. El campo breakdown.discount refleja el monto del descuento aplicado. No se necesitan parametros adicionales.


Ambiente de pruebas (Sandbox)

CertiVeh provee un ambiente de sandbox completo para que puedas desarrollar y probar tu integracion sin generar cobros reales, facturas, ni emails.

Como funciona

AspectoProduccionSandbox
API Keysk_live_xxxsk_sandbox_xxx
Cobros realesSi (Wompi produccion)No (Wompi sandbox o simulado)
Facturas AlegraSiNo
Emails / WhatsAppSiNo
Emision segurosSiNo
OCR documentosSiSi (para testear)
Webhooks al partnerSiSi (con sandbox: true)
DatosBase de datos principalMisma base, marcados sandbox=true
Header de respuesta-X-Sandbox: true

Flujo tipico de prueba

  1. Usa tu API key sandbox X-API-Key: sk_sandbox_xxx · Todos los endpoints funcionan igual, pero la data se marca como sandbox.
  2. Crea usuario y tramite POST /users y POST /tramites · Funcionan identico a produccion. Las respuestas incluyen "sandbox": true.
  3. Sube documentos POST /tramites/:id/documents · El OCR se ejecuta normalmente para que puedas validar la extraccion de datos.
  4. Simula el pago POST /tramites/:id/payment para crear el pago, luego POST /tramites/:id/simulate-payment para aprobar instantaneamente sin Wompi.
  5. Recibe el webhook Tu endpoint recibe tramite.payment_confirmed con sandbox: true. Valida tu implementacion.
i Wompi sandbox: Si prefieres probar con el widget real de Wompi (tarjetas de prueba), el endpoint POST /tramites/:id/payment en sandbox retorna la llave publica de Wompi sandbox automaticamente. Usa las tarjetas de prueba de Wompi para simular pagos.

Flujo de integracion

Integracion tipica de punta a punta en 6 pasos:

  1. Crear usuario POST /users · Registra al usuario con sus datos personales. Si el email ya existe, retorna el user_id existente.
  2. Crear tramite con datos del vehiculo POST /tramites · Envia los datos del vehiculo y recibe el desglose de costos. El tramite se crea en estado DRAFT.
  3. Subir documentos POST /tramites/:id/documents · Sube cedula (frente y reverso), tarjeta de propiedad (frente y reverso) y factura. Cada documento se procesa con OCR automaticamente. El orden no importa.
  4. Iniciar pago POST /tramites/:id/payment · Obtiene los parametros para renderizar el widget de Wompi. Cuando el usuario paga, el tramite cambia automaticamente a DOCUMENT_REVIEW.
  5. Consultar estado GET /tramites/:id · Consulta el progreso del tramite periodicamente. Usa status para el estado general y step (1-7) para el progreso detallado.
  6. Recibir webhooks Tu endpoint recibe notificaciones automaticas cada vez que el estado del tramite cambia (pago recibido, en proceso, certificado emitido, etc.).
i Nota: Los pasos 3 y 4 pueden ejecutarse en cualquier orden. Puedes subir documentos antes o despues del pago. El tramite avanza cuando ambos estan completos (pago aprobado + documentos subidos).

Contacto

Para solicitar tu API key o soporte tecnico, escribe a:

Email
contacto@certiveh.co