CBus API for Developers v1

Bienvenido a la documentación oficial de la CBus API for Developers v1. CBus es una plataforma líder en la gestión de flotas y venta de boletos para empresas de autotransporte.

Esta API RESTful proporciona a los desarrolladores un conjunto de endpoints para interactuar directamente con el sistema de ventas de CBus. El objetivo es permitir la integración de sistemas de terceros, agencias de viaje en línea (OTAs) y aplicaciones personalizadas para:

Sigue esta guía para entender el flujo de autenticación, los entornos disponibles y cada uno de los endpoints.

Autenticación

La autenticación de la API difiere entre los entornos de Sandbox y Producción.

Entorno de Sandbox (Pruebas)

Para el entorno de Sandbox, no es necesario enviar el header Authorization. Las peticiones funcionarán de forma abierta para facilitar las pruebas. Solo se requiere el header Accept.

Accept: application/json

Entorno de Producción

Para el entorno de Producción, el header Authorization es obligatorio. Esta Api_key (Bearer Token) deberá ser solicitada directamente al equipo de CBus y estará asociada al plan de API de la instancia.

Authorization: Bearer 
Accept: application/json

Entorno Sandbox

Todas las URL de los endpoints listados a continuación deben usar la siguiente URL base correspondiente al entorno de pruebas:

Flujo General de Venta

El proceso de reserva y confirmación de un boleto sigue un flujo específico de varios pasos. No puedes confirmar un boleto sin antes haberlo seleccionado y reservado.

  1. Búsqueda:
    • GET /api/dev/v1/origenes -> Obtiene la lista de todas las ciudades de origen.
    • GET /api/dev/v1/destinos -> Obtiene los destinos disponibles desde un origen.
    • GET /api/dev/v1/horarios -> Obtiene las corridas y horarios para una ruta y fecha.
  2. Selección:
    • POST /api/dev/v1/asientos -> Muestra el mapa de asientos disponibles para un horario.
    • POST /api/dev/v1/seleccionar-asiento -> Aparta temporalmente un asiento. Devuelve una clave única.
  3. Reserva:
    • POST /api/dev/v1/reservar -> Agrupa todas las claves de asientos (ida y regreso) bajo los datos de un cliente. Devuelve una clave_global.
  4. Confirmación:
    • POST /api/dev/v1/confirmar -> Finaliza la compra usando la clave_global y marca los boletos como "pagados".
  5. (Opcional) Cancelación:
    • POST /api/dev/v1/deseleccionar-asiento -> Libera un asiento que fue apartado temporalmente.

Planes de API y Límites de Tasa (Rate Limiting)

El acceso a la API está sujeto a límites de tasa (Rate Limiting) que dependen del plan de API adquirido para la instancia de CBus WEB. La Api_key asociada a la instancia de la empresa de transporte tendrá el límite de solicitudes por minuto (x-ratelimit-limit) correspondiente a su plan.

Plan de API Límite por Minuto (x-ratelimit-limit) Costo Mensual (USD)
Plan Básico (Default) 8 Incluido en la instancia
API Plan 1 15 $10.00
API Plan 2 30 $18.00
API Plan 3 90 $30.00

Si se excede el límite correspondiente al plan de la instancia, la API comenzará a responder con un código de error 429 Too Many Requests. Para adquirir o cambiar de plan, es necesario contactar al equipo de ventas de CBus.

Cuotas de Uso (Quotas)

Además de los límites de tasa por minuto, el uso de la API está sujeto a una **cuota general** basada en el **número total de claves/folios emitidos** (incluyendo apartados, cancelados, reservados y confirmados/pagados) permitidas por el plan de suscripción de la empresa de transporte con CBus.

Cada intento de seleccion de asiento emite una clave/folio

Si se excede la cuota total de reservaciones activas permitida por el plan, la API **rechazará cualquier nueva conexión o solicitud** que intente crear o confirmar una reservación, independientemente de los límites de tasa por minuto.

Es responsabilidad del cliente (la empresa de transporte) y del desarrollador estar al tanto de los límites específicos de su plan contratado.

Responsabilidades del Desarrollador

Importante: La API de CBus NO se encarga de las siguientes acciones:
  • Crear (imagen/pdf) el boleto (comprobante o confirmación de compra) al cliente final.
  • Notificar al cliente final sobre el estado de su reservación o compra (ej. por email, SMS, WhatsApp).
  • Enviar notificaciones activas (push, email, etc.) a la empresa de transporte sobre nuevas ventas o reservaciones confirmadas.

Sin embargo, toda reservación creada o confirmada a través de la API queda registrada en el sistema administrativo de CBus y puede ser consultada por el personal de la empresa de transporte a través de los reportes y módulos correspondientes.

Es responsabilidad del desarrollador que integra esta API implementar la lógica necesaria para:

  • Generar y enviar el comprobante de compra (boleto) al cliente final.
  • Establecer los mecanismos de notificación al cliente que considere necesarios.

GET /api/dev/v1/origenes

Obtiene una lista de todas las escalas (orígenes) disponibles.

Parámetros de Query

Ninguno.

Respuesta Exitosa (200 OK)

[
    {
        "id": 5,
        "nombre": "CDMX",
        "lat": null,
        "lng": null,
        "abordajes": []
    },
    {
        "id": 1,
        "nombre": "GPE",
        "lat": null,
        "lng": null,
        "abordajes": []
    },
    {
        "id": 3,
        "nombre": "OAXACA",
        "lat": null,
        "lng": null,
        "abordajes": []
    },
    {
        "id": 4,
        "nombre": "PUEBLA",
        "lat": null,
        "lng": null,
        "abordajes": []
    },
    {
        "id": 2,
        "nombre": "TEPIC",
        "lat": null,
        "lng": null,
        "abordajes": []
    }
]

GET /api/dev/v1/destinos

Obtiene los destinos disponibles basado en un nombre de origen.

Parámetros de Query

Parámetro Tipo Requerido Descripción
q string Nombre exacto del origen. Ej: DMX.

Respuesta Exitosa (200 OK)

[
    {
        "id": 3,
        "nombre": "OAXACA",
        "lat": null,
        "lng": null,
        "abordajes": []
    },
    {
        "id": 4,
        "nombre": "PUEBLA",
        "lat": null,
        "lng": null,
        "abordajes": []
    }
]

GET /api/dev/v1/horarios

Obtiene los horarios disponibles para una ruta y fechas específicas.

Parámetros de Query

Parámetro Tipo Requerido Descripción
origen string Nombre de la escala de origen (Ej: CDMX).
destino string Nombre de la escala de destino (Ej: OAXACA).
fecha_ida date Fecha de salida (Formato: YYYY-MM-DD).
fecha_regreso date No Fecha de regreso (Formato: YYYY-MM-DD).

Respuesta Exitosa (200 OK)

{
    "ida": [
        {
            "id": 3,
            "corrida_id": 2,
            "ab_ba": "ba",
            "ab": 1,
            "hora_salida": "14:00:00",
            "fcomp": 0,
            "fecha": "2025-10-30",
            "minutos_trayecto": 480,
            "activo": 1,
            "aplicar_venta_linea": 1,
            "corrida": {
                "id": 2,
                "nombre": "Oaxaca-CDMX",
                "mostrar_pv": 1,
                "aplicar_en_reservaciones": 1,
                "aplicar_venta_linea": 1,
                "extraordinaria": 0,
                "fechas_deshabilitadas": [],
                "activo": 1
            },
            "origen": {
                "id": 5,
                "nombre": "CDMX",
                "hora": "2:00 pm"
            },
            "destino": {
                "id": 3,
                "nombre": "OAXACA",
                "hora": "10:00 pm"
            },
            "disponibilidad": {
                "asientos_disponibles": 20,
                "asientos_ocupados": 0,
                "total_asientos": 20,
                "ultima_actualizacion": "2025-10-29T00:00:00.000000Z"
            }
        }
    ],
    "regreso": [
        {
            "id": 3,
            "corrida_id": 2,
            "ab_ba": "ab",
            "ab": 1,
            "hora_salida": "14:00:00",
            "fcomp": 0,
            "fecha": "2025-11-01",
            "minutos_trayecto": 480,
            "...": "..."
        }
    ]
}

POST /api/dev/v1/asientos

Obtiene el mapa de asientos (layout) de un autobús para un horario específico, indicando cuáles están disponibles, ocupados o bloqueados.

Cuerpo de la Solicitud (JSON)

Parámetro Tipo Requerido Descripción
ab integer Dirección del viaje (Usar 1 o 0).
corrida integer ID de la corrida (obtenido de /horarios).
origen integer ID de la escala de origen.
destino integer ID de la escala de destino.
horario integer ID del horario (obtenido de /horarios).
redondo integer 0 para viaje sencillo.
fecha date Fecha del viaje (Formato: YYYY-MM-DD).

Ejemplo de Solicitud

{
    "ab": 1,
    "corrida": 2,
    "origen": 5,
    "destino": 3,
    "horario": 3,
    "redondo": 0,
    "fecha": "2025-10-31"
}

Respuesta Exitosa (200 OK)

{
    "escalas": {
        "origen": "CDMX",
        "destino": "OAXACA"
    },
    "precio": [ ... ],
    "hora": {
        "salida": "2:00 pm",
        "llegada": "10:00 pm"
    },
    "asientos": [
        {
            "id": 21,
            "numero": 1,
            "corrida_id": 2,
            "categoria": null,
            "categoria_abreviacion": null,
            "forma_calculo_valor": null,
            "valor": null,
            "reservaciones": [],
            "disponible": true,
            "fcomp": 0,
            "horario_id": 3,
            "origen_id": 5,
            "destino_id": 3,
            "ab": false,
            "fecha_reservacion": "2025-10-31",
            "prefix": "000"
        },
        {
            "id": 22,
            "numero": 2,
            "corrida_id": 2,
            "..." : "..."
        }
    ],
    "total_asientos": 20,
    "abordajes": [],
    "fecha_reservacion": "31-10-2025",
    "fcomp": 0
}

Nota Importante sobre la Respuesta

La respuesta de este endpoint es crucial. Cada objeto dentro del array asientos contiene los IDs exactos que necesitarás para el siguiente paso (/api/dev/v1/seleccionar-asiento).

Debes capturar y utilizar los siguientes valores del asiento que elija el usuario:

POST /api/dev/v1/seleccionar-asiento

Aparta temporalmente un asiento específico. Este asiento se bloqueará por un tiempo limitado (ej. 10 minutos) y se generará una clave única para esta selección.

Cuerpo de la Solicitud (JSON)

Parámetro Tipo Requerido Descripción
corrida string ID de la corrida (obtenido de /asientos).
origen string ID de la escala de origen (obtenido de /asientos).
destino string ID de la escala de destino (obtenido de /asientos).
horario string ID del horario (obtenido de /asientos).
asiento string ID del asiento a seleccionar (obtenido de /asientos).
tipo_persona string adulto o nino.
ab integer Dirección del viaje (1 o 0). Importante: Debes usar el valor ab (true/false o 1/0) que se obtuvo del objeto asiento en la respuesta de /api/dev/v1/asientos.
fecha date Fecha del viaje (Formato: YYYY-MM-DD).
canal_venta string Identificador del canal (Ej: "TU CANAL").
observaciones string No Notas adicionales para este asiento.

Ejemplo de Solicitud

{
    "corrida":"2",
    "origen":"5",
    "destino":"3",
    "horario":"3",
    "asiento":"23",
    "tipo_persona":"adulto",
    "ab": 0,
    "fecha": "2025-10-31",
    "canal_venta":"TU CANAL",
    "observaciones": "Texto que saldrá en los reportes y boleto"
}

Respuesta Exitosa (200 OK)

{
    "cliente": "N/A",
    "asiento_id": "23",
    "horario_id": "3",
    "corrida_id": "2",
    "redondo": null,
    "fecha_reservacion": "2025-10-31",
    "fcomp": 0,
    "origen_id": "5",
    "destino_id": "3",
    "estatus": "apartado",
    "tipo_persona": "adulto",
    "clave": "YGBD2D",
    "ab": false,
    "is_plt_reservacion": true,
    "canal_venta": "TU CANAL",
    "updated_at": "2025-10-30T02:29:45.000000Z",
    "created_at": "2025-10-30T02:29:45.000000Z",
    "id": 3,
    "abordajes": [],
    "expiracion": {
        "fecha_expira": "2025-10-29T20:39:45.666850Z",
        "fecha_expira_diff_h": "en 9 minutos",
        "fecha_expira_mins": 9
    },
    "observaciones": "Texto que saldrá en los reportes y boleto"
}

Nota Importante sobre la clave

La clave (ej: "YGBD2D") devuelta por este endpoint es **temporal** y se usa para agrupar el asiento en el siguiente paso (/api/dev/v1/reservar).

Al ser usada en /reservar, la API generará una nueva clave final (con caracteres diferentes). Además, si se trata de un viaje redondo, las claves finales tendrán un sufijo: -1 para el viaje de ida y -2 para el viaje de regreso.

POST /api/dev/v1/deseleccionar-asiento

Libera un asiento que fue apartado (con /seleccionar-asiento) antes de que expire su tiempo. Esto cancela la pre-reserva de ese asiento individual.

Cuerpo de la Solicitud (JSON)

Parámetro Tipo Requerido Descripción
clave string La clave única del asiento que se obtuvo en /seleccionar-asiento.

Ejemplo de Solicitud

{
    "clave": "YGBD2D"
}

Respuesta Exitosa (200 OK)

{
    "message": "Clave cancelada"
}

POST /api/dev/v1/reservar

Asigna los datos de un cliente a uno o más asientos apartados (claves). Esto agrupa todas las selecciones de asientos bajo una clave_global y prepara la orden para el pago.

Cuerpo de la Solicitud (JSON)

Parámetro Tipo Requerido Descripción
lang string No Idioma (ej: "es").
cliente object Objeto que contiene la información del cliente.
cliente.nombre string Nombre completo del cliente.
cliente.celular string No Número de celular del cliente.
cliente.email string No Email del cliente (debe ser un email válido si se envía).
reservaciones object Objeto que contiene los arrays de asientos de ida y (opcionalmente) regreso.
reservaciones.ida array Array de objetos, cada uno con la clave temporal de un asiento (obtenida de /seleccionar-asiento).
...ida[].clave string Clave temporal del asiento.
...ida[].observaciones string No Observaciones específicas para este asiento/pasajero.
reservaciones.regreso array No Array de objetos para el viaje de regreso. Requerido si es viaje redondo.
...regreso[].clave string Clave temporal del asiento de regreso.
...regreso[].observaciones string No Observaciones específicas para este asiento/pasajero.
abordajes object No Objeto con los IDs de los puntos de abordaje (puede ser requerido según la configuración).
abordajes.ida integer No ID del punto de abordaje para el viaje de ida.
abordajes.regreso integer No ID del punto de abordaje para el viaje de regreso.

Ejemplo de Solicitud (Viaje Redondo)

{
    "cliente": {
        "nombre": "Fulanito Pérez",
        "celular": "9585846497",
        "email": "alejandro@cbus.com.mx"
    },
    "reservaciones": {
        "ida": [
            {
                "clave": "YGBD2D",
                "observaciones": "Pasajero adulto, ventana"
            }
        ],
        "regreso": [
            {
                "clave": "HJD8K1",
                "observaciones": "Pasajero adulto, pasillo"
            }
        ]
    },
    "abordajes": {
        "ida": 1,
        "regreso": 3
    }
}

Respuesta Exitosa (200 OK)

{
    "clave_global": "YBR7HRGL",
    "divisa": "MXN",
    "cliente": {
        "nombre": "Fulanito Pérez",
        "telefono": "9585846497"
    },
    "primer_viaje": false,
    "reservaciones": {
        "ida": [
            {
                "id": 3,
                "cliente": "Fulanito Pérez",
                "celular": "9585846497",
                "email": "alejandro@cbus.com.mx",
                "redondo": true,
                "clave": "YGBD2D-1",
                "observaciones": "Pasajero adulto, ventana"
            }
        ],
        "regreso": [
            {
                "id": 4,
                "cliente": "Fulanito Pérez",
                "celular": "9585846497",
                "email": "alejandro@cbus.com.mx",
                "redondo": true,
                "clave": "YGBD2D-2",
                "observaciones": "Pasajero adulto, pasillo"
            }
        ]
    },
    "expiracion": {
        "fecha_expira": "2025-10-30T06:31:37.360615Z",
        "fecha_expira_diff_h": "en 3 horas",
        "fecha_expira_mins": 120
    }
}

POST /api/dev/v1/confirmar

Confirma la reservación y marca todos los boletos asociados a la clave_global como "pagados". Este es el último paso del flujo. La respuesta incluye detalles de los boletos confirmados, información de las sucursales/terminales relevantes al origen del viaje, y los datos fiscales de la empresa transportista.

Cuerpo de la Solicitud (JSON)

Parámetro Tipo Requerido Descripción
clave_global string La clave obtenida en /reservar.
tipo_pago string efectivo, TD, TC, deposito, transferencia.
total numeric El monto total de la venta con descentos de comisión.
total_original numeric El monto total de la venta sin descuentos de comisi´pn.
observaciones string No Observaciones generales de la venta que aplicarán para cada una de las claves. (Se recomienda colocar aquí los folios de transacción o de control interno para aclaraciones). Ten en cuenta que al registrar nuevas observaciones, estas sobrescribirán las observaciones previas asignadas desde otros endpoints. Esta información sale en reportes y boletos del cliente.

Ejemplo de Solicitud

{
    "clave_global": "YBR7HRGL",
    "tipo_pago": "TD",
    "total": 700,
    "total_original": 776
    "observaciones": "Folio de transacción MTI1MzU0Ng | Venta relizada por desarrollador independiente"
}

Respuesta Exitosa (200 OK)

La respuesta contiene un array reservaciones con los boletos confirmados, un array sucursales con la información de las terminales asociadas al origen del primer boleto (útil para mostrar dirección, teléfonos, ubicación), y un objeto empresa con los datos fiscales del transportista.

{
    "reservaciones": [
        {
            "id": 3,
            "cliente": "Fulanito Pérez",
            "celular": "9585846497",
            "email": "alejandro@cbus.com.mx",
            "redondo": false,
            "costo_boleto": 700,
            "clave": "YGBD2D", // Clave final del boleto
            "fecha_reservacion": "2025-10-31",
            "fcomp": 0,
            "estatus": "pagado",
            "costo_boleto_original": 776,
            "is_plt_reservacion": 1,
            "tipo_persona": "adulto",
            "corrida_id": 2,
            "asiento_id": 23,
            "horario_id": 3,
            "origen_id": 5,
            "destino_id": 3,
            "ab": 0,
            "created_at": "2025-10-30T02:31:37.000000Z",
            "updated_at": "2025-10-30T02:31:46.000000Z",
            "abordaje_id": null,
            "canal_venta": "TU CANAL",
            "observaciones": "Folio de transacción MTI1MzU0Ng | Venta relizada por desarrollador independiente",
            "origen": {
                "id": 5,
                "nombre": "CDMX"
            },
            "destino": {
                "id": 3,
                "nombre": "OAXACA"
            },
            "abordaje": null
        }
        // ... más boletos si la clave_global agrupaba varios
    ],
    "sucursales": [ // Información de terminales/sucursales asociadas al origen
         {
            "nombre": "Terminal Central CDMX",
            "direccion": "Av. Principal 123",
            "estado": "Ciudad de México",
            "comision": null, // Campo interno, puede ignorarse
            "codigo_postal": "01234",
            "telefono_1": "5512345678",
            "telefono_2": null,
            "telefono_3": null,
            "descripcion": "Terminal principal en CDMX",
            "pais": "México",
            "colonia": "Centro",
            "localidad": null,
            "municipio": "Cuauhtémoc",
            "lat": "19.4326",
            "lng": "-99.1332"
        }
        // ... puede haber más sucursales relacionadas al origen
    ],
    "empresa": { // Datos fiscales de la empresa transportista
        "nombre": "CBus DEMO",
        "rfc": "ALEJANDRO TONATIUH BERNAL ZAMORANO",
        "razon_social": null,
        "calle": "Jilguero 57",
        "tel_1": "",
        "tel_2": "",
        "tel_3": "",
        "cp": "63170"
    },
    "clave_global": "YBR7HRGL"
}

Manejo de Errores

La API utiliza códigos de estado HTTP estándar para indicar el éxito o fracaso de una solicitud.

422 Unprocessable Entity (Entidad no procesable)

Este es el error más común. Se devuelve cuando la solicitud es sintácticamente correcta, pero no se puede procesar debido a errores de validación o de lógica de negocio.

A) Error de Validación de Campos (Formato Laravel)

Ocurre cuando faltan campos requeridos o los datos no tienen el formato correcto (ej. un email inválido, una fecha mal formada).

{
    "message": "The given data was invalid.",
    "errors": {
        "corrida": [
            "El campo corrida es obligatorio."
        ],
        "horario": [
            "El campo horario es obligatorio."
        ],
        "fecha": [
            "El campo fecha debe ser una fecha posterior o igual a hoy."
        ]
    }
}

B) Error de Lógica de Negocio (Formato Personalizado)

Ocurre cuando los datos son válidos, pero rompen una regla de negocio (ej. el asiento ya está ocupado, el origen y destino son el mismo, la clave de reservación expiró).

{
    "message": "El asiento ya no está disponible"
}
{
    "errors": {
        "message": "Has execedido el tiempo de reservación o las claves no existen, inicia de nuevo."
    }
}

404 Not Found (No Encontrado)

Este error ocurre cuando se intenta acceder a un recurso que no existe, como una URL de endpoint incorrecta.

{
    "message": "Not Found"
}

500 Internal Server Error (Error Interno del Servidor)

Este error indica que algo salió mal en el servidor de forma inesperada (un error en el código, fallo de la base de datos). Este error debe ser reportado al equipo de desarrollo.

{
    "message": "Server Error"
}