ListNRideDevelopers
Einstieg

Anmeldung & Modi

Jede Anfrage braucht deinen Schlüssel im Kopf Authorization: Bearer …. Schlüssel vergeben wir nach einem kurzen Gespräch – es gibt keine Selbstregistrierung.

Basis-URL
https://api.listnride.com/v1
lnr_test_…

Echte Räder und Preise, Buchungen nur simuliert: Der Link führt auf eine Testseite, es gibt keine Zahlung und keine Nachricht an den Vermieter.

lnr_live_…

Echte Buchungen über die ListNRide-Kasse.

Schlüssel gehören auf deinen Server. Nie im Browser oder in einer App ausliefern – wer ihn hat, kann in deinem Namen buchen.
curl
curl "https://api.listnride.com/v1/rides?lat=52.52&lng=13.40" \
  -H "Authorization: Bearer lnr_test_…"
Einstieg

Ablauf einer Buchung

Du brauchst keine eigene Kasse: Der Kunde bucht und bezahlt bei uns und landet danach wieder auf deiner Seite.

  1. Räder finden

    GET /v1/rides nach Ort, Zeitraum und Kategorie.

  2. Kassensitzung anlegen

    POST /v1/checkout/sessions – du bekommst Preis und Link.

  3. Kunden weiterleiten

    Buchen und Bezahlen in der ListNRide-Kasse, dann zurück zu dir.

  4. Status erhalten

    Per Benachrichtigung oder GET /v1/bookings/{id}.

Einstieg

Testmodus Schritt für Schritt

Mit einem Testschlüssel läuft alles wie live – nur bezahlt niemand, und kein Vermieter bekommt etwas mit. So baust du die ganze Strecke einmal durch, bevor du live gehst.

  1. Sitzung anlegen

    POST /v1/checkout/sessions mit lnr_test_…. Preis und Verfügbarkeit sind echt.

  2. Link öffnen

    Die url führt auf eine Testseite statt in die Kasse. Dort „Testbuchung abschließen“ wählen.

  3. Rücksprung prüfen

    Der Kunde landet auf deiner return_url mit booking=bkg_test_… und status=success.

  4. Benachrichtigung prüfen

    Mit hinterlegter Adresse kommt innerhalb einer Minute booking.confirmed mit "mode": "test".

Referenz

Endpunkte

GET/v1/ridesrides:read

Räder in der Nähe eines Ortes oder eines Vermieters. Mit Zeitraum zeigt availability.units_available die freien Einheiten.

ParameterBedeutung
lat, lngMittelpunkt der Suche (oder lister)
radius_km0,1–100, Standard 15
bboxKartenausschnitt minLng,minLat,maxLng,maxLat statt lat/lng
from, toZeitraum, ISO-Datum oder -Zeitpunkt
quantityAnzahl gleicher Räder, Standard 1
categoryz. B. e-bike,cargo-bike
price_min
price_max
Preis pro Tag in Cent, inkl. Servicegebühr und Basisversicherung
rider_heightKörpergröße in cm (150–210) – findet Räder in passender Größe und Unisize
frame_size
brand
Exakte Rahmengröße bzw. Marke, z. B. M oder Gazelle
accessoriesMitgeliefertes Zubehör, alles muss dabei sein: helmet,lock,lights,basket,childseat,trailer,gps,repair_kit
instant_booking
top_booked
true: nur Sofortbestätigung / nur Top gebuchte Räder
min_rating
lister_type
type
Mindestbewertung, business oder private, bike oder accessory
sortrecommended · distance · price_asc · price_desc · rating · popular
limit, cursorBlättern, höchstens 100 je Seite
Antwort (gekürzt)
{
  "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

Ein Rad mit Beschreibung, allen Bildern, Ausstattung, Kaution und Versicherung.

Dazu alles, was eine Produktseite braucht: Gesamtpreise für 1–28 Tage, Körpergröße, Buchungsregeln, Öffnungszeiten, Stornoregeln und buchbare Extras mit Lieferzonen.

Antwort (gekürzt)
{
  "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

Freie Exemplare je Tag plus Abhol- und Rückgabefenster in Ortszeit, bis zu 92 Tage pro Abruf. Ruhetage und Öffnungszeiten sind schon eingerechnet – ideal für deinen eigenen Datumswähler. Verbindlich prüfen POST /v1/quotes und die Kasse.

Antwort (gekürzt)
{
  "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

Verifizierte Bewertungen eines Rads, neueste zuerst, mit Durchschnitt und Gesamtzahl. Verfasser erscheinen mit Vorname und Initial. Alle Bewertungen eines Vermieters: GET /v1/listers/{id}/reviews.

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

Öffentliches Profil eines Vermieters: Name, Standort, Bewertung, abgeschlossene Buchungen, Anzahl Räder, Sofortbestätigung, Buchungsregeln, Öffnungszeiten und Lieferzonen. Privatvermieter erscheinen mit Vorname und ohne Straße.

GET/v1/cancellation-policyrides:read

Die Stornoregeln, die für jede Buchung gelten: ab 72 Stunden vor Abholung wird alles erstattet, darunter ein Anteil der Miete je Zeitfenster. Storniert der Vermieter, bekommt der Kunde alles zurück.

GET/v1/categoriesrides:read

Alle Kategorien mit deutschem und englischem Namen. Eine Oberkategorie wie e-bike schließt bei der Suche ihre Unterkategorien ein.

GET/v1/placesrides:read

Alle Orte mit buchbaren Rädern, die mit den meisten Rädern zuerst. Mit q suchst du in allen Sprachen (z. B. q=münch), mit country filterst du nach Land, locale wählt die Sprache der Namen. Einzelner Ort: GET /v1/places/{id}.

GET/v1/classesrides:read

Statt eines bestimmten Rads bucht dein Kunde eine Klasse – z. B. „E-Bike, Mittelklasse“ in Berlin – und ListNRide findet einen passenden Verleiher. Abfrage mit place oder lat/lng. Gebucht wird über eine Kassensitzung mit class und size (Fahrergröße).

Antwort (gekürzt)
{
  "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

Berechnet den genauen Preis wie die ListNRide-Kasse: Miete, Rabatt, Servicegebühr, Basisversicherung, Extras (insurance_plus) und Lieferung an eine Adresse – ohne etwas zu reservieren. Ein Angebot umfasst Räder eines Vermieters oder eine Klasse.

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

Legt eine Kassensitzung an. Preis und Verfügbarkeit prüft dabei die ListNRide-Kasse. Der Link ist 24 Stunden gültig; Anzahl und Uhrzeiten sind in der Kasse vorausgewählt.

FeldBedeutung
ride *Rad-ID ride_…
class, sizeStatt ride: Klasse aus GET /v1/classes und Fahrergröße (165-175 … oder Unisize)
from, to *Abhol- und Rückgabetag, YYYY-MM-DD
pickup_time, return_timeHH:MM, Standard 10:00 / 17:00
quantityAnzahl, 1–50, Standard 1
return_url *Hierhin kommt der Kunde nach der Buchung zurück (https), mit checkout_session, booking und status=success
cancel_urlOptional, für den Abbruch (https)
localede · en · fr · es · it · nl
client_referenceDeine eigene Nummer
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://deine-seite.de/danke",
    "locale": "de"
  }'

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

Status der Sitzung: open, booked (mit booking-ID) oder expired.

GET/v1/bookings/{id}bookings:read
statusBedeutung
awaiting_paymentKunde ist in der Kasse, noch nicht bezahlt
requestedBezahlt bzw. vorgemerkt, Vermieter muss zusagen
acceptedVermieter hat zugesagt, Zahlung läuft
confirmedFest gebucht
completedMiete abgeschlossen
canceled_by_lister · canceled_by_customer · canceledStorniert
expiredNicht bezahlt oder nicht rechtzeitig angenommen
GET/v1/bookingsbookings:read

Alle Buchungen aus deinen Kassensitzungen, neueste zuerst. Filter nach status oder deiner client_reference. Ein Testschlüssel listet Testbuchungen, ein Live-Schlüssel echte Buchungen. Stornierte Buchungen tragen cancellation mit Erstattungsbetrag und -status.

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

Storniert eine Buchung im Namen deines Kunden – nach denselben Regeln wie auf listnride.com: ab 72 Stunden vor Abholung wird alles erstattet, darunter ein Anteil der Miete. Der Vermieter wird benachrichtigt, du bekommst booking.canceled_by_customer, und die Erstattung geht auf das Zahlungsmittel des Kunden zurück.

Vorher prüfen mit GET /v1/bookings/{id}/cancellation – zeigt, ob ein Storno möglich ist, und die genaue Erstattung, ohne etwas zu ändern. Stornieren braucht den Scope bookings:cancel, den wir auf Wunsch freischalten. Optional: reason (changed_mind, found_better, timing_issue, price_too_high, personal_reasons, other) und comment.

curl
# 1. Vorschau: geht ein Storno, und was bekommt der Kunde zurück?
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. Stornieren
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

Häng ?aff=DEINCODE an jeden ListNRide-Link – jede Seite, jede Sprache. Bucht der Kunde innerhalb der vereinbarten Frist, zählt die Buchung für dich; der letzte Klick gewinnt. Buchungen über deine Kassensitzungen zählen immer für dich, auch ohne Klick.

Die Provision wird individuell vereinbart und richtet sich nach den Gebühren, die ListNRide an der Buchung verdient. Sie zählt, sobald die Miete beendet ist; storniert der Vermieter, gibt es keine. GET /v1/commissions zeigt Klicks, Buchungen, Stufe und Provision je Monat – ohne Kundendaten. Abgerechnet wird monatlich per Gutschrift.

Link & Auswertung
# Partner-Link – funktioniert auf jeder Seite
https://www.listnride.de/berlin/e-bike?aff=NEEDABIKE

# Deine Provision für einen Monat
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"
Mehr

Benachrichtigungen

Ändert sich der Status einer Buchung, schicken wir ein POST an deine hinterlegte Adresse, z. B. booking.confirmed. Antworte mit 2xx – sonst versuchen wir es nach 1 Min., 5 Min., 30 Min. und bis zu 24 Std. erneut. Mit ping kannst du die Verbindung testen; die Ereignis-id bleibt bei Wiederholungen gleich.

Prüfe jede Nachricht mit der Kopfzeile LNR-Signature: t=…,v1=…: HMAC-SHA256 über t + "." + body mit deinem Geheimnis whsec_…. Rechne mit dem unveränderten Body und weise Nachrichten ab, deren t älter als 5 Minuten ist.

Beispiel: booking.confirmed
POST https://deine-seite.de/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"
  } }
}
Signatur prüfen
const crypto = require("crypto");

// rawBody: der unveränderte Body, wie er ankam
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));
}
Mehr

Fehler & Limits

Fehler haben immer dieselbe Form. Mit der request_id finden wir deinen Fall schnell.

Grenzen pro Schlüssel: ein Minutenlimit und ein Tageskontingent (Kopfzeilen X-Quota-Limit, X-Quota-Remaining). Eine Suche lässt sich höchstens 500 Treffer tief durchblättern – grenze sie mit Ort, Radius, Kategorie oder Zeitraum ein. Massenabruf und Weiterverkauf der Daten sind nicht erlaubt.

Sicher wiederholen: Schick bei POST /v1/checkout/sessions und POST /v1/bookings/{id}/cancel den Kopf Idempotency-Key mit. Eine Wiederholung mit gleichem Schlüssel und gleichem Inhalt liefert die erste Antwort (Kopf Idempotent-Replayed: true), statt doppelt zu handeln. Schlüssel gelten 24 Stunden.

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

SDKs & Werkzeuge

Offizielle Clients als einzelne Datei ohne Abhängigkeiten – einfach ins Projekt kopieren. Sie übernehmen Anmeldung, Blättern, Wiederholung bei 429/5xx, Idempotency-Keys und die Prüfung von Benachrichtigungen.

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" });  // Idempotency-Key wird automatisch gesetzt
Mehr

Versionen

Die Version steht im Pfad. Innerhalb von /v1 kommen nur Felder dazu – nichts wird entfernt oder umbenannt. Größere Änderungen erscheinen als /v2, und /v1 läuft mindestens 12 Monate weiter. Die maschinenlesbare Beschreibung (OpenAPI 3.1) liegt unter /openapi.json bzw. https://api.listnride.com/v1/openapi.json.

Mehr

Änderungen

  1. Idempotency-Key für schreibende Aufrufe, Postman-Sammlung, offizielle Clients für Node.js, PHP und Python.

  2. Affiliate: Partner-Links mit ?aff=CODE und GET /v1/commissions.

  3. GET /v1/bookings, Storno-Vorschau und POST /v1/bookings/{id}/cancel (Scope bookings:cancel).

  4. Suchfilter (Preis, Körpergröße, Zubehör, Kartenausschnitt …), Preisstaffel, Öffnungszeiten, Stornoregeln, Verfügbarkeitskalender, Bewertungen und Vermieterprofile.

  5. Orte, Fahrzeugklassen, POST /v1/quotes, Buchung nach Klasse und ein Tageskontingent je Schlüssel.

  6. Start von v1: Räder, Kategorien, Kassensitzungen, Buchungen, Benachrichtigungen und Testmodus.

Zugang anfragen

Schreib uns mit deiner Website und was du vorhast. Du bekommst zuerst einen Testschlüssel – live geht es nach einem kurzen Gespräch.

partner@listnride.com

Zugang anfragen

Erzähl uns kurz, wer du bist und was du vorhast. Du bekommst zuerst einen Testschlüssel – live geht es nach einem kurzen Gespräch.

Lieber per Mail? partner@listnride.com