ListNRideDevelopers
Primeros pasos

Autenticación y modos

Cada petición necesita tu clave en la cabecera Authorization: Bearer …. Entregamos las claves tras una breve conversación – no hay registro libre.

URL base
https://api.listnride.com/v1
lnr_test_…

Bicicletas y precios reales, reservas simuladas: el enlace abre una página de prueba, nadie paga y el arrendador no recibe aviso.

lnr_live_…

Reservas reales a través del pago de ListNRide.

Las claves van en tu servidor. Nunca las incluyas en un navegador o una app – quien tenga tu clave puede reservar en tu nombre.
curl
curl "https://api.listnride.com/v1/rides?lat=52.52&lng=13.40" \
  -H "Authorization: Bearer lnr_test_…"
Primeros pasos

Cómo funciona una reserva

No necesitas un pago propio: el cliente reserva y paga con nosotros y después vuelve a tu web.

  1. Encontrar bicicletas

    GET /v1/rides por lugar, periodo y categoría.

  2. Crear una sesión de pago

    POST /v1/checkout/sessions – recibes el precio y un enlace.

  3. Redirigir al cliente

    Reserva y pago en ListNRide y vuelta a tu web.

  4. Recibir el estado

    Por webhook o con GET /v1/bookings/{id}.

Primeros pasos

El modo de prueba paso a paso

Con una clave de prueba todo funciona como en real – solo que nadie paga y ningún arrendador interviene. Prueba el recorrido completo una vez antes de salir en real.

  1. Crear una sesión

    POST /v1/checkout/sessions con lnr_test_…. Precios y disponibilidad son reales.

  2. Abrir el enlace

    La url abre una página de prueba en lugar del pago. Elige allí «Complete test booking».

  3. Comprobar la vuelta

    El cliente llega a tu return_url con booking=bkg_test_… y status=success.

  4. Comprobar el webhook

    Si hay una URL de webhook configurada, booking.confirmed con "mode": "test" llega en menos de un minuto.

Referencia

Endpoints

GET/v1/ridesrides:read

Bicicletas cerca de un lugar o de un arrendador. Con un periodo, availability.units_available indica las unidades libres.

ParámetroDescripción
lat, lngCentro de la búsqueda (o lister)
radius_km0,1–100, por defecto 15
bboxZona del mapa minLng,minLat,maxLng,maxLat en vez de lat/lng
from, toPeriodo, fecha o fecha-hora ISO
quantityNúmero de bicicletas iguales, por defecto 1
categoryp. ej. e-bike,cargo-bike
price_min
price_max
Precio por día en céntimos, con tarifa de servicio y seguro básico
rider_heightAltura del ciclista en cm (150–210) – encuentra bicicletas de la talla adecuada y unisize
frame_size
brand
Talla de cuadro o marca exacta, p. ej. M o Gazelle
accessoriesEquipamiento incluido, debe estar todo: helmet,lock,lights,basket,childseat,trailer,gps,repair_kit
instant_booking
top_booked
true: solo confirmación inmediata / solo las más reservadas
min_rating
lister_type
type
Valoración mínima, business o private, bike o accessory
sortrecommended · distance · price_asc · price_desc · rating · popular
limit, cursorPaginación, máximo 100 por página
Respuesta (resumida)
{
  "object": "list",
  "data": [{
    "id": "ride_oEbNgLPApUJf52PkgHU49A",
    "name": "KRZBERG – Single Speed",
    "category": { "id": "single-speed" },
    "price": { "currency": "EUR", "per_day": 2500 },
    "lister": { "id": "lis_VTknvPc20LBQbXE9p7dt6A" },
    "instant_booking": true,
    "distance_km": 1.46
  }],
  "has_more": true, "next_cursor": "eyJvIjoyMH0"
}
GET/v1/rides/{id}rides:read

Una bicicleta con descripción, todas las fotos, equipamiento, fianza y seguro.

Además, todo lo que necesita una página de producto: precios totales de 1 a 28 días, altura del ciclista, reglas de reserva, horarios, condiciones de cancelación y extras reservables con zonas de entrega.

Respuesta (resumida)
{
  "price": { "per_day": 2500, "tiers": [
    { "days": 1, "total": 2500 },
    { "days": 7, "total": 15599, "discount": 1400 } ] },
  "size": { "rider_height": { "range": "175-185" } },
  "booking_rules": { "min_days": 1, "time_slot_minutes": 30 },
  "opening_hours": { "monday": ["09:00-18:00"], … },
  "cancellation_policy": { "by_customer": [
    { "hours_before_pickup_min": 72, "refund_percent_of_rental": 100 }, … ] },
  "extras": [{ "code": "insurance_plus" }, { "code": "delivery" }]
}
GET/v1/rides/{id}/availabilityrides:read

Unidades libres por día y franjas de recogida y devolución en hora local, hasta 92 días por petición. Los días de cierre y los horarios ya están incluidos – ideal para tu propio selector de fechas. La comprobación vinculante la hacen POST /v1/quotes y el pago.

Respuesta (resumida)
{
  "object": "availability",
  "units_total": 4,
  "days": [{
    "date": "2026-11-17",
    "units_available": 3,
    "closed": false,
    "pickup_windows": ["09:00-18:00"],
    "return_windows": ["09:00-18:00"]
  }, …]
}
GET/v1/rides/{id}/reviewsrides:read

Opiniones verificadas de una bicicleta, las más recientes primero, con media y número total. Los autores aparecen con nombre e inicial. Todas las opiniones de un arrendador: GET /v1/listers/{id}/reviews.

GET/v1/listers/{id}rides:read

Perfil público de un arrendador: nombre, ubicación, valoración, reservas completadas, número de bicicletas, confirmación inmediata, reglas de reserva, horarios y zonas de entrega. Los particulares aparecen con su nombre y sin calle.

GET/v1/cancellation-policyrides:read

Las condiciones de cancelación que se aplican a cada reserva: desde 72 horas antes de la recogida se reembolsa todo; por debajo, una parte del alquiler según la franja. Si cancela el arrendador, el cliente recupera todo.

GET/v1/categoriesrides:read

Todas las categorías con nombre en alemán e inglés. Una categoría principal como e-bike incluye sus subcategorías en la búsqueda.

GET/v1/placesrides:read

Todos los lugares con bicicletas reservables, primero los que más tienen. Con q buscas en todos los idiomas (p. ej. q=munich), con country filtras por país y locale elige el idioma de los nombres. Un lugar: GET /v1/places/{id}.

GET/v1/classesrides:read

En vez de una bicicleta concreta, tu cliente reserva una clase – p. ej. «E-bike, gama media» en Berlín – y ListNRide encuentra un arrendador adecuado. Consulta con place o lat/lng. Se reserva con una sesión de pago con class y size (altura del ciclista).

Respuesta (resumida)
{
  "id": "berlin.e-bike.mid",
  "object": "class",
  "category": { "id": "e-bike" },
  "tier": { "id": "mid" },
  "price": { "currency": "EUR", "per_day": 3900 },
  "sizes": ["150-165", "165-175", "175-185", "185-205", "Unisize"],
  "listers_nearby": 12
}
POST/v1/quotesrides:read

Calcula el precio exacto como el pago de ListNRide: alquiler, descuento, tarifa de servicio, seguro básico, extras (insurance_plus) y entrega a una dirección, sin reservar nada. Un presupuesto incluye bicicletas de un arrendador o una clase.

curl
curl -X POST https://api.listnride.com/v1/quotes \
  -H "Authorization: Bearer lnr_test_…" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "2026-11-17", "to": "2026-11-19",
    "items": [{ "ride": "ride_jK6n…", "quantity": 2,
                "extras": ["insurance_plus"] }],
    "delivery_address": "Torstraße 1, 10119 Berlin"
  }'

# → "amounts": { "rental": 6000, "service_fee": 1100,
#   "insurance_plus": 900, "delivery": 1500, "total": 9600 }
POST/v1/checkout/sessionsbookings:write

Crea una sesión de pago. El pago de ListNRide comprueba precio y disponibilidad. El enlace es válido 24 horas; cantidad y horarios vienen preseleccionados en el pago.

CampoDescripción
ride *ID de la bicicleta ride_…
class, sizeEn vez de ride: una clase de GET /v1/classes y la altura del ciclista (165-175 … o Unisize)
from, to *Día de recogida y devolución, YYYY-MM-DD
pickup_time, return_timeHH:MM, por defecto 10:00 / 17:00
quantityCantidad, 1–50, por defecto 1
return_url *A dónde vuelve el cliente tras reservar (https), con checkout_session, booking y status=success
cancel_urlOpcional, si el cliente cancela (https)
localede · en · fr · es · it · nl
client_referenceTu propia referencia
curl
curl -X POST https://api.listnride.com/v1/checkout/sessions \
  -H "Authorization: Bearer lnr_test_…" \
  -H "Content-Type: application/json" \
  -d '{
    "ride": "ride_jK6nvpDczET3Adx8AKKn1w",
    "from": "2026-11-17", "to": "2026-11-18",
    "pickup_time": "09:00", "return_time": "17:00",
    "return_url": "https://tu-web.es/gracias",
    "locale": "es"
  }'

# → { "id": "cs_O8t1…", "amount_total": 7800,
#     "url": "https://www.listnride.es/api/go/p/BHTm…" }
GET/v1/checkout/sessions/{id}bookings:read

Estado de la sesión: open, booked (con ID de booking) o expired.

GET/v1/bookings/{id}bookings:read
statusDescripción
awaiting_paymentEl cliente está en el pago, aún sin pagar
requestedPagado o reservado, pendiente de aceptación del arrendador
acceptedAceptado por el arrendador, pago en curso
confirmedConfirmada
completedAlquiler finalizado
canceled_by_lister · canceled_by_customer · canceledCancelada
expiredNo pagada o no aceptada a tiempo
GET/v1/bookingsbookings:read

Todas las reservas de tus sesiones de pago, las más recientes primero. Filtra por status o por tu client_reference. Una clave de prueba lista reservas de prueba; una clave real, las reales. Las reservas canceladas incluyen cancellation con el importe y el estado del reembolso.

POST/v1/bookings/{id}/cancelbookings:cancel

Cancela una reserva en nombre de tu cliente – con las mismas reglas que en listnride.com: desde 72 horas antes de la recogida se reembolsa todo; por debajo, una parte del alquiler. Se avisa al arrendador, recibes booking.canceled_by_customer y el reembolso vuelve al medio de pago del cliente.

Comprueba antes con GET /v1/bookings/{id}/cancellation: indica si es posible cancelar y el reembolso exacto, sin cambiar nada. Cancelar requiere el scope bookings:cancel, que activamos a petición. Opcional: reason (changed_mind, found_better, timing_issue, price_too_high, personal_reasons, other) y comment.

curl
# 1. Vista previa: ¿se puede cancelar y cuánto recupera el cliente?
curl https://api.listnride.com/v1/bookings/bkg_gr9z…/cancellation \
  -H "Authorization: Bearer lnr_live_…"
# → "cancelable": true, "refund": { "amount": 7300 },
#   "breakdown": { "rental_refunded_percent": 75 }

# 2. Cancelar
curl -X POST https://api.listnride.com/v1/bookings/bkg_gr9z…/cancel \
  -H "Authorization: Bearer lnr_live_…" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "timing_issue" }'
# → "status": "canceled_by_customer"
GET/v1/commissionsbookings:read

Añade ?aff=TUCODIGO a cualquier enlace de ListNRide – cualquier página, cualquier idioma. Si el cliente reserva dentro del plazo acordado, la reserva cuenta para ti; gana el último clic. Las reservas de tus sesiones de pago cuentan siempre para ti, incluso sin clic.

La comisión se acuerda de forma individual y se basa en las tarifas que ListNRide gana con la reserva. Cuenta cuando termina el alquiler; si cancela el arrendador, no hay comisión. GET /v1/commissions muestra clics, reservas, nivel y comisión por mes – sin datos de clientes. Se liquida mensualmente mediante nota de abono.

Enlace e informe
# Enlace de partner – funciona en cualquier página
https://www.listnride.de/berlin/e-bike?aff=NEEDABIKE

# Tu comisión de un mes
curl "https://api.listnride.com/v1/commissions?month=2026-09" \
  -H "Authorization: Bearer lnr_live_…"
# → "clicks": 4812, "bookings": 91, "tier": "Stufe 3 · 30 %",
#   "commission_net": { "amount": 54120 }, "status": "approved"
Más

Webhooks

Cuando cambia el estado de una reserva, enviamos un POST a tu URL de webhook, p. ej. booking.confirmed. Responde con 2xx – si no, reintentamos tras 1 min, 5 min, 30 min y hasta 24 h. Usa ping para probar la conexión; el id del evento no cambia en los reintentos.

Verifica cada mensaje con la cabecera LNR-Signature: t=…,v1=…: HMAC-SHA256 sobre t + "." + body con tu secreto whsec_…. Usa el cuerpo sin modificar y rechaza los mensajes cuyo t tenga más de 5 minutos.

Ejemplo: booking.confirmed
POST https://tu-web.es/hooks/listnride
LNR-Event: booking.confirmed
LNR-Signature: t=1791210000,v1=5f2c…

{
  "id": "evt_Qm3xT0bWl2kZ8yQe",
  "object": "event",
  "type": "booking.confirmed",
  "created": "2026-11-02T09:14:03.000Z",
  "data": { "object": {
    "id": "bkg_gr9z-CSUh4I8UrC9WEwW2Q",
    "object": "booking",
    "mode": "live",
    "status": "confirmed",
    "reference": "LNR-w4kKb",
    "checkout_session": "cs_O8t1fc2rdEG2GyYTqghvfA",
    "ride": "ride_jK6nvpDczET3Adx8AKKn1w",
    "from": "2026-11-17T08:00:00.000Z",
    "to": "2026-11-18T16:00:00.000Z",
    "quantity": 1,
    "amount_total": 7800,
    "currency": "EUR",
    "client_reference": "NB-1042"
  } }
}
Verificar la firma
const crypto = require("crypto");

// rawBody: el cuerpo sin modificar, tal como llegó
function verify(rawBody, header, secret) {
  const p = Object.fromEntries(header.split(",").map(x => x.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(p.t)) > 300) return false;
  const expected = crypto.createHmac("sha256", secret)
    .update(`${p.t}.${rawBody}`).digest("hex");
  return typeof p.v1 === "string" && p.v1.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(p.v1));
}
Más

Errores y límites

Los errores tienen siempre la misma forma. Con el request_id encontramos tu caso rápidamente.

Límites por clave: un límite por minuto y una cuota diaria (cabeceras X-Quota-Limit, X-Quota-Remaining). Una búsqueda se puede paginar como máximo hasta 500 resultados: acótala por lugar, radio, categoría o periodo. No se permite la extracción masiva ni la reventa de los datos.

Reintentos seguros: envía la cabecera Idempotency-Key con POST /v1/checkout/sessions y POST /v1/bookings/{id}/cancel. Un reintento con la misma clave y el mismo contenido devuelve la primera respuesta (cabecera Idempotent-Replayed: true) en lugar de actuar dos veces. Las claves se guardan 24 horas.

HTTPcode
400parameter_missing, parameter_invalid, outside_opening_hours, duration_too_short, duration_too_long, multiple_listers, delivery_unavailable, pagination_limit
401missing_api_key, invalid_api_key
403missing_scope
404resource_missing, route_not_found
409ride_unavailable, already_canceled, processing, already_started
429rate_limited, daily_quota_exceeded, too_many_failed_attempts – X-RateLimit-*, X-Quota-*, Retry-After
Respuesta de error
{ "error": {
    "type": "invalid_request_error",
    "code": "ride_unavailable",
    "message": "The ride is not available for this period and quantity.",
    "param": "ride",
    "request_id": "req_UqrIw8P5wzwT" } }
Más

SDK y herramientas

Clientes oficiales en un solo archivo, sin dependencias – cópialos en tu proyecto. Se encargan de la autenticación, la paginación, los reintentos con 429/5xx, las Idempotency-Keys y la verificación de webhooks.

Node.js
const { ListNRide } = require("./listnride");
const lnr = new ListNRide({ apiKey: process.env.LNR_API_KEY });

for await (const ride of lnr.rides.all({ lat: 52.52, lng: 13.40, category: "e-bike" })) {
  console.log(ride.name, ride.price.per_day);
}
const session = await lnr.checkoutSessions.create({ ride: "ride_…", from: "2026-11-17",
  to: "2026-11-19", return_url: "https://your-site.com/thanks" });  // la Idempotency-Key se añade automáticamente
Más

Versiones

La versión forma parte de la ruta. Dentro de /v1 solo añadimos campos – nada se elimina ni se renombra. Los cambios mayores aparecerán como /v2, y /v1 seguirá funcionando al menos 12 meses. La descripción legible por máquina (OpenAPI 3.1) está en /openapi.json y https://api.listnride.com/v1/openapi.json.

Más

Cambios

  1. Idempotency-Key para llamadas de escritura, colección de Postman, clientes oficiales para Node.js, PHP y Python.

  2. Afiliación: enlaces de partner con ?aff=CODE y GET /v1/commissions.

  3. GET /v1/bookings, vista previa de cancelación y POST /v1/bookings/{id}/cancel (scope bookings:cancel).

  4. Filtros de búsqueda (precio, altura, accesorios, zona del mapa …), escalas de precio, horarios, condiciones de cancelación, calendario de disponibilidad, opiniones y perfiles de arrendadores.

  5. Lugares, clases de vehículos, POST /v1/quotes, reserva por clase y cuota diaria por clave.

  6. Lanzamiento de v1: bicicletas, categorías, sesiones de pago, reservas, webhooks y modo de prueba.

Solicitar acceso

Cuéntanos tu web y lo que tienes en mente. Primero recibes una clave de prueba – la puesta en real llega tras una breve llamada.

partner@listnride.com

Solicitar acceso

Cuéntanos brevemente quién eres y qué tienes en mente. Primero recibes una clave de prueba – la puesta en real llega tras una breve llamada.

¿Prefieres el correo? partner@listnride.com