Introduction
REST-Schnittstelle für Landingpages zur Angebots- und Buchungsanfrage von Fahrten bei Primos.
Diese Schnittstelle erlaubt es Landingpages (LPs), bei Primos ein Angebot für eine Fahrt anzufragen
(verfügbare Fahrzeuge, Distanz, Preise) und anschließend eine Buchung anzulegen. Eine Buchung erzeugt
im Primos-CRM eine Fahrt (Status „Anfrage") und löst dort die üblichen Automatismen aus.
**Typischer Ablauf:**
1. `POST /api/v1/quotes` – Angebot anfragen. Antwort enthält `quote_id` sowie ein einmalig sichtbares `quote_token`.
2. `POST /api/v1/bookings` – mit `quote_id`, `quote_token` und gewähltem `vehicle_id` buchen.
Preise sind im Angebot eingefroren; die Buchung verwendet ausschließlich den serverseitig berechneten Preis.
Ein Angebot ist zeitlich begrenzt gültig und kann nur einmal gebucht werden.
Authenticating requests
To authenticate requests, include an Authorization header with the value "Bearer {YOUR_AUTH_KEY}".
All authenticated endpoints are marked with a requires authentication badge in the documentation below.
Jeder Zugang gehört zu einer Auftragsquelle. Das Bearer-Token wird von Primos im Admin-Bereich erstellt und verwaltet. Token besitzen Berechtigungen: quote (Angebote) und book (Buchungen).
Origin-Beschränkung (optional): Für eine Auftragsquelle kann eine Liste erlaubter Origins hinterlegt sein. Ist sie gesetzt, werden Browser-Anfragen nur von einer dieser Origins akzeptiert (sonst 403); Anfragen ohne Origin-Header (Server-zu-Server) sind nicht betroffen. Ist keine Liste hinterlegt, gilt keine Einschränkung. Bei Bedarf teilt Primos die freigeschalteten Origins mit.
Angebote
Angebot anfragen
requires authentication
Berechnet für die angegebene Strecke die verfügbaren Fahrzeuge samt Distanz und Preisen und legt ein zeitlich begrenztes Angebot an.
Locator-Regeln (identisch zum Website-Rechner): Jede Seite (pickup/destination) ist
entweder eine Adresse oder ein Flughafen.
- Adress-Seite:
place_id(Pflicht, aus Google Places Autocomplete) plusformatted_address,streetundhouse_number. Es wird ausschließlich über dieplace_idgeroutet – reine Koordinaten oder Freitext-Adressen werden nicht akzeptiert, damit Distanz und Preis exakt mit der Website übereinstimmen und keine Abweichungen entstehen. - Flughafen-Seite: ausschließlich
airport_iataausGET /api/v1/airports. place_id, Koordinaten und Anzeigename löst Primos serverseitig auf.
Bei type=airport muss genau eine Seite ein airport_iata enthalten (die andere ist eine
Adress-Seite); bei type=transfer sind beide Seiten Adress-Seiten und airport_iata ist nicht erlaubt.
Example request:
curl --request POST \
"https://primos-fahrservice.de/api/v1/quotes" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"type\": \"airport\",
\"pickup\": {
\"airport_iata\": \"fra\",
\"place_id\": \"ChIJ7cv00DwsDogRAMDACa2m4K8\",
\"formatted_address\": \"Bahnhofstraße 1, 65552 Limburg an der Lahn, Deutschland\",
\"street\": \"Bahnhofstraße\",
\"house_number\": \"1\",
\"postal_code\": \"65552\",
\"city\": \"Limburg an der Lahn\"
},
\"destination\": {
\"airport_iata\": \"fra\",
\"place_id\": \"ChIJeflCVHQLvUcRMfP4IU3YdIo\",
\"formatted_address\": \"Zeil 1, 60313 Frankfurt am Main, Deutschland\",
\"street\": \"Zeil\",
\"house_number\": \"1\",
\"postal_code\": \"60313\",
\"city\": \"Frankfurt am Main\"
},
\"pickup_time\": \"2026-07-10T14:30:00+02:00\",
\"roundtrip\": false,
\"passengers\": 1,
\"child_seats\": 0,
\"flight_number\": \"LH123\",
\"options\": {
\"sign_service\": false
}
}"
const url = new URL(
"https://primos-fahrservice.de/api/v1/quotes"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"type": "airport",
"pickup": {
"airport_iata": "fra",
"place_id": "ChIJ7cv00DwsDogRAMDACa2m4K8",
"formatted_address": "Bahnhofstraße 1, 65552 Limburg an der Lahn, Deutschland",
"street": "Bahnhofstraße",
"house_number": "1",
"postal_code": "65552",
"city": "Limburg an der Lahn"
},
"destination": {
"airport_iata": "fra",
"place_id": "ChIJeflCVHQLvUcRMfP4IU3YdIo",
"formatted_address": "Zeil 1, 60313 Frankfurt am Main, Deutschland",
"street": "Zeil",
"house_number": "1",
"postal_code": "60313",
"city": "Frankfurt am Main"
},
"pickup_time": "2026-07-10T14:30:00+02:00",
"roundtrip": false,
"passengers": 1,
"child_seats": 0,
"flight_number": "LH123",
"options": {
"sign_service": false
}
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"data": {
"quote_id": "9b1f2c34-1a2b-4c3d-8e9f-000000000000",
"type": "transfer",
"distance_km": 42,
"roundtrip": true,
"currency": "EUR",
"expires_at": "2026-07-15T14:30:00+02:00",
"vehicles": [
{
"vehicle_id": 3,
"name": "Business Van",
"passengers": 7,
"luggage": 7,
"child_seats": 3,
"image": "vehicles/van.jpg",
"price": {
"amount": 189,
"currency": "EUR",
"roundtrip_included": true
}
}
]
},
"meta": {
"quote_token": "einmalig-sichtbarer-token"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Angebot abrufen
requires authentication
Liefert ein zuvor erstelltes Angebot erneut (ohne das einmalige Token).
Example request:
curl --request GET \
--get "https://primos-fahrservice.de/api/v1/quotes/019f435c-eb4e-732a-8a53-03b2e1a7f6f6" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://primos-fahrservice.de/api/v1/quotes/019f435c-eb4e-732a-8a53-03b2e1a7f6f6"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"quote_id": "9b1f2c34-1a2b-4c3d-8e9f-000000000000",
"type": "transfer",
"distance_km": 42,
"roundtrip": true,
"currency": "EUR",
"expires_at": "2026-07-15T14:30:00+02:00",
"vehicles": [
{
"vehicle_id": 3,
"name": "Business Van",
"passengers": 7,
"luggage": 7,
"child_seats": 3,
"image": "vehicles/van.jpg",
"price": {
"amount": 189,
"currency": "EUR",
"roundtrip_included": true
}
}
]
}
}
Example response (404):
{
"message": "No query results for model [App\\Models\\Quote]."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Authentifizierung
Eigene Auftragsquelle
requires authentication
Gibt die zum Token gehörende Auftragsquelle samt Berechtigungen zurück – nützlich als Token-Check.
Example request:
curl --request GET \
--get "https://primos-fahrservice.de/api/v1/me" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://primos-fahrservice.de/api/v1/me"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"name": "LP Flughafentransfer FFM",
"slug": "lp-ffm",
"contact_email": "[email protected]",
"is_active": true,
"abilities": [
"quote",
"book"
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Buchungen
Fahrt buchen
requires authentication
Bucht ein zuvor erstelltes Angebot und legt im CRM eine Fahrt an (Status „Anfrage"), wodurch die Automatismen (Benachrichtigungen, Kalender) ausgelöst werden. Der Preis wird immer aus dem Angebot übernommen – ein im Request gesendeter Preis wird ignoriert.
Optionaler Header Idempotency-Key: Wird derselbe Schlüssel erneut gesendet, wird die
bereits erstellte Buchung zurückgegeben (Status 200 statt 201), ohne eine zweite Fahrt anzulegen.
Example request:
curl --request POST \
"https://primos-fahrservice.de/api/v1/bookings" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Idempotency-Key: abc-123" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"quote_id\": \"6ff8f7f6-1eb3-3525-be4a-3932c805afed\",
\"quote_token\": \"architecto\",
\"vehicle_id\": 16,
\"customer\": {
\"firstname\": \"b\",
\"lastname\": \"n\",
\"email\": \"[email protected]\",
\"phone\": \"v\"
},
\"payment_method\": \"paypal\",
\"billing\": {
\"different\": true,
\"name\": \"d\",
\"street\": \"l\",
\"house_number\": \"j\",
\"postal_code\": \"nikhwaykcmyuwpwl\",
\"city\": \"v\"
},
\"notes\": \"q\",
\"reference\": \"w\"
}"
const url = new URL(
"https://primos-fahrservice.de/api/v1/bookings"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Idempotency-Key": "abc-123",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"quote_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed",
"quote_token": "architecto",
"vehicle_id": 16,
"customer": {
"firstname": "b",
"lastname": "n",
"email": "[email protected]",
"phone": "v"
},
"payment_method": "paypal",
"billing": {
"different": true,
"name": "d",
"street": "l",
"house_number": "j",
"postal_code": "nikhwaykcmyuwpwl",
"city": "v"
},
"notes": "q",
"reference": "w"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"data": {
"booking_id": 12345,
"status": "inquiry",
"type": "transfer",
"vehicle": {
"vehicle_id": 3,
"name": "Business Van"
},
"pickup_time": "2026-07-15T14:30:00+02:00",
"roundtrip": true,
"external_reference": "LP-ORDER-5567",
"price": {
"amount": 189,
"currency": "EUR"
},
"created_at": "2026-07-08T12:00:00+02:00"
}
}
Example response (409):
{
"message": "Angebot ist abgelaufen oder wurde bereits gebucht."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Buchungsstatus abrufen
requires authentication
Liefert den aktuellen Status einer Buchung (z. B. inquiry, confirmed, booked, done).
Example request:
curl --request GET \
--get "https://primos-fahrservice.de/api/v1/bookings/40" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://primos-fahrservice.de/api/v1/bookings/40"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"booking_id": 12345,
"status": "confirmed",
"type": "transfer",
"vehicle": {
"vehicle_id": 3,
"name": "Business Van"
},
"pickup_time": "2026-07-15T14:30:00+02:00",
"roundtrip": true,
"external_reference": "LP-ORDER-5567",
"price": {
"amount": 189,
"currency": "EUR"
},
"created_at": "2026-07-08T12:00:00+02:00"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Fahrzeuge
Fahrzeugkatalog
requires authentication
Liefert die aktuell angebotenen Fahrzeuge (ohne Preise – Preise entstehen erst im Angebot).
Example request:
curl --request GET \
--get "https://primos-fahrservice.de/api/v1/vehicles" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://primos-fahrservice.de/api/v1/vehicles"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"vehicle_id": 3,
"name": "Business Van",
"description": "Bis zu 7 Personen",
"passengers": 7,
"luggage": 7,
"child_seats": 3,
"image": "vehicles/van.jpg"
},
{
"vehicle_id": 1,
"name": "Business Limousine",
"description": "Mercedes E-Klasse o. ä.",
"passengers": 3,
"luggage": 3,
"child_seats": 1,
"image": "vehicles/limo.jpg"
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Flughäfen
Flughäfen
requires authentication
Liefert die aktuell bedienten Flughäfen. Der zurückgegebene iata-Wert ist exakt der Wert,
der bei type=airport-Angeboten als pickup.airport_iata bzw. destination.airport_iata
gesendet werden muss. Bitte diese Liste als einzige Quelle für gültige IATA-Codes nutzen und
die Werte unverändert übernehmen (der Vergleich erfolgt case-sensitive) – so entstehen keine
Abweichungen zwischen Landingpage und Angebotsanfrage.
Die mitgelieferten Koordinaten (lat/lng) und die Google-place_id entsprechen dem, was
Primos serverseitig für die Distanzberechnung verwendet, und können für ein eigenes
Google-Maps-Autocomplete genutzt werden.
Example request:
curl --request GET \
--get "https://primos-fahrservice.de/api/v1/airports" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://primos-fahrservice.de/api/v1/airports"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"iata": "fra",
"name": "Frankfurt International Airport",
"lat": 50.0353788,
"lng": 8.5518391,
"place_id": "ChIJeflCVHQLvUcRMfP4IU3YdIo"
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Status
Public liveness endpoint.
Example request:
curl --request GET \
--get "https://primos-fahrservice.de/api/v1/health" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://primos-fahrservice.de/api/v1/health"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
Show headers
cache-control: no-cache, private
content-type: application/json
x-ratelimit-limit: 60
x-ratelimit-remaining: 59
access-control-allow-origin: *
{
"status": "ok",
"api": "primos-lp",
"version": "v1"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.