Calira (formerly Clustermarket) API (0.1.6)

Download OpenAPI specification:

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

Errors (Write API)

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

Shared error formats

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

HTTP error When
401 unauthorised Missing, invalid, or expired Bearer token
403 unapproved_application OAuth application not approved by Calira
403 resource_authorisation_failure Missing OAuth scope, lab not authorised for the application, or user lacks permission
404 resource_not_found Unknown API path, or record not found where no endpoint-specific handler exists (e.g. unknown booking ID)
500 internal_server_error Unexpected server error — retry with exponential backoff

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

HTTP errors Endpoint
404 account_not_found POST /equipmentaccount_id missing or does not exist
404 equipment_not_found PATCH /equipment/{id} — equipment ID in URL does not exist
404 not_found GET /equipment/contact_peopleaccount_id omitted, or account/equipment not found

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

POST /bookings/{id}/invitation

HTTP Condition Response body
401 Missing or invalid access token { "error": "unauthorised", ... }
403 Missing write_bookings OAuth scope { "error": "resource_authorisation_failure", ... }
403 OAuth application not approved { "error": "unapproved_application", ... }
403 Application not authorised for the booking's lab { "error": "resource_authorisation_failure", ... }
403 Token user is not the invited user { "error": "resource_authorisation_failure", ... }
403 Token user has no invitation for this booking ID { "error": "resource_authorisation_failure", ... }
403 Accepting when invitee already has an overlapping booking on the same equipment (request_scope: current) { "error": "resource_authorisation_failure", ... }
403 Accepting an invitation that is already accepted (reject is still allowed on accepted invitations) { "error": "resource_authorisation_failure", ... }
404 Booking ID does not exist { "error": "resource_not_found", ... }
422 status omitted, null, or not accept/reject { "error": "invalid_invitation_status", "error_description": "The status parameter must be either 'accept' or 'reject'." }
422 request_scope not current, subsequent, or all { "errors": [{ "attribute": "base", "message": "unknown request_scope: ..." }] }
200 Bulk 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": [] }
429 More than 30 requests per minute per IP HTML error page
500 Unexpected server error { "error": "internal_server_error", ... }

POST /uploads

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

HTTP Condition Response body
401 Missing or invalid access token { "error": "unauthorised", ... }
403 Missing write_equipment OAuth scope { "error": "resource_authorisation_failure", ... }
403 OAuth application not approved { "error": "unapproved_application", ... }
422 See field table below { "success": false, "message": "The upload could not be registered...", "errors": [...] }
500 Unexpected server error { "error": "internal_server_error", ... }

422 field errors (POST /uploads)

attribute When
filename Missing or blank
content_type Missing or blank
content_type Not a supported image type when purpose is photo (image/png, image/jpeg, image/jpg, image/svg+xml)
content_type Not a supported document type when purpose is document
byte_size Missing, zero, or not a positive integer
byte_size Exceeds 10 MB when purpose is photo
byte_size Exceeds 25 MB when purpose is document
checksum Missing or blank (must be base64-encoded MD5)
purpose Not photo or document

GET /equipment/contact_people

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

POST /equipment and PATCH /equipment/{id}

HTTP-level errors

HTTP Condition Endpoint Response body
401 Missing or invalid access token Both { "error": "unauthorised", ... }
403 Missing write_equipment OAuth scope Both { "error": "resource_authorisation_failure", ... }
403 OAuth application not approved Both { "error": "unapproved_application", ... }
403 Application not authorised for the lab Both { "error": "resource_authorisation_failure", ... }
403 User cannot create equipment in the lab Create { "error": "resource_authorisation_failure", ... }
403 User cannot update the equipment Update { "error": "resource_authorisation_failure", ... }
404 account_id missing or does not exist Create { "errors": ["account_not_found"], ... }
404 Equipment ID in URL does not exist Update { "errors": ["equipment_not_found"], ... }
422 See field tables below Both { "success": false, "message": "Equipment could not be created/updated...", "errors": [...] }
500 Unexpected server error Both { "error": "internal_server_error", ... }

422 schema errors (create and update)

attribute When
account_id Required on create but missing
name Required on create but missing, or empty string
category Required on create but missing, or empty string
base Update request body is empty ({})
availability_status Not Always Available or Unavailable
pricing.currency Not a supported currency code
pricing.charging_type Not perHour or perDay
pricing.price_details Wrong type (must be object with internal)
pricing.* Unsupported nested field (e.g. unknown property under pricing)
booking_rules.min_booking_time.unit Not perMinute, perHour, or perDay
booking_rules.max_booking_time.unit Not perMinute, perHour, or perDay
booking_rules.time_step.unit Not perMinute, perHour, or perDay
booking_rules.start_step.start_step Not quarter, halfHour, fullHour, fullDay, or custom
booking_rules.advance_booking_must.unit Not hours, days, or weeks
booking_rules.advance_booking_can.unit Not hours, days, or weeks
photos Wrong type on create (must be array of signed_id strings)
photos.action Not extend, replace, destroy, or remove (update only)
photos.signed_ids Required but missing or empty for extend/replace/remove (update)
documents Same rules as photos
documents.action Same rules as photos.action
documents.signed_ids Same rules as photos.signed_ids
Any field Wrong JSON type (e.g. string where object expected)
<section>.<field> Unsupported property not in the API schema

422 attachment errors (create and update)

attribute When
photos remove action used on create (not supported)
documents remove action used on create (not supported)
photos Unsupported action value (not extend, replace, destroy, or remove)
documents Unsupported action value
photos.signed_ids Required for extend/replace/remove but missing or empty
documents.signed_ids Required for extend/replace/remove but missing or empty
photos.signed_ids signed_id references an attachment not on this equipment (remove on update)
documents.signed_ids signed_id references an attachment not on this equipment
photos.signed_ids Unknown or expired signed_id
documents.signed_ids Unknown or expired signed_id
base signed_id registered by a different user
base signed_id registered by a different OAuth application
base signed_id registered with wrong purpose (photo vs document)
base File bytes not uploaded to direct_upload.url (step B incomplete)
base signed_id unknown or expired — register a new upload via POST /uploads

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

attribute When
name Required but blank
category Required but blank, or not a valid category
subcategory Required for the selected category but missing
subcategory Set without category, or invalid for the selected category
manufacturer Required but blank, or longer than 200 characters
model_number Required but blank, or longer than 200 characters
availability_status Invalid value
contact_access_role_ids ID is not an admin or instructor for the lab — use GET /equipment/contact_people
group_ids Contains invalid group IDs for this lab
group_ids Users and equipment already assigned together in another group
charging_type Unsupported charging type
currency Unsupported currency
purchase_price Not between 0 and 99,999,999.99
internal_id Longer than 100 characters
room Longer than 255 characters
serial_number Longer than 255 characters
min_booking_time Duration is zero
min_booking_time Duration exceeds maximum booking time
max_booking_time Duration is zero
max_booking_time Duration exceeds 90 days
max_booking_time Invalid configuration
time_step Duration is zero
time_step Duration exceeds maximum booking time
start_step Invalid custom start step
photos File exceeds 10 MB or is not an image
documents File exceeds 25 MB or is unsupported type
other_attributes Invalid add-ons in pricing.custom_addons
base Pricing enabled but pricing.price_details.internal missing
base pricing.price_details.internal is not a valid number
base Invalid advance pricing configuration (overlapping time slots, etc.)

Write API (Upcoming)

The following write endpoints are upcoming and not yet publicly released. They are documented for early access and testing only:

  • GET /equipment/contact_people — list valid contact access role IDs for equipment create/update
  • POST /uploads — register file uploads (step A); step B uploads bytes to direct_upload.url
  • POST /equipment — create equipment
  • PATCH /equipment/{id} — update equipment
  • POST /bookings/{id}/invitation — respond to booking invitations

These endpoints are not generally available yet and may change without notice — including request/response schemas, validation rules, error formats, and behaviour. Do not rely on them in production until announced as stable. Contact support@calira.co for early access feedback.

accounts

Accounts represent Organisations, Departments or Labs

List Accounts

Lists all accounts accessible through the integration. The application scope must include read_accounts.

Pagination: This endpoint supports pagination with a default limit of 100 records. Use page and per_page parameters to navigate through large datasets efficiently. Pagination metadata is provided in response headers (X-Total-Records, X-Current-Page, X-Per-Page).

Authorizations:
oauth
query Parameters
page
integer >= 1
Default: 1

Page number (1-based indexing, default: 1)

per_page
integer [ 1 .. 100 ]
Default: 100

Number of records per page (1-100, default: 100, max: 100)

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Account Details

Get the full details of a specific account. The application scope must include read_accounts.

Authorizations:
oauth
path Parameters
id
required
integer

Account ID

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "Cambridge Graphene Center",
  • "account_type": "lab",
  • "sector": "academia",
  • "description": "string",
  • "timezone": "Europe/London",
  • "department": {
    },
  • "organisation": {
    },
  • "labs": [
    ],
  • "departments": [
    ]
}

bookings

A booking made on a piece of equipment.

Write endpoints (POST /bookings/{id}/invitation) are upcoming, not yet publicly released, and currently in testing. They may change without notice.

List Bookings

Return lists of bookings accessible to the user, optionally scopable to the providing lab account. The application scope must include read_bookings.

Pagination: This endpoint supports pagination with a default limit of 100 records. Use page and per_page parameters to navigate through large datasets efficiently. Pagination metadata is provided in response headers (X-Total-Records, X-Current-Page, X-Per-Page).

Authorizations:
oauth
query Parameters
provider_account
number

The parent lab account ID.

page
integer >= 1
Default: 1

Page number (1-based indexing, default: 1)

per_page
integer [ 1 .. 100 ]
Default: 100

Number of records per page (1-100, default: 100, max: 100)

Responses

Response samples

Content type
application/json

Example response showing multiple bookings

[
  • {
    },
  • {
    },
  • {
    }
]

Booking Details

Return the details about a particular booking as defined by the database identifier. The application scope must include read_bookings.

Authorizations:
oauth
path Parameters
id
required
integer

Booking ID

Responses

Response samples

Content type
application/json

Example response showing all booking information

{
  • "id": 12345,
  • "cost": "150.00",
  • "currency": "USD",
  • "charging_type": "Per Hour",
  • "start_time": "2024-01-15T09:00:00.000Z",
  • "end_time": "2024-01-15T11:00:00.000Z",
  • "requested_at": "2024-01-10T14:30:00.000Z",
  • "booking_type": "internal",
  • "status": "Confirmed",
  • "duration": 120,
  • "add_ons": "Data analysis service included",
  • "requester_group": {
    },
  • "equipment": {
    },
  • "parent_equipment": {
    },
  • "requester_lab": {
    },
  • "requester_organisation": {
    },
  • "provider_lab": {
    },
  • "provider_organisation": {
    },
  • "creator": {
    },
  • "requester": {
    },
  • "custom_form_responses": [
    ],
  • "last_public_note": {
    },
  • "projects": [
    ]
}

Respond to Booking Invitation

Upcoming / Beta notice

This write endpoint is upcoming and not yet publicly released. It is currently in testing and may not be available on all environments. Request and response shapes, validation rules, error formats, and behaviour may change without notice. Do not use in production until announced as generally available. Contact support for early access.


Accept or reject a booking invitation for the authenticated user.

Overview

When a booking is created for a group, each invited user receives a booking invitation. This endpoint lets the invited user respond on their own behalf. The booking ID in the path (/bookings/{id}/invitation) must be the ID of a booking where the current access-token user has an invitation.

Authorisation

Requirement Details
OAuth scope write_bookings
Application Must be approved and authorised for the lab that owns the booking
Resource owner Must be the invited user — you cannot respond to another user's invitation

A 403 Forbidden response is returned when the scope is missing, the application is not authorised for the lab, the token user is not the invitee, or the invitation cannot be acted on (for example, accepting when the invitee already has an overlapping booking on the same equipment).

Request body

Field Required Description
status Yes accept or reject
reject_reason No Free-text reason stored when rejecting. Ignored for accept.
request_scope No Controls how many occurrences are affected for recurring bookings. Default: current
accept_available No Boolean, default false. Only relevant when accepting with a bulk request_scope

request_scope values (recurring bookings)

  • current (default) — only the invitation tied to this booking ID
  • subsequent — this booking and every later occurrence in the recurrence series where the user has an invitation
  • all — every occurrence in the recurrence series where the user has an invitation

For non-recurring bookings, request_scope has no practical effect beyond current.

Conflict handling (bulk accept)

When accepting with subsequent or all, the API checks whether the invitee already has overlapping confirmed bookings on the same equipment. If conflicts exist:

  • With accept_available: false (default): no invitations are accepted. The response still returns HTTP 200 and includes conflicting_invitations with the affected dates/times, plus an errors array explaining the conflict.
  • With accept_available: true: only non-conflicting invitations are accepted; conflicting ones are listed in conflicting_invitations.

Response

Returns the primary booking_invitation (the one for the booking ID in the path), plus:

  • processed_invitations — all invitations that were successfully accepted or rejected in this request
  • conflicting_invitations — invitations that could not be accepted due to scheduling conflicts (empty when there are no conflicts)

Invitation status values in responses: pending, accepted, rejected.

Errors

See Errors (Write API) for the full catalogue.

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

Side effects

Accepting a confirmed booking may enqueue calendar sync jobs (for example, Outlook) for the invitee. Notifications are sent to relevant parties when an invitation is responded to.

Example workflow

# Accept a single invitation
POST /bookings/12345/invitation
Authorization: Bearer <token>
Content-Type: application/json

{ "status": "accept" }
# Reject with a reason
POST /bookings/12345/invitation

{ "status": "reject", "reject_reason": "Not available that day" }
# Accept all non-conflicting occurrences in a recurring series
POST /bookings/12345/invitation

{ "status": "accept", "request_scope": "all", "accept_available": true }
Authorizations:
oauth
path Parameters
id
required
integer

Booking ID

Request Body schema: application/json
required
status
required
string
Enum: "accept" "reject"

The action to take on the invitation.

  • accept — confirm attendance; may trigger calendar sync and notifications
  • reject — decline the invitation; optionally include reject_reason
reject_reason
string

Optional free-text reason stored when status is reject. Ignored when accepting.

request_scope
string
Default: "current"
Enum: "current" "subsequent" "all"

For recurring bookings only. Controls which invitations in the series are affected.

accept_available
boolean
Default: false

When accepting with request_scope of subsequent or all, controls conflict behaviour. If false (default) and scheduling conflicts exist, no invitations are accepted. If true, non-conflicting invitations are accepted and conflicting ones are returned in conflicting_invitations.

Responses

Request samples

Content type
application/json
Example
{
  • "status": "accept"
}

Response samples

Content type
application/json
Example
{
  • "booking_invitation": {
    },
  • "processed_invitations": [
    ],
  • "conflicting_invitations": [ ]
}

Custom Form Response Details

Returns a submitted custom form response linked to a booking. Use this endpoint to retrieve the user-submitted answers for a booking's custom form. The application scope must include read_bookings.

Example request: GET /custom_form_responses/16

Authorizations:
oauth
path Parameters
id
required
integer

Custom form response ID

Responses

Response samples

Content type
application/json
{
  • "custom_form_response_id": 16,
  • "custom_form_id": 28,
  • "custom_form_version_id": 1,
  • "booking_reference_id": 2045426,
  • "created_by": "Demo Admin",
  • "created_at": "2026-04-08T14:13:27.602Z",
  • "updated_at": "2026-04-08T14:13:28.075Z",
  • "form_response": [
    ]
}

equipment

A piece of equipment (e.g. microscope, spectrometer).

Write endpoints (GET /equipment/contact_people, POST /uploads, POST /equipment, PATCH /equipment/{id}) are upcoming, not yet publicly released, and currently in testing. They may change without notice.

Register Direct Upload

Upcoming / Beta notice

This write endpoint is upcoming and not yet publicly released. It is currently in testing and may not be available on all environments. Request and response shapes, validation rules, error formats, and behaviour may change without notice. Do not use in production until announced as generally available. Contact support for early access.


Registers a file for direct upload before attaching it to equipment via POST /equipment or PATCH /equipment/{id}.

Overview

Equipment photos and documents are not uploaded inline with create/update requests. Instead, use this three-step direct upload flow:

Step Endpoint Action
A POST /uploads Register upload metadata and receive signed_id + direct_upload target
B PUT direct_upload.url Upload the raw file bytes to cloud storage (not the Calira API)
C POST /equipment or PATCH /equipment/{id} Attach the signed_id from step A

The signed_id is scoped to the registering user and OAuth application. It must be used with the same credentials that registered it.

Step A — Register upload (POST /uploads)

Send file metadata (name, type, size, checksum). On success you receive:

{
  "signed_id": "eyJfcmFpbHMiOnsiZGF0YSI6MTE3OSwicHVyIjoiYmxvYl9pZCJ9fQ==--6109b8c4568a1687e0b95fc25955d4c52cae4b4e",
  "filename": "microscope.jpg",
  "content_type": "image/jpeg",
  "byte_size": 1048576,
  "purpose": "photo",
  "direct_upload": {
    "url": "https://storage.example.com/rails/active_storage/disk/...",
    "headers": {
      "Content-Type": "image/jpeg",
      "Content-MD5": "dGVzdCBjaGVja3N1bQ=="
    }
  }
}

Save signed_id for step C. Use direct_upload.url and direct_upload.headers for step B.

Step B — Upload file bytes (PUT direct_upload.url)

This step does not call the Calira API. You upload the file directly to cloud storage using the pre-signed URL returned in step A.

Requirement Details
HTTP method PUT (not POST)
URL direct_upload.url from the step A response
Headers All key/value pairs from direct_upload.headers — include them exactly as returned (typically Content-Type and Content-MD5)
Request body Raw file bytes — not JSON, not multipart/form-data
Body size Must match the byte_size sent in step A

Important:

  • direct_upload.url is short-lived (pre-signed; expires after approximately 5 minutes by default). Complete step B promptly after step A — if the URL expires, register a new upload with POST /uploads.
  • The Content-MD5 header must match the checksum you sent in step A (base64-encoded MD5 of the file).
  • Do not add an Authorization header on this request — authentication is embedded in the pre-signed URL.
  • Step B must succeed before you reference the signed_id in step C. If you skip step B, equipment create/update will fail with an incomplete-upload error.
  • A successful upload typically returns 200 OK or 204 No Content from the storage provider (not from Calira).
# Step B example — upload file bytes to storage
curl -X PUT "https://storage.example.com/rails/active_storage/disk/..." \
  -H "Content-Type: image/jpeg" \
  -H "Content-MD5: dGVzdCBjaGVja3N1bQ==" \
  --data-binary @microscope.jpg
# Alternative: pipe file contents
curl -X PUT "https://storage.example.com/rails/active_storage/disk/..." \
  -H "Content-Type: image/jpeg" \
  -H "Content-MD5: dGVzdCBjaGVja3N1bQ==" \
  --data-binary "@/path/to/microscope.jpg"

Step C — Attach to equipment

Reference the signed_id from step A in photos or documents when creating or updating equipment. See POST /equipment or PATCH /equipment/{id}.

Authorisation

Requirement Details
OAuth scope write_equipment

Request body

Field Required Description
filename Yes Original file name including extension (e.g. microscope.jpg)
content_type Yes MIME type of the file. Must match the purpose restrictions below
byte_size Yes File size in bytes. Must be greater than 0
checksum Yes Base64-encoded MD5 digest of the file bytes
purpose Yes photo or document — determines allowed types and size limits

Purpose restrictions

photo

  • Allowed content types: image/png, image/jpeg, image/jpg, image/svg+xml
  • Maximum size: 10 MB

document

  • Allowed content types: image/jpeg, image/jpg, image/png, application/pdf, application/msword, application/vnd.ms-excel, application/vnd.oasis.opendocument.spreadsheet, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.openxmlformats-officedocument.wordprocessingml.document
  • Maximum size: 25 MB

Response

On success (201 Created), returns the signed_id to reference in equipment requests, plus direct_upload.url and direct_upload.headers for the file upload step.

Errors

See Errors (Write API) for the full catalogue. This endpoint does not require lab authorisation — only a valid write_equipment token.

HTTP Condition Response
401 Missing or invalid access token { "error": "unauthorised", ... }
403 Missing write_equipment scope { "error": "resource_authorisation_failure", ... }
403 OAuth application not approved { "error": "unapproved_application", ... }
422 Invalid upload metadata — see field table below { "success": false, "message": "The upload could not be registered...", "errors": [...] }
500 Unexpected server error { "error": "internal_server_error", ... }

422 field errors

attribute When
filename Missing or blank
content_type Missing, blank, or not allowed for the purpose
byte_size Missing, zero, exceeds 10 MB (photo), or exceeds 25 MB (document)
checksum Missing or blank
purpose Not photo or document

If you reference a signed_id on equipment create/update before uploading file bytes (step B), or after the signed ID expires, validation fails on the equipment request with a base error — register a new upload.

Example workflow (all steps)

# Step A: Register upload
POST /uploads
Authorization: Bearer <token>
Content-Type: application/json

{
  "filename": "microscope.jpg",
  "content_type": "image/jpeg",
  "byte_size": 1048576,
  "checksum": "dGVzdCBjaGVja3N1bQ==",
  "purpose": "photo"
}

# Response includes signed_id and direct_upload — save both for steps B and C
# Step B: Upload file bytes to direct_upload.url (NOT the Calira API)
curl -X PUT "<direct_upload.url from step A>" \
  -H "Content-Type: image/jpeg" \
  -H "Content-MD5: dGVzdCBjaGVja3N1bQ==" \
  --data-binary @microscope.jpg
# Step C: Create equipment with the signed_id from step A
POST /equipment
Authorization: Bearer <token>
Content-Type: application/json

{
  "account_id": 123,
  "name": "API Microscope",
  "category": "Equipment",
  "photos": ["<signed_id from step A>"]
}
Authorizations:
oauth
Request Body schema: application/json
required
filename
required
string non-empty

Original file name including extension.

content_type
required
string non-empty

MIME type of the file. Must match purpose restrictions (see POST /uploads).

byte_size
required
integer >= 1

File size in bytes. Maximum 10 MB for photos, 25 MB for documents.

checksum
required
string non-empty

Base64-encoded MD5 digest of the file bytes.

purpose
required
string
Enum: "photo" "document"

Determines allowed content types and size limits.

Responses

Request samples

Content type
application/json
Example
{
  • "filename": "microscope.jpg",
  • "content_type": "image/jpeg",
  • "byte_size": 1048576,
  • "checksum": "dGVzdCBjaGVja3N1bQ==",
  • "purpose": "photo"
}

Response samples

Content type
application/json
Example
{
  • "signed_id": "eyJfcmFpbHMiOnsiZGF0YSI6MTE3OSwicHVyIjoiYmxvYl9pZCJ9fQ==--6109b8c4568a1687e0b95fc25955d4c52cae4b4e",
  • "filename": "microscope.jpg",
  • "content_type": "image/jpeg",
  • "byte_size": 1048576,
  • "purpose": "photo",
  • "direct_upload": {}
}

List Equipment

Lists all equipment under the specified lab. Requires read_equipment scope.

Pagination: This endpoint supports pagination with a default limit of 100 records. Use page and per_page parameters to navigate through large datasets efficiently. Pagination metadata is provided in response headers (X-Total-Records, X-Current-Page, X-Per-Page).

Authorizations:
oauth
query Parameters
account
number

The target lab account ID

exclude_parents
boolean
Default: false

When true, only child equipment will be returned (no parent equipment)

page
integer >= 1
Default: 1

Page number (1-based indexing, default: 1)

per_page
integer [ 1 .. 100 ]
Default: 100

Number of records per page (1-100, default: 100, max: 100)

Responses

Response samples

Content type
application/json
[
  • {
    },
  • {
    }
]

Create Equipment

Upcoming / Beta notice

This write endpoint is upcoming and not yet publicly released. It is currently in testing and may not be available on all environments. Request and response shapes, validation rules, error formats, and behaviour may change without notice. Do not use in production until announced as generally available. Contact support for early access.


Creates a new piece of equipment in the specified lab account.

Overview

This endpoint creates equipment atomically in a single request. You can supply general fields, pricing, booking rules, maintenance settings, contact people, group access, labels, and file attachments in one payload.

Authorisation

Requirement Details
OAuth scope write_equipment
Application Must be approved and authorised for the target lab (account_id)
User Must have permission to create equipment in that lab (typically admin or instructor)

Required fields

Field Description
account_id ID of the lab account where the equipment will be created
name Display name of the equipment
category One of: Equipment, Parent equipment, Room/Space, Desk/Bench, Other

Depending on the category, a subcategory may also be required (for example, Microscopy & Imaging when category is Equipment).

Request body

The request body schema defines every field with types, allowed values, and nested object structure. Expand the schema in the panel below or see these component schemas:

Schema Contents
EquipmentMutableFields All top-level fields
EquipmentPricingInput pricing object — currency, charging, price details, advance pricing, add-ons
EquipmentBookingRulesInput booking_rules object — min/max duration, time step, start step, advance notice, business hours
EquipmentMaintenanceInput maintenance object — maintenance contracts
EquipmentAttachmentInput photos and documents — signed IDs (create) or action objects (update)

Optional top-level fields (summary)

Field Description
room Physical location or room name
subcategory Subcategory name matching the selected category
manufacturer Manufacturer name
model_number Model or catalogue number
manufacturing_year Year of manufacture (integer or string)
serial_number Serial number
availability_status Always Available or Unavailable (default: Always Available)
description Plain-text description
lab_rules Plain-text lab-specific usage rules
safety_features Plain-text safety information
date_of_purchase Purchase date (ISO 8601 date string)
internal_id Internal inventory identifier
purchase_price Purchase price
contact_access_role_ids Array of access role IDs for equipment contact people. Use GET /equipment/contact_people?account_id={id} to list valid IDs
group_ids Array of group IDs that should have access
equipment_label_ids Array of equipment label IDs
photos Array of signed_id strings from POST /uploads with purpose: photo — see EquipmentAttachmentInput
documents Array of signed_id strings from POST /uploads with purpose: document — see EquipmentAttachmentInput

Nested sections (summary)

See the nested schemas above for full parameter definitions. Brief overview:

pricingEquipmentPricingInput

Enable charging, set currency (GBP, USD, …), charging_type (perHour/perDay), price_details.internal, optional advance_pricing slots, and custom_addons.

booking_rulesEquipmentBookingRulesInput

Enable constraints, set min_booking_time / max_booking_time ({ unit, duration }), time_step, start_step, advance_booking_must / advance_booking_can, and optional business_hours.

maintenanceEquipmentMaintenanceInput

Set maintenance_contract and maintenance_contract_ids.

File attachments

Photos and documents use the three-step direct upload flow:

Step Action
A POST /uploads — register metadata, receive signed_id and direct_upload
B PUT direct_upload.url — upload raw file bytes to storage (see POST /uploads for full step B documentation)
C Include signed_id in photos or documents on this request

On create, photos and documents must be arrays of signed IDs (not action objects). Step B must complete before step C.

Response

Returns 201 Created with { success: true, equipment: { ... } } containing the full equipment configuration including pricing, booking_rules, and maintenance sections.

Validation errors

Returns 422 Unprocessable Entity with field-level errors when validation fails. No equipment is created on validation failure.

See Errors (Write API) for the complete field-level catalogue.

HTTP Condition Response
401 Missing or invalid access token { "error": "unauthorised", ... }
403 Missing write_equipment scope { "error": "resource_authorisation_failure", ... }
403 OAuth application not approved { "error": "unapproved_application", ... }
403 Application not authorised for the lab { "error": "resource_authorisation_failure", ... }
403 User cannot create equipment in the lab { "error": "resource_authorisation_failure", ... }
404 account_id missing or does not exist { "errors": ["account_not_found"], ... }
422 Schema, attachment, or business-rule validation failed { "success": false, "message": "Equipment could not be created...", "errors": [...] }
500 Unexpected server error { "error": "internal_server_error", ... }

Common 422 causes: missing account_id/name/category; invalid subcategory, availability_status, or contact_access_role_ids; unsupported pricing/booking_rules values; invalid or incomplete photos/documents signed_id references (see upload flow).

Authorizations:
oauth
Request Body schema: application/json
required
account_id
required
integer

Lab account ID where the equipment belongs. Required on create. Cannot be changed on update.

name
required
string non-empty

Display name of the equipment. Required on create.

room
string

Physical location or room name (max 255 characters).

category
required
string non-empty
Enum: "Equipment" "Parent equipment" "Room/Space" "Desk/Bench" "Other"

Equipment category. Required on create.

subcategory
string

Subcategory name matching the selected category. Required when the category has subcategories (e.g. Microscopy & Imaging for Equipment).

manufacturer
string

Manufacturer name. Required by business rules for Equipment, Other, and Parent equipment categories (max 200 characters).

model_number
string

Model or catalogue number. Required by business rules for Equipment, Other, and Parent equipment categories (max 200 characters).

Equipment Numeric Value (number) or Equipment Numeric Value (string) (Equipment Numeric Value)

Numeric value accepted as a JSON number or decimal string (e.g. 25 or "25.50").

serial_number
string

Equipment serial number (max 255 characters).

availability_status
string
Default: "Always Available"
Enum: "Always Available" "Unavailable"

Whether the equipment can be booked.

description
string

Plain-text description. Rich-text editor formats (HTML or Quill JSON) are not accepted — send plain text only.

lab_rules
string

Plain-text lab-specific usage rules shown to bookers. Send plain text only.

safety_features
string

Plain-text safety information shown to bookers. Send plain text only.

date_of_purchase
string

Purchase date as an ISO 8601 date string (e.g. 2024-01-15).

internal_id
string

Internal inventory identifier (max 100 characters; unique per lab).

Equipment Numeric Value (number) or Equipment Numeric Value (string) (Equipment Numeric Value)

Numeric value accepted as a JSON number or decimal string (e.g. 25 or "25.50").

contact_access_role_ids
Array of integers

Access role IDs for equipment contact people. Use GET /equipment/contact_people?account_id={id} to list valid IDs.

group_ids
Array of integers

IDs of user groups that should have access to book this equipment.

equipment_label_ids
Array of integers

IDs of equipment labels to apply.

maintenance_contract_ids
Array of integers

IDs of maintenance contracts. May also be set inside maintenance.maintenance_contract_ids.

Array of Equipment Attachment Input (strings) or Equipment Attachment Input (object) (Equipment Attachment Input)

On create (POST /equipment): pass an array of signed_id strings from POST /uploads (with matching purpose). Example:

"photos": ["eyJfcmFpbHMiOnsiZGF0YSI6MTE3OSwicHVyIjoiYmxvYl9pZCJ9fQ==--abc123"]

On update (PATCH /equipment/{id}): pass an action object. Example:

"photos": { "action": "replace", "signed_ids": ["eyJfcmFpbHMiOnsiZGF0YSI6MTE3OSwicHVyIjoiYmxvYl9pZCJ9fQ==--abc123"] }

File bytes must be uploaded to direct_upload.url (step B) before referencing a signed_id.

Array of Equipment Attachment Input (strings) or Equipment Attachment Input (object) (Equipment Attachment Input)

On create (POST /equipment): pass an array of signed_id strings from POST /uploads (with matching purpose). Example:

"photos": ["eyJfcmFpbHMiOnsiZGF0YSI6MTE3OSwicHVyIjoiYmxvYl9pZCJ9fQ==--abc123"]

On update (PATCH /equipment/{id}): pass an action object. Example:

"photos": { "action": "replace", "signed_ids": ["eyJfcmFpbHMiOnsiZGF0YSI6MTE3OSwicHVyIjoiYmxvYl9pZCJ9fQ==--abc123"] }

File bytes must be uploaded to direct_upload.url (step B) before referencing a signed_id.

object (Equipment Pricing Input)

Pricing configuration object. Pass as the top-level pricing property on create/update.

When pricing is true, price_details.internal is required.

object (Equipment Booking Rules Input)

Booking constraint configuration. Pass as the booking_rules property on create/update.

object (Equipment Maintenance Input)

Maintenance contract configuration. Pass as the maintenance property on create/update.

Responses

Request samples

Content type
application/json
Example
{
  • "account_id": 123,
  • "name": "API Microscope",
  • "category": "Equipment",
  • "subcategory": "Microscopy & Imaging",
  • "manufacturer": "Acme",
  • "model_number": "X1",
  • "availability_status": "Always Available"
}

Response samples

Content type
application/json
{
  • "success": true,
  • "equipment": {
    }
}

List Equipment Contact People

Upcoming / Beta notice

This write endpoint is upcoming and not yet publicly released. It is currently in testing and may not be available on all environments. Request and response shapes, validation rules, error formats, and behaviour may change without notice. Do not use in production until announced as generally available. Contact support for early access.


Returns access roles that may be assigned as equipment contact people for a lab. Use the returned id values in contact_access_role_ids when creating or updating equipment.

When to call

Scenario Parameters
Creating new equipment account_id only — returns lab admins and instructors
Updating existing equipment account_id + equipment_id — also includes instructors assigned to that equipment

Authorisation

Requirement Details
OAuth scope write_equipment
Application Must be approved and authorised for the lab (account_id)
User Must have permission to create equipment (no equipment_id) or update the equipment (with equipment_id)

Response

Returns { "contact_access_roles": [ ... ] } where each item includes id, user_id, account_id, name, email, and role (admin or instructor).

Errors

See Errors (Write API) for the full catalogue.

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

Lab account ID.

equipment_id
integer

Equipment ID when updating an existing item. Narrows the instructor list to those assigned to this equipment.

Responses

Response samples

Content type
application/json
Example
{
  • "contact_access_roles": [
    ]
}

Equipment Details

Returns details about a particular piece of equipment. Requires the equipment ID, and the application scope must include read_equipment.

Authorizations:
oauth
path Parameters
id
required
integer

Equipment ID

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "room": "string",
  • "manufacturer": "string",
  • "model": "string",
  • "city": "string",
  • "country": "string",
  • "currency": "string",
  • "charging_type": "string",
  • "description": "string",
  • "category": {
    },
  • "lab": {
    },
  • "contact_person": {
    },
  • "contact_persons": [
    ],
  • "parent_id": 0,
  • "parent_name": "string",
  • "manufacturing_year": "string",
  • "serial_number": "string"
}

Update Equipment

Upcoming / Beta notice

This write endpoint is upcoming and not yet publicly released. It is currently in testing and may not be available on all environments. Request and response shapes, validation rules, error formats, and behaviour may change without notice. Do not use in production until announced as generally available. Contact support for early access.


Updates an existing piece of equipment. Send only the fields you want to change — this is a partial update.

Overview

At least one updatable field must be present in the request body. An empty body returns 422 Unprocessable Entity.

Any field documented for create (except account_id) can be updated, including nested pricing, booking_rules, and maintenance sections.

See the Request body schema (EquipmentUpdateRequestEquipmentMutableFields and nested schemas) for the full parameter reference including EquipmentAttachmentInput action objects for photos and documents.

Authorisation

Requirement Details
OAuth scope write_equipment
Application Must be approved and authorised for the lab that owns the equipment
User Must have permission to update the equipment

Updating file attachments

Unlike create, photos and documents on update use an action object (not a plain array):

Action signed_ids required Effect
extend Yes Add new attachments alongside existing ones
replace Yes Remove all existing attachments of that type and attach the given signed IDs
remove Yes Remove only the attachments matching the given signed IDs
destroy No Remove all attachments of that type

Each signed_id must be registered via POST /uploads (step A) and file bytes uploaded via step B before use.

Response

Returns 200 OK with { success: true, message: "Equipment was updated.", equipment: { ... } }.

Validation errors

Returns 422 Unprocessable Entity with field-level errors when validation fails. No partial updates are applied when validation fails.

See Errors (Write API) for the complete field-level catalogue.

HTTP Condition Response
401 Missing or invalid access token { "error": "unauthorised", ... }
403 Missing write_equipment scope { "error": "resource_authorisation_failure", ... }
403 OAuth application not approved { "error": "unapproved_application", ... }
403 Application not authorised for the lab { "error": "resource_authorisation_failure", ... }
403 User cannot update the equipment { "error": "resource_authorisation_failure", ... }
404 Equipment ID in URL does not exist { "errors": ["equipment_not_found"], ... }
422 Empty body, schema, attachment, or business-rule validation failed { "success": false, "message": "Equipment could not be updated...", "errors": [...] }
500 Unexpected server error { "error": "internal_server_error", ... }

Common 422 causes: empty request body; invalid field values; unsupported photos/documents action; missing signed_ids for extend/replace/remove; unknown signed_id; attachment not on equipment; incomplete upload (step B not done).

Authorizations:
oauth
path Parameters
id
required
integer

Equipment ID

Request Body schema: application/json
required
non-empty
account_id
integer

Lab account ID where the equipment belongs. Required on create. Cannot be changed on update.

name
string non-empty

Display name of the equipment. Required on create.

room
string

Physical location or room name (max 255 characters).

category
string non-empty
Enum: "Equipment" "Parent equipment" "Room/Space" "Desk/Bench" "Other"

Equipment category. Required on create.

subcategory
string

Subcategory name matching the selected category. Required when the category has subcategories (e.g. Microscopy & Imaging for Equipment).

manufacturer
string

Manufacturer name. Required by business rules for Equipment, Other, and Parent equipment categories (max 200 characters).

model_number
string

Model or catalogue number. Required by business rules for Equipment, Other, and Parent equipment categories (max 200 characters).

Equipment Numeric Value (number) or Equipment Numeric Value (string) (Equipment Numeric Value)

Numeric value accepted as a JSON number or decimal string (e.g. 25 or "25.50").

serial_number
string

Equipment serial number (max 255 characters).

availability_status
string
Default: "Always Available"
Enum: "Always Available" "Unavailable"

Whether the equipment can be booked.

description
string

Plain-text description. Rich-text editor formats (HTML or Quill JSON) are not accepted — send plain text only.

lab_rules
string

Plain-text lab-specific usage rules shown to bookers. Send plain text only.

safety_features
string

Plain-text safety information shown to bookers. Send plain text only.

date_of_purchase
string

Purchase date as an ISO 8601 date string (e.g. 2024-01-15).

internal_id
string

Internal inventory identifier (max 100 characters; unique per lab).

Equipment Numeric Value (number) or Equipment Numeric Value (string) (Equipment Numeric Value)

Numeric value accepted as a JSON number or decimal string (e.g. 25 or "25.50").

contact_access_role_ids
Array of integers

Access role IDs for equipment contact people. Use GET /equipment/contact_people?account_id={id} to list valid IDs.

group_ids
Array of integers

IDs of user groups that should have access to book this equipment.

equipment_label_ids
Array of integers

IDs of equipment labels to apply.

maintenance_contract_ids
Array of integers

IDs of maintenance contracts. May also be set inside maintenance.maintenance_contract_ids.

Array of Equipment Attachment Input (strings) or Equipment Attachment Input (object) (Equipment Attachment Input)

On create (POST /equipment): pass an array of signed_id strings from POST /uploads (with matching purpose). Example:

"photos": ["eyJfcmFpbHMiOnsiZGF0YSI6MTE3OSwicHVyIjoiYmxvYl9pZCJ9fQ==--abc123"]

On update (PATCH /equipment/{id}): pass an action object. Example:

"photos": { "action": "replace", "signed_ids": ["eyJfcmFpbHMiOnsiZGF0YSI6MTE3OSwicHVyIjoiYmxvYl9pZCJ9fQ==--abc123"] }

File bytes must be uploaded to direct_upload.url (step B) before referencing a signed_id.

Array of Equipment Attachment Input (strings) or Equipment Attachment Input (object) (Equipment Attachment Input)

On create (POST /equipment): pass an array of signed_id strings from POST /uploads (with matching purpose). Example:

"photos": ["eyJfcmFpbHMiOnsiZGF0YSI6MTE3OSwicHVyIjoiYmxvYl9pZCJ9fQ==--abc123"]

On update (PATCH /equipment/{id}): pass an action object. Example:

"photos": { "action": "replace", "signed_ids": ["eyJfcmFpbHMiOnsiZGF0YSI6MTE3OSwicHVyIjoiYmxvYl9pZCJ9fQ==--abc123"] }

File bytes must be uploaded to direct_upload.url (step B) before referencing a signed_id.

object (Equipment Pricing Input)

Pricing configuration object. Pass as the top-level pricing property on create/update.

When pricing is true, price_details.internal is required.

object (Equipment Booking Rules Input)

Booking constraint configuration. Pass as the booking_rules property on create/update.

object (Equipment Maintenance Input)

Maintenance contract configuration. Pass as the maintenance property on create/update.

Responses

Request samples

Content type
application/json
Example
{
  • "name": "Updated Microscope",
  • "manufacturer": "Updated Acme"
}

Response samples

Content type
application/json
{
  • "success": true,
  • "message": "Equipment was updated.",
  • "equipment": {
    }
}

Equipment Bookings

Returns bookings about a particular piece of equipment. Requires the equipment ID, and the application scope must include read_equipment.

Pagination: This endpoint supports pagination with a default limit of 100 records. Use page and per_page parameters to navigate through large datasets efficiently. Pagination metadata is provided in response headers (X-Total-Records, X-Current-Page, X-Per-Page).

Authorizations:
oauth
path Parameters
id
required
integer

Unique ID of the equipment

query Parameters
page
integer >= 1
Default: 1

Page number (1-based indexing, default: 1)

per_page
integer [ 1 .. 100 ]
Default: 100

Number of records per page (1-100, default: 100, max: 100)

Responses

Response samples

Content type
application/json
[
  • {
    }
]

user

A registered user on the platform

User Resource Owner

Outputs user information when the credential resource owner is a user.

Authorizations:
oauth

Responses

Response samples

Content type
{
  • "id": 0,
  • "first_name": "string",
  • "last_name": "string"
}

projects

Projects within an account

List Projects

Lists all projects under the specified account. Requires read_projects scope.

Pagination: This endpoint supports pagination with a default limit of 100 records. Use page and per_page parameters to navigate through large datasets efficiently. Pagination metadata is provided in response headers (X-Total-Records, X-Current-Page, X-Per-Page).

Authorizations:
oauth
path Parameters
account_id
required
integer

Account ID

query Parameters
page
integer >= 1
Default: 1

Page number (1-based indexing, default: 1)

per_page
integer [ 1 .. 100 ]
Default: 100

Number of records per page (1-100, default: 100, max: 100)

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Project Details

Get the full details of a specific project. Requires read_projects scope.

Authorizations:
oauth
path Parameters
account_id
required
integer

Account ID

id
required
integer

Project ID

Responses

Response samples

Content type
application/json
{
  • "name": "Project 31",
  • "supervisor": "Niklas",
  • "additional_information": null,
  • "funding_codes": [
    ],
  • "selected_users": [ ]
}

groups

List Groups

Lists all groups under the specified lab. Requires read_accounts scope.

Pagination: This endpoint supports pagination with a default limit of 100 records. Use page and per_page parameters to navigate through large datasets efficiently. Pagination metadata is provided in response headers (X-Total-Records, X-Current-Page, X-Per-Page).

Authorizations:
oauth
query Parameters
account
number

The target lab account ID

page
integer >= 1
Default: 1

Page number (1-based indexing, default: 1)

per_page
integer [ 1 .. 100 ]
Default: 100

Number of records per page (1-100, default: 100, max: 100)

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Group Details

Get the full details of a specific group. The application scope must include read_accounts.

Authorizations:
oauth
path Parameters
id
required
integer

Group ID

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "equipment": [
    ]
}