Calira (formerly Clustermarket) API (0.1.7)

Important Concepts

Account

An account in Calira (formerly Clustermarket) represents an organisation, department, or lab. We have a hierarchical structure following these rules:

  • An organisation can have many departments and many labs.
  • A department can only have labs.
  • A lab can exist by itself, without a department or organisation. We refer to these as independent labs.
graph TD
    org[Organisation]
    org-->lab0[Lab]
    dep1[Department]
    dep2[Department]
    org-->dep1
    dep1-->lab1[Lab]
    dep1-->lab2[Lab]
    org-->dep2
    dep2-->lab3[Lab]
    il[Independent Lab]

Pagination

All endpoints in the Calira (formerly Clustermarket) API support pagination to efficiently handle large datasets. The API uses a custom pagination system with header-based metadata.

Default Behavior

  • A maximum of 100 records are returned per request if no pagination parameters are specified
  • Page 1 is returned by default

Pagination Parameters

  • page: The page number to retrieve (1-based indexing, default: 1)
  • per_page: Number of records per page (1-100, default: 100, maximum: 100)

Pagination Headers

The API provides pagination metadata in response headers:

  • X-Total-Records: Total number of records available
  • X-Current-Page: Current page number
  • X-Per-Page: Number of records per page

Pagination Usage Examples

Basic Pagination

# Get first page (default behavior)
GET /equipment?account=123
# Headers: X-Total-Records: 250, X-Current-Page: 1, X-Per-Page: 100

# Get first page with 50 records
GET /equipment?account=123&per_page=50
# Headers: X-Total-Records: 250, X-Current-Page: 1, X-Per-Page: 50

# Get second page with 50 records
GET /equipment?account=123&per_page=50&page=2
# Headers: X-Total-Records: 250, X-Current-Page: 2, X-Per-Page: 50

# Get third page with 25 records
GET /equipment?account=123&per_page=25&page=3
# Headers: X-Total-Records: 250, X-Current-Page: 3, X-Per-Page: 25

Retrieving All Records

# Example: Get all equipment by iterating through pages
# Page 1: GET /equipment?account=123&per_page=100&page=1
# Page 2: GET /equipment?account=123&per_page=100&page=2
# Page 3: GET /equipment?account=123&per_page=100&page=3
# Continue until X-Current-Page * X-Per-Page >= X-Total-Records

Performance Considerations

  • Default behavior: When no pagination parameters are provided, the API returns page 1 with up to 100 records
  • Large datasets: For datasets with more than 100 records, you must use pagination parameters to retrieve additional pages
  • Recommended approach: Use reasonable page sizes (25-100 records) for optimal performance
  • For large datasets: Implement proper pagination logic in your application to retrieve all records
  • Rate limiting: Be mindful of API rate limits when making multiple paginated requests

Pagination Response Format

  • JSON Response: Simple array of records (no pagination metadata in JSON)
  • Headers: Pagination metadata is provided in response headers
  • Ordering: Records are ordered by creation date (most recent first)
  • Authorization: Pagination respects authorization policies

Write API errors

Complete error reference for all write endpoints. Each endpoint section below also repeats its relevant errors.

Shared error formats

OAuth / authorisation — { "error": "<code>", "error_description": "<message>" }

HTTPerrorWhen
401unauthorisedMissing, invalid, or expired Bearer token
403unapproved_applicationOAuth application not approved by Calira
403resource_authorisation_failureMissing OAuth scope, lab not authorised for the application, or user lacks permission
404resource_not_foundUnknown API path, or record not found where no endpoint-specific handler exists (e.g. unknown booking ID)
500internal_server_errorUnexpected server error — retry with exponential backoff
429Write endpoint rate limit exceededHTML error page (see Rate limiting below)

Rate limiting (write endpoints)

All write endpoints are throttled per client IP address:

EndpointMethodDefault limit
POST /bookingsCreate booking30 requests / minute
PATCH /bookings/{id}Update booking30 requests / minute
POST /bookings/{id}/invitationRespond to invitation30 requests / minute
POST /bookings/{id}/manageApprove, decline, or cancel a booking30 requests / minute
POST /bookings/searchSearch bookings30 requests / minute
POST /booking/notes/{id}Add a booking note30 requests / minute
PATCH /booking/notes/{id}Update a booking note30 requests / minute
POST /uploadsRegister direct upload30 requests / minute
POST /equipmentCreate equipment30 requests / minute
PATCH /equipment/{id}Update equipment30 requests / minute
POST /equipment_training/{user_id}Add equipment training30 requests / minute
DELETE /equipment_training/{user_id}Remove equipment training30 requests / minute

Limits are enforced independently per endpoint path (each row above has its own 30/minute bucket per IP). Exceeding a limit returns HTTP 429 Too Many Requests with an HTML error page. Retry with exponential backoff.

Equipment resource not found — { "errors": ["<code>"], "error_messages": "<message>" }

HTTPerrorsEndpoint
404account_not_foundPOST /equipment — account_id missing or does not exist
404equipment_not_foundPATCH /equipment/{id} — equipment ID in URL does not exist
404not_foundGET /equipment/contact_people — account_id omitted, or account/equipment not found

Validation — { "success": false, "message": "...", "errors": [{ "attribute": "...", "message": "..." }], "error_messages": ["..."] } on 422

Booking helper endpoints — { "errors": ["<code>"], "error_messages": ["<message>"] }

Used by GET /equipment_available_slots/{equipment_id}, GET /equipment/{id}/booking_add_ons, GET /equipment/{id}/users, GET /users/{id}, and POST /bookings/search. errors holds a stable machine-readable code; error_messages holds the matching human-readable explanation. Each endpoint section lists its codes.

Manage booking — { "error": "<code>", "error_description": "<message>" }, used by POST /bookings/{id}/manage.

Booking notes — { "success": null | false, "message": "...", "booking_id": null, "booking_note": null, "errors": [...], "error_messages": [...] }, used by /booking/notes/{id}.

POST /bookings/{id}/invitation

HTTPConditionResponse body
401Missing or invalid access token{ "error": "unauthorised", ... }
403Missing write_bookings OAuth scope{ "error": "resource_authorisation_failure", ... }
403OAuth application not approved{ "error": "unapproved_application", ... }
403Application not authorised for the booking's lab{ "error": "resource_authorisation_failure", ... }
403Token user is not the invited user{ "error": "resource_authorisation_failure", ... }
403Token user has no invitation for this booking ID{ "error": "resource_authorisation_failure", ... }
403Accepting when invitee already has an overlapping booking on the same equipment (request_scope: current){ "error": "resource_authorisation_failure", ... }
403Accepting an invitation that is already accepted (reject is still allowed on accepted invitations){ "error": "resource_authorisation_failure", ... }
404Booking ID does not exist{ "error": "resource_not_found", ... }
422status omitted, null, or not accept/reject{ "error": "invalid_invitation_status", "error_description": "The status parameter must be either 'accept' or 'reject'." }
422request_scope not current, subsequent, or all{ "errors": [{ "attribute": "base", "message": "unknown request_scope: ..." }] }
200Bulk accept (subsequent/all) blocked by scheduling conflicts and accept_available: false{ "errors": [{ "attribute": "base", "message": "Cannot complete action: the invitee already has overlapping bookings..." }], "conflicting_invitations": [...], "processed_invitations": [] }
429More than 30 requests per minute per IPHTML error page
500Unexpected server error{ "error": "internal_server_error", ... }

POST /uploads

Does not require lab authorisation — only a valid write_equipment or write_bookings token.

HTTPConditionResponse body
401Missing or invalid access token{ "error": "unauthorised", ... }
403Token has neither write_equipment nor write_bookings{ "error": "resource_authorisation_failure", ... }
403OAuth application not approved{ "error": "unapproved_application", ... }
422See field table below{ "success": false, "message": "The upload could not be registered...", "errors": [...] }
429More than 30 requests per minute per IPHTML error page
500Unexpected server error{ "error": "internal_server_error", ... }
attributeWhen
filenameMissing or blank
content_typeMissing or blank
content_typeNot a supported image type when purpose is photo (image/png, image/jpeg, image/jpg, image/svg+xml)
content_typeNot a supported document type when purpose is document
content_typeNot a supported booking note file type when purpose is booking_note
byte_sizeMissing, zero, or not a positive integer
byte_sizeExceeds 10 MB when purpose is photo
byte_sizeExceeds 25 MB when purpose is document
byte_sizeExceeds 20 MB when purpose is booking_note
checksumMissing or blank (must be base64-encoded MD5)
purposeNot photo, document, or booking_note

GET /equipment/contact_people

HTTPConditionResponse body
401Missing or invalid access token{ "error": "unauthorised", ... }
403Missing write_equipment OAuth scope{ "error": "resource_authorisation_failure", ... }
403OAuth application not approved{ "error": "unapproved_application", ... }
403Application not authorised for the lab (account_id){ "error": "resource_authorisation_failure", ... }
403User cannot create equipment in the lab (no equipment_id; e.g. guest role){ "error": "resource_authorisation_failure", ... }
403User cannot update the equipment (with equipment_id){ "error": "resource_authorisation_failure", ... }
404account_id query parameter omitted{ "errors": ["not_found"], "error_messages": "No lab, account, or equipment was found..." }
404account_id or equipment_id does not exist{ "errors": ["not_found"], "error_messages": "No lab, account, or equipment was found..." }
500Unexpected server error{ "error": "internal_server_error", ... }

POST /equipment and PATCH /equipment/{id}

HTTP-level errors

HTTPConditionEndpointResponse body
401Missing or invalid access tokenBoth{ "error": "unauthorised", ... }
403Missing write_equipment OAuth scopeBoth{ "error": "resource_authorisation_failure", ... }
403OAuth application not approvedBoth{ "error": "unapproved_application", ... }
403Application not authorised for the labBoth{ "error": "resource_authorisation_failure", ... }
403User cannot create equipment in the labCreate{ "error": "resource_authorisation_failure", ... }
403User cannot update the equipmentUpdate{ "error": "resource_authorisation_failure", ... }
404account_id missing or does not existCreate{ "errors": ["account_not_found"], ... }
404Equipment ID in URL does not existUpdate{ "errors": ["equipment_not_found"], ... }
422See field tables belowBoth{ "success": false, "message": "Equipment could not be created/updated...", "errors": [...] }
429More than 30 requests per minute per IPBothHTML error page
500Unexpected server errorBoth{ "error": "internal_server_error", ... }
attributeWhen
account_idRequired on create but missing
nameRequired on create but missing, or empty string
categoryRequired on create but missing, or empty string
baseUpdate request body is empty ({})
availability_statusNot Always Available or Unavailable
pricing.currencyNot a supported currency code
pricing.charging_typeNot perHour or perDay
pricing.price_detailsWrong type (must be object with internal)
pricing.*Unsupported nested field (e.g. unknown property under pricing)
booking_rules.min_booking_time.unitNot perMinute, perHour, or perDay
booking_rules.max_booking_time.unitNot perMinute, perHour, or perDay
booking_rules.time_step.unitNot perMinute, perHour, or perDay
booking_rules.start_step.start_stepNot quarter, halfHour, fullHour, fullDay, or custom
booking_rules.advance_booking_must.unitNot hours, days, or weeks
booking_rules.advance_booking_can.unitNot hours, days, or weeks
photosWrong type on create (must be array of signed_id strings)
photos.actionNot extend, replace, destroy, or remove (update only)
photos.signed_idsRequired but missing or empty for extend/replace/remove (update)
documentsSame rules as photos
documents.actionSame rules as photos.action
documents.signed_idsSame rules as photos.signed_ids
Any fieldWrong JSON type (e.g. string where object expected)
<section>.<field>Unsupported property not in the API schema

422 attachment errors (create and update)

attributeWhen
photosremove action used on create (not supported)
documentsremove action used on create (not supported)
photosUnsupported action value (not extend, replace, destroy, or remove)
documentsUnsupported action value
photos.signed_idsRequired for extend/replace/remove but missing or empty
documents.signed_idsRequired for extend/replace/remove but missing or empty
photos.signed_idssigned_id references an attachment not on this equipment (remove on update)
documents.signed_idssigned_id references an attachment not on this equipment
photos.signed_idsUnknown or expired signed_id
documents.signed_idsUnknown or expired signed_id
basesigned_id registered by a different user
basesigned_id registered by a different OAuth application
basesigned_id registered with wrong purpose (photo vs document)
baseFile bytes not uploaded to direct_upload.url (step B incomplete)
basesigned_id unknown or expired — register a new upload via POST /uploads

422 model / business-rule errors (create and update)

attributeWhen
nameRequired but blank
categoryRequired but blank, or not a valid category
subcategoryRequired for the selected category but missing
subcategorySet without category, or invalid for the selected category
manufacturerRequired but blank, or longer than 200 characters
model_numberRequired but blank, or longer than 200 characters
availability_statusInvalid value
contact_access_role_idsID is not an admin or instructor for the lab — use GET /equipment/contact_people
group_idsContains invalid group IDs for this lab
group_idsUsers and equipment already assigned together in another group
charging_typeUnsupported charging type
currencyUnsupported currency
purchase_priceNot between 0 and 99,999,999.99
internal_idLonger than 100 characters
roomLonger than 255 characters
serial_numberLonger than 255 characters
min_booking_timeDuration is zero
min_booking_timeDuration exceeds maximum booking time
max_booking_timeDuration is zero
max_booking_timeDuration exceeds 90 days
max_booking_timeInvalid configuration
time_stepDuration is zero
time_stepDuration exceeds maximum booking time
start_stepInvalid custom start step
photosFile exceeds 10 MB or is not an image
documentsFile exceeds 25 MB or is unsupported type
other_attributesInvalid add-ons in pricing.custom_addons
childrencategory is Parent equipment and the equipment has no children. Message: "Parent equipment is required to have at least one child."
childrenchildren sent when category is not Parent equipment. Message: "can only be added when category is Parent equipment"
childrenThe same child id appears more than once in one update. Message: "The list of child equipment must be unique and cannot contain duplicates." Nothing is updated.
children.N.inherits_parent_maintenanceThe two inherit flags would differ. Message: "must match inherits_parent_properties — maintenance is included in Inherit properties from parent"
description, lab_rules, serial_number, availability_status, internal_id, contact_access_role_ids, photos, documentsPATCH of the child itself while inherits_parent_properties is true. Attribute is the field that was sent. Message: "cannot be updated while inherits_parent_properties is true — set inherits_parent_properties to false to change this field". name can still be updated. The same fields inside the parent's children array are accepted and the child keeps the parent value.
maintenance_contract, maintenance_contract_idsPATCH of the child itself while inherits_parent_maintenance is true. Message: "cannot be updated while inherits_parent_maintenance is true — set inherits_parent_maintenance to false to change maintenance"
basePricing enabled but pricing.price_details.internal missing
basepricing.price_details.internal is not a valid number
baseInvalid advance pricing configuration (overlapping time slots, etc.)

POST /equipment_training/{user_id} and DELETE /equipment_training/{user_id}

A missing or invalid token, a missing write_equipment scope, or an unapproved application uses the OAuth error body { "error": "<code>", "error_description": "<message>" }.

Training failures use { "success": false, "message": "...", "user_id": null, "trained_equipment": null, "errors": [{ "attribute": "...", "code": "...", "message": "...", "equipment_ids": [1001] }], "error_messages": ["..."] }. Nothing is written when the request fails. equipment_ids is omitted when the failure is not about particular equipment. A body that cannot be read (trained_equipment missing or empty, or an unsupported field) is 422 and those errors entries have no code.

HTTPerrors[].codeattributeWhen
403training_feature_disabledtrained_equipmentA lab that owns equipment in the request does not have training enabled. equipment_ids lists that equipment.
403role_not_permittedbaseThe caller is not an admin or an instructor. equipment_ids is omitted.
403account_not_admintrained_equipmentThe caller is not an admin of a lab that owns the equipment, and is not an instructor there either.
403equipment_not_authorisedtrained_equipmentThe caller is an instructor for the lab but is not assigned to the equipment.
403equipment_not_accessibletrained_equipmentThe OAuth application is not authorised for the equipment's lab.
404user_not_founduser_idNo user exists with the path user_id. equipment_ids is omitted.
404equipment_not_foundtrained_equipmentAn equipment_id does not exist. equipment_ids lists the missing IDs.
422user_not_lab_memberuser_idThe user is not a member of a lab that owns the equipment.
422record_invalidtrained_equipmentThe training row could not be saved. message is that record's validation error.

POST /bookings and PATCH /bookings/{id}

HTTP-level errors

HTTPConditionEndpointResponse body
401Missing or invalid access tokenBoth{ "error": "unauthorised", ... }
403Missing write_bookings OAuth scopeBoth{ "error": "resource_authorisation_failure", ... }
403OAuth application not approvedBoth{ "error": "unapproved_application", ... }
403Application not authorised for the booking's labBoth{ "error": "resource_authorisation_failure", ... }
403User cannot create bookings on the equipmentCreate{ "error": "resource_authorisation_failure", ... }
403User cannot update the bookingUpdate{ "error": "resource_authorisation_failure", ... }
403Business rules prevent create/update (overlapping bookings, usage limits, advance notice, etc.)Both{ "success": null, "message": "Forbidden — one or more application business rules...", "booking": null, "errors": ["..."], "error_messages": ["..."] }
404Booking ID does not exist or is not accessibleUpdate{ "success": null, "message": "No booking exists with that ID...", "booking": null, "errors": ["..."], "error_messages": ["..."] }
422See field tables belowBoth{ "success": false, "message": "The booking could not be created/updated...", "booking": null, "errors": [...] }
429More than 30 requests per minute per IPBothHTML error page
500Unexpected server errorBoth{ "error": "internal_server_error", ... }
attributeWhen
equipment_idRequired but missing
start_timeRequired but missing or blank
end_timeRequired but missing or blank
booking_typeNot use or maintenance
maintenance_providerRequired when booking_type is maintenance but missing
maintenance_typeRequired when booking_type is maintenance but missing
maintenance_providerSent on a use booking (not allowed)
maintenance_typeSent on a use booking (not allowed)
equipment_idEquipment does not exist
account_idAccount does not exist
equipment_idEquipment is parent equipment (book a child item instead)
Any fieldWrong JSON type
<field>Unsupported property not in the API schema

422 schema errors (update)

attributeWhen
baseEmpty request body ({}) — at least one field required
start_timeBlank or wrong type
end_timeBlank or wrong type
maintenance_providerSent on a use booking (not allowed)
maintenance_typeSent on a use booking (not allowed)
maintenance_providerNot internal or external (maintenance bookings only)
maintenance_typeNot a supported maintenance type (maintenance bookings only)
equipment_idNot updatable via this endpoint
account_idNot updatable via this endpoint
booking_typeNot updatable via this endpoint
Any other fieldUnsupported property not in the API schema

403 business-rule errors (create and update)

Returned when schema validation passes but equipment booking rules reject the request. The errors and error_messages arrays contain human-readable strings (not attribute objects). Common causes include:

  • Equipment already booked during the requested time
  • Booking would exceed personal or group usage limits
  • Booking violates minimum/maximum duration or advance-notice rules on the equipment
  • Booking falls outside permitted business hours or usage schedule
  • User lacks permission to book the equipment at the requested time

422 time errors (create and update)

attributemessageWhen
start_time / end_timemust be an ISO 8601 date-time string with a timezone offset or Z (e.g. 2024-01-15T10:00:00.000Z or 2024-01-15T10:00:00+01:00)Not an ISO 8601 date-time with Z or an offset
start_time / end_timemust not include seconds or milliseconds — use a value such as 2024-01-15T10:00:00.000ZSeconds or milliseconds are not zero
start_time / end_timemust use 15-minute intervals — only :00, :15, :30, and :45 minutes are supportedMinutes, in the lab's time zone, are not 00, 15, 30, or 45. end_time may also be 23:59 local time.

Projects, participants, recurrence, add-ons, and booking on behalf of (create and update)

These failures use the booking write body (success, message, booking: null, errors, error_messages). errors and error_messages both contain the message below.

HTTPFieldMessage (start)When
403booking_on_behalf_ofThe user associated with your token is not an admin or instructor...Caller is not an admin or instructor for the equipment
404booking_on_behalf_ofBooking on behalf of user not found or user inactive...User does not exist, is inactive, or has no access to the equipment
403projectsYou are attempting to set a project for a booking in a lab where projects are not enabled...The lab does not support projects
404projectsProject not found...project_id does not exist
403projectsForbidden - The project you provided is a user project not a lab project...Project is a personal user project
403projectsForbidden - The project you provided is not valid for the booking owner...Project belongs to another lab, or the booking owner is not on the project and neither the caller nor the owner manages the lab
404projectsOne or more of the project funding codes you provided could not be found...funding_code_id is not a funding code of that project
403projectsForbidden - The project funding code percentages ... must add up to 0 or 100...Sum of every funding_code_percentage is not 0 or 100
422projects.<n>.project_idis listed more than once — include each project only once in the projects arraySame project listed twice
403invited_usersMaintenance bookings do not currently support booking participants...Participants sent on a maintenance booking
403invited_usersThe lab setting allowing group bookings is not enabled...Lab setting Multiple users per booking is off
403invited_usersThe user group setting allowing group bookings is not enabled...Caller's access group does not allow group bookings
403invited_usersYour subscription plan does not support multiple guest bookings.Lab subscription does not include group bookings
403invited_usersYou do not have permission to invite users.Caller has the guest role in the lab
403invited_usersParticipants cannot be added to a booking that has already ended...Update of a booking whose end time has passed
403invited_usersOne or more of the users passed into the invited_users parameter could not be found or is not a member of the lab...Unknown user, or user not in the equipment's lab
403invited_usersA user without access to book the equipment has been passed into the invited_users parameter...Participant cannot book the equipment
422recurrenceYou have passed an unsupported value to the recurrence_action property...recurrence_action not skip_conflict, overlap_existing, or decline_existing
403recurrenceOnly admins and instructors can create overlapping bookings...overlap_existing or decline_existing sent by a user who is not an admin or instructor for the equipment
422recurrenceYou have passed an unsupported value to recurrence_type property...recurrence_type not daily, weekly, monthly_relative, monthly_absolute, or yearly
422recurrenceYou have passed an unsupported value to recurrence_interval property...recurrence_interval is not a positive integer
422recurrenceYou have passed an unsupported value to recurrence_end property...recurrence_end is not an ISO 8601 date or date-time
422recurrenceThe value of recurrence_end must be after the start_time valuerecurrence_end is not after start_time
422recurrenceYou have passed an unsupported value to recurrence_days property...recurrence_days empty or contains a value that is not a lowercase English weekday
422recurrenceYou have passed values to recurrence_days when the recurrence type is not weekly...recurrence_days sent with a type other than weekly
422recurrenceYou have passed an unsupported value to recurrence_date property...recurrence_date not an integer from 1 to 31
422recurrenceThe value of recurrence_date must match the day of the month of start_time...monthly_absolute with a recurrence_date that differs from the local day of start_time
422recurrencerecurrence_date is only used for monthly_absolute bookings...recurrence_date sent with monthly_relative
422recurrenceYou have passed values to recurrence_date when the recurrence type is not monthly_absolute...recurrence_date sent with daily, weekly, or yearly
422recurrenceRepeating on the last weekday of the month is not supported...monthly_relative with a start_time in the fifth week of the month
403add_onsMaintenance bookings do not currently support equipment add-ons...Add-ons sent on a maintenance booking
422add_onsYou failed to provide a value for <name> this is a mandatory parameter...A mandatory add-on is missing (<name> is the add-on), equipment_addon is blank, or quantity is missing for a user_specified add-on
404add_onsThe add-on name you provided could not be found...equipment_addon is not an add-on the caller can use on this equipment
422add_onsThe add-on quantity you provided is less than 0 or greater than 999999999...quantity out of range
422add_ons.<n>.equipment_addonis listed more than once — include each add-on only once in the add_ons arraySame add-on listed twice

POST /bookings/{id}/manage

HTTPerrorWhen
401unauthorisedMissing or invalid access token
403resource_authorisation_failureToken does not have write_bookings, or the caller's role cannot make this change (for example a researcher approving a booking)
403account_not_authorisedOAuth application or token user is not authorised for the booking's lab
403cancel_not_ownerstatus: cancelled on a booking the caller neither owns nor participates in
404resource_not_foundBooking ID does not exist
422unsupported_propertyBody contains a property other than status and recurrence
422unsupported_statusstatus missing or not booked, declined, or cancelled
422unsupported_recurrencerecurrence not current_booking, subsequent_booking, or all_bookings
422unsupported_status_changeChange not allowed from the booking's current status (see the endpoint for allowed changes)
422unprocessable_entityStatus change failed a booking rule; error_description explains why

/booking/notes/{id}

HTTPerrorsWhen
403insufficient_scopeMissing read_bookings (GET) or write_bookings (POST, PATCH). This body has only errors and error_messages.
403account_not_authorisedOAuth application or token user is not authorised for the booking's lab
403not_owner_or_participantGET by a user who is not the booking owner, a participant, or an admin or instructor for the equipment
403not_ownerPOST or PATCH by a user who is not the booking owner or an admin or instructor for the equipment
403note_by_another_userPATCH by the booking owner on a note written by someone else
404booking_not_foundBooking ID does not exist (GET, POST)
404note_not_foundNote ID does not exist (PATCH)
422field errorsSee the endpoint for booking_note.note_text and booking_note.note_file_signed_id errors

Booking Write API

The following booking write endpoints are available:

  • POST /bookings — create a booking
  • PATCH /bookings/{id} — update a booking
Servers
Production
https://api.clustermarket.com/v1
Staging
https://api.clustermarket.dev/v1