Introduction
Blue's LTCR Workshop Booking API lets long-term-rental partner integrators — such as the team that operates bluecarrental.is — book workshop service appointments (tire change, oil and lube service, or other work) on behalf of the long-term-rental customers they serve, for the cars those customers are renting from Blue Car Rental. It replaces a previous manual booking workflow.
Base URLs
| Environment | Base URL |
|---|---|
| Production | https://ltcr-workshop-booking-api.bluecarrental.is |
| Staging | https://ltcr-workshop-booking-api.staging.bluecarrental.is |
API version
This document covers v1. All paths are prefixed with /api/v1/workshop. All timestamps are RFC 3339 in UTC. Requests and responses are JSON.
Getting started
Four steps to your first booking:
- Request an API key from Blue Car Rental (see Authentication).
- Call
GET /api/v1/workshop/locationsto list active workshop locations. - Call
GET /api/v1/workshop/availabilityto retrieve bookable slots for the location and date range your customer is choosing from. - Call
POST /api/v1/workshop/bookingswith the chosen slot and the customer's contact details. The response includes a tokenised cancel URL Blue Car Rental will email the customer.
End-to-end example
# 1. List locations curl -s https://ltcr-workshop-booking-api.bluecarrental.is/api/v1/workshop/locations \ -H "X-API-Key: bws_a1b2c3d4_" # 2. Check availability for Keflavík next week curl -s "https://ltcr-workshop-booking-api.bluecarrental.is/api/v1/workshop/availability?location=keflavik&from=2026-05-19&to=2026-05-23" \ -H "X-API-Key: bws_a1b2c3d4_ " # 3. Book the 09:00 slot on 2026-05-19 curl -s -X POST https://ltcr-workshop-booking-api.bluecarrental.is/api/v1/workshop/bookings \ -H "X-API-Key: bws_a1b2c3d4_ " \ -H "Content-Type: application/json" \ -H "Idempotency-Key: 9b1c-7e2f-2026-05-19-keflavik-AB123" \ -d '{ "location": "keflavik", "slot_start_at": "2026-05-19T09:00:00Z", "service_type": "dekkjaskipti", "customer": {"name": "Kalli Bimbo", "email": "kalli@example.is", "phone": "+3546901588"}, "license_plate": "AB123" }'
Authentication
Every request must include an API key in the X-API-Key header. Keys are issued by Blue Car Rental — there is no self-service signup.
Header
X-API-Key: bws_a1b2c3d4_e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0
Key format
An API key is three underscore-separated parts: a fixed scheme tag, a public prefix, and a secret.
| Part | Example | Notes |
|---|---|---|
bws | bws | Scheme tag. Always bws. |
| Prefix | a1b2c3d4 | 8 hex characters. Identifies your partner record. Safe to log. |
| Secret | e5f6…b0 | 32 hex characters. Never log, never expose to the customer browser. |
Onboarding
Email Blue Car Rental to request a key. You will receive one production key and one staging key. Keys are not recoverable: if you lose a key, Blue Car Rental rotates it and issues a new one.
Rotation and deactivation
Blue Car Rental can rotate or deactivate any key at any time. Your integration should handle:
401 unauthorized— the key is missing, malformed, or no longer recognised. Stop sending requests with that key and contact Blue Car Rental.403 forbidden— the key is recognised but the partner has been deactivated.
Concepts
Locations
A location is a physical workshop site. The v1 launch ships with one location: keflavik (Keflavík). The schema is multi-location-ready; new locations are added over time by Blue Car Rental.
Slots and availability
Slots are not stored — they are derived per request from operating-hour rules, blackouts, and existing bookings. Always call /availability immediately before showing a calendar to the customer. Do not cache slots client-side. The server caches the response for 30 seconds.
Service types
| Value | Meaning |
|---|---|
dekkjaskipti | Tire change. |
smurthjonusta | Oil and lube service. |
annad | Other / free-form (use the message field on the booking to describe). |
Idempotency
The POST /bookings endpoint accepts an Idempotency-Key header (≤255 characters). Replaying the same key with the same payload returns the original booking instead of creating a duplicate. Replaying the same key with a different payload returns 409 idempotency_conflict. Keys are honoured for 24 hours; after that they are pruned and a replay creates a new booking.
Cancellation flow
When a booking is created, Blue Car Rental emails the customer a confirmation with a tokenised cancel link. The customer clicks the link to cancel. Partners do not call /cancel directly — the endpoint is documented for completeness only.
Rate limits
| Scope | Limit |
|---|---|
| Per IP, global | 1000 requests/minute |
| Per API key, all endpoints | 500 requests/minute |
Per API key, POST /bookings | 60 requests/minute |
Exceeded → 429 rate_limited with a Retry-After header. Back off and retry.
Time zones
All slot_start_at values are UTC. The workshop in Keflavík operates in Atlantic/Reykjavik. Render times in the customer's local timezone in your UI, but always send and store UTC.
List locations
List active workshop locations.
Request
curl -s https://ltcr-workshop-booking-api.bluecarrental.is/api/v1/workshop/locations \ -H "X-API-Key: bws_a1b2c3d4_<your-secret>"
Response
200 Success
{
"locations": [
{"slug": "keflavik", "name": "Keflavík", "timezone": "Atlantic/Reykjavik"}
]
}
Use the slug value as the location parameter in subsequent calls.
Check availability
List bookable slots in a date range for a single location.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
location | string | Yes | Location slug (e.g. keflavik). |
from | date (YYYY-MM-DD) | Yes | Inclusive. |
to | date (YYYY-MM-DD) | Yes | Inclusive. Max 90 days from from. |
service_type | string | No | Accepted but ignored in v1. |
Request
curl -s "https://ltcr-workshop-booking-api.bluecarrental.is/api/v1/workshop/availability?location=keflavik&from=2026-05-19&to=2026-05-23" \ -H "X-API-Key: bws_a1b2c3d4_<your-secret>"
Response
200 Success
{
"location": "keflavik",
"slots": [
{"start_at": "2026-05-19T09:00:00Z", "end_at": "2026-05-19T10:00:00Z"},
{"start_at": "2026-05-19T10:00:00Z", "end_at": "2026-05-19T11:00:00Z"}
]
}
Create a booking
Create a workshop booking.
Headers
| Name | Required | Notes |
|---|---|---|
X-API-Key | Yes | Your partner API key. |
Content-Type | Yes | application/json. |
Idempotency-Key | No (recommended) | Up to 255 chars. See Concepts → Idempotency. |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
location | string | Yes | Location slug. |
slot_start_at | string (RFC 3339 UTC) | Yes | Must align with a slot returned by /availability. |
service_type | string | Yes | One of dekkjaskipti, smurthjonusta, annad. |
customer.name | string | Yes | |
customer.email | string | Yes | Confirmation email is sent here. |
customer.phone | string | Yes | E.164 recommended. |
license_plate | string | Yes | Plate of the long-term rental car. |
mileage | integer | No | Current odometer. |
message | string | No | Free text from the customer. |
Request
curl -s -X POST https://ltcr-workshop-booking-api.bluecarrental.is/api/v1/workshop/bookings \
-H "X-API-Key: bws_a1b2c3d4_<your-secret>" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 9b1c-7e2f-2026-05-19-keflavik-AB123" \
-d '{
"location": "keflavik",
"slot_start_at": "2026-05-19T09:00:00Z",
"service_type": "dekkjaskipti",
"customer": {"name": "Kalli Bimbo", "email": "kalli@example.is", "phone": "+3546901588"},
"license_plate": "AB123",
"mileage": 12345,
"message": "Vil skipta yfir í sumardekk."
}'
Response
201 Created
{
"booking_id": "5f8e3b1c-4e2a-4a91-9b8f-2c7d6e5a4b3c",
"status": "active",
"location": "keflavik",
"slot_start_at": "2026-05-19T09:00:00Z",
"slot_end_at": "2026-05-19T10:00:00Z",
"service_type": "dekkjaskipti",
"cancel_url": "https://ltcr-workshop-booking-api.bluecarrental.is/api/v1/workshop/bookings/5f8e3b1c-4e2a-4a91-9b8f-2c7d6e5a4b3c/cancel?token=..."
}
Error responses
400 validation_failed— malformed body, missing field, invalid email, or slot is in the past.401 unauthorized— missing or invalid API key.403 forbidden— partner deactivated.409 slot_taken— that slot was just booked. Terminal — do not retry. Show the customer a different slot.409 idempotency_conflict— sameIdempotency-Keyreused with a different payload. Generate a new key.422 slot_unavailable— slot is outside operating hours, on a blackout, or otherwise no longer offered. Refresh availability.429 rate_limited— see Concepts → Rate limits.5xx internal_error— safe to retry with the sameIdempotency-Key.
Read a booking
Read a booking record. Two authentication modes are supported.
Authentication modes
| Mode | How | When to use |
|---|---|---|
| API key | X-API-Key header | Partner backend reading the booking. |
| Cancel token | ?token=<cancel_token> query string | Partner frontend confirmation page (no API secret in the browser bundle). |
Request
curl -s https://ltcr-workshop-booking-api.bluecarrental.is/api/v1/workshop/bookings/5f8e3b1c-4e2a-4a91-9b8f-2c7d6e5a4b3c \ -H "X-API-Key: bws_a1b2c3d4_<your-secret>"
Response
200 Success
{
"booking_id": "5f8e3b1c-4e2a-4a91-9b8f-2c7d6e5a4b3c",
"status": "active",
"location": "keflavik",
"slot_start_at": "2026-05-19T09:00:00Z",
"slot_end_at": "2026-05-19T10:00:00Z",
"service_type": "dekkjaskipti",
"customer": {"name": "Kalli Bimbo", "email": "kalli@example.is", "phone": "+3546901588"},
"license_plate": "AB123",
"mileage": 12345,
"message": "Vil skipta yfir í sumardekk.",
"cancelled_at": null
}
Error responses
401 unauthorized— missing or invalid API key (API-key mode only).403 forbidden— cancel token does not match this booking.404 not_found— booking ID does not exist.
Cancel a booking
Single-click cancellation via the tokenised link in the confirmation email.
Query parameters
| Name | Required | Notes |
|---|---|---|
token | Yes | The cancel token from the confirmation email. |
Response
Determined by the Accept header:
text/html(the default for browsers) — renders a bilingual confirmation page. If the partner has acancel_redirect_urlconfigured, the response is a302redirect there with?status=cancelledappended.application/json— returns the JSON shape below.
200 Cancelled (JSON)
{
"booking_id": "5f8e3b1c-4e2a-4a91-9b8f-2c7d6e5a4b3c",
"status": "cancelled",
"cancelled_at": "2026-05-17T14:23:08Z"
}
Error responses
403 forbidden— token invalid.404 not_found— booking ID unknown.409 already_cancelled— booking is already cancelled. Idempotent: still returns200with the existingcancelled_at.409 too_late_to_cancel— the slot start is in the past.
Errors
Errors return a uniform JSON envelope:
{
"error": "slot_taken",
"message": "That slot was just booked. Please choose another time.",
"details": {
"slot_start_at": "2026-05-19T09:00:00Z"
}
}
HTTP status codes
| Status | Meaning | Retry? |
|---|---|---|
400 validation_failed | Malformed request body or missing/invalid field. | No. |
401 unauthorized | Missing or invalid API key. | No. Stop and contact Blue Car Rental. |
403 forbidden | Partner deactivated, or cancel token does not match. | No. |
404 not_found | Booking ID unknown. | No. |
409 slot_taken | Slot was just booked by someone else. | No — terminal. Offer a different slot. |
409 idempotency_conflict | Same Idempotency-Key, different payload. | No. Generate a new key. |
409 already_cancelled | Booking already cancelled (cancel endpoint only). | No — treated as success. |
409 too_late_to_cancel | Slot start is in the past (cancel endpoint only). | No. |
422 slot_unavailable | Slot is outside operating hours, on a blackout, or otherwise no longer offered. | No. Refresh /availability. |
429 rate_limited | Rate limit exceeded. | Yes, after Retry-After. |
5xx internal_error | Server-side failure. | Yes, with the same Idempotency-Key and exponential backoff. |
Retry guidance
- Retry
429and5xxwith exponential backoff (e.g. 1s, 2s, 4s, 8s, cap at 60s). - Always include the original
Idempotency-Keywhen retryingPOST /bookings— without it, retries may create duplicate bookings. - Never retry any other
4xx.