Management API
Read and write your fleet, pricing, and settings over the REST API
The management API lets an integration change the same data the admin panel does — vehicles, categories, addons, coupons, locations, seasons, pricing, and tenant settings — without a browser session. It lives under /api/v1/manage and is the write half of the CR Bee REST API.
Typical uses: syncing a fleet from another system, bulk price updates at the start of a season, or scripting the setup of a new account.
Creating a read & write key
Every /manage endpoint — including the GETs — needs an API key created with write access. An ordinary key returns 403.
- Go to Settings > API Keys
- Click Create API Key
- Enter a Key name (e.g. "Fleet sync")
- Tick Read & write
- Click Generate Key and copy the key — it is shown only once
Keys with write access are marked Read & write in the key list.
A read & write key can change your fleet, your prices and your public settings, and it can delete records. It is not limited to a subset of them. Only issue one to an integration you control, keep it out of browser code, and revoke it the moment it is no longer needed.
Making a request
Base URL:
https://your-slug.crbeeapp.com/api/v1Custom domains work too: https://your-domain.com/api/v1.
Send the key as a bearer token and JSON as the body:
Authorization: Bearer crb_live_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4
Content-Type: application/jsonEvery successful response wraps its payload in a data key:
| Request | Response body |
|---|---|
GET /manage/cars | { "data": [ { ...car }, ... ] } |
GET /manage/cars/{id} | { "data": { ...car } } |
POST /manage/cars | { "data": { "id": "car_..." } } (status 201) |
PUT /manage/cars/{id} | { "data": { "id": "car_..." } } |
DELETE /manage/cars/{id} | { "data": { "id": "car_..." } } |
A create or replace returns only the ID. Read the record back if you need the stored row.
Resources
The same five operations — list, create, read, replace, delete — exist for each of these, at /manage/{resource}:
| Resource | Path |
|---|---|
| Vehicles | /manage/cars |
| Categories | /manage/categories |
| Feature labels | /manage/features |
| Addons | /manage/addons |
| Coupons | /manage/coupons |
| Locations | /manage/locations |
| Seasons | /manage/seasons |
| Duration tiers | /manage/duration-tiers |
| Price groups | /manage/price-groups |
| Pricing adjustments | /manage/pricing-adjustments |
| Availability blocks | /manage/availability-blocks |
| Price group mappings | /manage/price-group-maps |
Price group mappings have no replace operation — PUT /manage/price-group-maps/{id} answers 405. Delete the mapping and create the replacement.
Updates are PUT, and a PUT sends the complete record. The body is validated by the same schema as POST, so a field you leave out is written with that field's default rather than keeping the value already stored. The working pattern is: GET the record, change what you need in the object you got back, PUT the whole thing.
Operations that are not plain CRUD
| Operation | Endpoint |
|---|---|
| Clone a vehicle | POST /manage/cars/{id}/clone |
| Duplicate a season with its prices | POST /manage/seasons/{id}/duplicate |
| Read tenant settings | GET /manage/settings |
| Replace tenant settings | PUT /manage/settings |
| Reorder addons or locations | PUT /manage/sort-order |
| Read / replace one-way fees | GET / PUT /manage/location-fees |
| Read / save pricing rules | GET / PUT /manage/pricing-rules |
| Copy prices between seasons | POST /manage/pricing-rules/copy-season |
PUT /manage/location-fees and PUT /manage/pricing-rules take a batch and apply it in one transaction. These two are the exception to the replace rule: entries you do not send are left alone, and a null price (pricePerDay for rules, feeValue for fees) deletes that entry.
PUT /manage/settings follows the same contract as the resource PUTs — it writes the whole settings object, so start from GET /manage/settings. It also accepts two optional fields that are not stored, labels_locale and trust_locale, naming which locale the labels and the trust banners/messages in the request belong to. Both default to the tenant's default locale.
Errors
Errors are JSON with an error string, and details on a validation failure:
{
"error": "Validation error",
"details": {
"slug": ["Slug must be lowercase alphanumeric with hyphens"]
}
}| Status | Meaning |
|---|---|
400 | The body failed validation, or a referenced record does not exist |
401 | The API key is missing, malformed, expired, or wrong |
403 | The key is valid but was not created with read & write access |
404 | Unknown resource name, or no such record for this tenant |
405 | That resource has no replace operation — only /manage/price-group-maps |
409 | A conflict — a duplicate slug, name or coupon code; a block overlapping confirmed bookings; deleting the default price group |
429 | Rate limited — see Retry-After |
500 | The write failed. Nothing was saved |
An ID belonging to another tenant answers 404, never 403.
Rate limits
Limits are per API key, in a one-minute window:
| Limit | |
|---|---|
Reads (GET) | 60 requests/minute |
Writes (POST, PUT, DELETE) | 30 requests/minute |
Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset; a 429 also carries Retry-After in seconds. See Rate Limits.
Examples
Add a vehicle
curl -X POST https://your-slug.crbeeapp.com/api/v1/manage/cars \
-H "Authorization: Bearer crb_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Toyota Yaris",
"slug": "toyota-yaris",
"categoryId": "cat_abc123",
"description": "Compact, fuel-efficient hatchback",
"quantity": 4,
"transmission": "manual",
"fuelType": "petrol",
"seats": 5,
"doors": 5,
"status": "published"
}'{ "data": { "id": "car_xyz789" } }The car is created as a draft unless you send "status": "published".
Change a price
Prices live in pricing rules, one per car (or category) × season × duration tier × price group. Save them in a batch:
curl -X PUT https://your-slug.crbeeapp.com/api/v1/manage/pricing-rules \
-H "Authorization: Bearer crb_live_..." \
-H "Content-Type: application/json" \
-d '{
"rules": [
{
"scopeType": "car",
"scopeId": "car_xyz789",
"seasonId": "sea_summer",
"tierId": "tier_3_6",
"priceGroupId": "pg_default",
"pricePerDay": 42.50
}
]
}'{ "data": { "count": 1 } }Set "pricePerDay": null on the same combination to remove that price. If any referenced season, tier, price group, car or category does not exist, the whole batch is rejected with 400.
Reorder addons
Send the IDs in the order you want them shown; the first gets position 0.
curl -X PUT https://your-slug.crbeeapp.com/api/v1/manage/sort-order \
-H "Authorization: Bearer crb_live_..." \
-H "Content-Type: application/json" \
-d '{
"resource": "addons",
"orderedIds": ["addon_gps", "addon_childseat", "addon_extradriver"]
}'{ "data": { "count": 3 } }resource accepts addons and locations. Everything else is ordered by its own sortOrder field, which you set on the record itself.
Full reference
Request and response schemas for every endpoint are in the API Reference and the interactive API Explorer, under the Management tag.