Skip to content

API Overview

Production: https://api.roboscope.example.com/api/v1
Development: http://localhost:8080/api/v1

Currently, the API does not require authentication. Future versions will support:

  • API keys
  • OAuth 2.0
  • JWT tokens

All requests and responses use JSON:

Content-Type: application/json
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Example Space",
...
}
{
"error": "Not Found",
"message": "Work session not found",
"status": 404
}
CodeMeaningDescription
200OKRequest successful
201CreatedResource created successfully
204No ContentDeletion successful
400Bad RequestInvalid request data
404Not FoundResource not found
409ConflictVersion conflict (optimistic locking)
500Internal Server ErrorServer error
GET /api/v1/spaces

Response: Array of Space objects

Example:

Terminal window
curl http://localhost:8080/api/v1/spaces

GET /api/v1/spaces/{id}

Path Parameters:

  • id (UUID): Space identifier

Response: Space object

Example:

Terminal window
curl http://localhost:8080/api/v1/spaces/550e8400-e29b-41d4-a716-446655440000

POST /api/v1/spaces

Request Body:

{
"key": "warehouse-a1",
"name": "Warehouse A1",
"description": "Main warehouse storage area",
"model_glb_url": "https://example.com/models/warehouse.glb",
"model_usdc_url": "https://example.com/models/warehouse.usdc",
"preview_url": "https://example.com/previews/warehouse.jpg",
"scan_url": "https://example.com/scans/warehouse.obj",
"calibration_vector": [1.5, 0.0, 2.0]
}

Response: Created Space object (201)

Example:

Terminal window
curl -X POST http://localhost:8080/api/v1/spaces \
-H "Content-Type: application/json" \
-d '{
"key": "warehouse-a1",
"name": "Warehouse A1",
"calibration_vector": [0, 0, 0]
}'

PATCH /api/v1/spaces/{id}

Path Parameters:

  • id (UUID): Space identifier

Request Body (all fields optional):

{
"name": "Updated Name",
"description": "Updated description",
"calibration_vector": [2.0, 0.0, 3.0]
}

Response: Updated Space object


DELETE /api/v1/spaces/{id}

Path Parameters:

  • id (UUID): Space identifier

Response: 204 No Content

Note: Deletes all associated work sessions and markers (CASCADE)


GET /api/v1/work-sessions?space_id={spaceId}&status={status}&session_type={type}

Query Parameters (all optional):

  • space_id (UUID): Filter by space
  • status (enum): Filter by status (draft, active, done, archived)
  • session_type (enum): Filter by type (inspection, repair, other)

Response: Array of Work Session objects with marker counts

Example:

Terminal window
# All sessions
curl http://localhost:8080/api/v1/work-sessions
# Active inspections in a space
curl "http://localhost:8080/api/v1/work-sessions?space_id=550e8400-e29b-41d4-a716-446655440000&status=active&session_type=inspection"

GET /api/v1/work-sessions/{id}

Path Parameters:

  • id (UUID): Work session identifier

Response: Work Session object with marker count


POST /api/v1/work-sessions

Request Body:

{
"space_id": "550e8400-e29b-41d4-a716-446655440000",
"session_type": "inspection",
"status": "draft",
"started_at": "2025-01-16T09:00:00Z",
"completed_at": null
}

Response: Created Work Session object (201)

Example:

Terminal window
curl -X POST http://localhost:8080/api/v1/work-sessions \
-H "Content-Type: application/json" \
-d '{
"space_id": "550e8400-e29b-41d4-a716-446655440000",
"session_type": "inspection",
"status": "active",
"started_at": "2025-01-16T09:00:00Z"
}'

PATCH /api/v1/work-sessions/{id}

Path Parameters:

  • id (UUID): Work session identifier

Request Body (all fields optional):

{
"status": "done",
"completed_at": "2025-01-16T12:00:00Z",
"version": 3
}

Response: Updated Work Session object

Note: Include version for optimistic concurrency control


DELETE /api/v1/work-sessions/{id}

Path Parameters:

  • id (UUID): Work session identifier

Response: 204 No Content

Note: Deletes all associated markers and marker details (CASCADE)


GET /api/v1/work-sessions/{id}/export

Path Parameters:

  • id (UUID): Work session identifier

Response: Exported work session data (excludes IDs, includes all markers and details)

{
"session_type": "inspection",
"status": "active",
"started_at": "2025-01-16T09:00:00Z",
"completed_at": null,
"meta": {},
"markers": [
{
"label": "Issue 1",
"p1": [0, 0, 0],
"p2": [0.1, 0, 0],
"p3": [0.1, 0.1, 0],
"p4": [0, 0.1, 0],
"color": "#FF0000",
"custom_props": {},
"calibrated_data": null,
"details": {
"center_location_long": 0.05,
"center_location_cross": 0.05,
...
}
}
]
}

POST /api/v1/work-sessions/import

Request Body:

{
"space_id": "target-space-uuid",
"session": {
"session_type": "inspection",
"status": "active",
"started_at": "2025-01-16T09:00:00Z",
"completed_at": null,
"meta": {},
"markers": [...]
}
}

Response: Created Work Session object (201)

Use Cases:

  • Move session to different space
  • Duplicate session for comparison
  • Backup and restore
  • Data migration

POST /api/v1/work-sessions/{id}/calibrate-markers

Path Parameters:

  • id (UUID): Work session identifier

Response: Array of updated Marker objects

Description: Applies space calibration vector to all markers in the session, populating calibrated_data field.


GET /api/v1/markers?work_session_id={sessionId}

Query Parameters (optional):

  • work_session_id (UUID): Filter by work session

Response: Array of Marker objects

Example:

Terminal window
curl "http://localhost:8080/api/v1/markers?work_session_id=660e8400-e29b-41d4-a716-446655440001"

GET /api/v1/markers/{id}

Path Parameters:

  • id (UUID): Marker identifier

Response: Marker object


POST /api/v1/markers

Request Body:

{
"work_session_id": "660e8400-e29b-41d4-a716-446655440001",
"label": "Crack in wall",
"p1": [-0.230, 0.060, 0.030],
"p2": [-0.165, 0.057, 0.037],
"p3": [-0.167, 0.050, 0.262],
"p4": [-0.232, 0.053, 0.255],
"color": "#FF0000",
"custom_props": {
"severity": "medium",
"type": "crack"
},
"calibrated_data": null
}

Response: Created Marker object (201)

Validation:

  • All edge lengths must be ≥ 5mm
  • Coordinates must be finite numbers
  • Points must form valid quadrilateral

POST /api/v1/markers/bulk

Request Body:

{
"markers": [
{
"work_session_id": "660e8400-e29b-41d4-a716-446655440001",
"label": "Marker 1",
"p1": [0, 0, 0],
"p2": [0.1, 0, 0],
"p3": [0.1, 0.1, 0],
"p4": [0, 0.1, 0],
"color": "#FF0000"
},
{
"work_session_id": "660e8400-e29b-41d4-a716-446655440001",
"label": "Marker 2",
"p1": [0.5, 0, 0],
"p2": [0.6, 0, 0],
"p3": [0.6, 0.1, 0],
"p4": [0.5, 0.1, 0],
"color": "#00FF00"
}
]
}

Response: Array of created Marker objects (201)


PATCH /api/v1/markers/{id}

Path Parameters:

  • id (UUID): Marker identifier

Request Body (all fields optional):

{
"label": "Updated label",
"color": "#00FF00",
"custom_props": {
"severity": "high"
},
"version": 2
}

Response: Updated Marker object


DELETE /api/v1/markers/{id}

Path Parameters:

  • id (UUID): Marker identifier

Response: 204 No Content

Note: Deletes associated marker details (CASCADE)


GET /api/v1/markers/{id}/details

Path Parameters:

  • id (UUID): Marker identifier

Response: Marker Details object or 404


PUT /api/v1/markers/{id}/details

Path Parameters:

  • id (UUID): Marker identifier

Request Body:

{
"center_location_long": 0.146,
"center_location_cross": -0.198,
"x_negative": -0.232,
"x_positive": -0.165,
"z_negative": 0.030,
"z_positive": 0.262,
"long_size": 0.232,
"cross_size": 0.067,
"custom_props": {}
}

Response: Marker Details object (200 for update, 201 for create)

Note: Upsert operation - creates if doesn’t exist, updates if exists


DELETE /api/v1/markers/{id}/details

Path Parameters:

  • id (UUID): Marker identifier

Response: 204 No Content


POST /api/v1/markers/{id}/details/calculate

Path Parameters:

  • id (UUID): Marker identifier

Response: Calculated and saved Marker Details object (201)

Description: Automatically calculates all metrics from marker corner points and saves as marker details.


POST /api/v1/work-sessions/{id}/markers/calculate-details

Path Parameters:

  • id (UUID): Work session identifier

Response: Count of calculated marker details

{
"calculated": 25
}

Description: Batch calculates details for all markers in the session.


POST /api/v1/presence/sessions/{sessionId}/join

Path Parameters:

  • sessionId (UUID): Work session identifier

Request Body:

{
"user_id": "user-123",
"user_name": "John Doe"
}

Response: 200 OK


POST /api/v1/presence/sessions/{sessionId}/leave

Path Parameters:

  • sessionId (UUID): Work session identifier

Request Body:

{
"user_id": "user-123"
}

Response: 200 OK


POST /api/v1/presence/sessions/{sessionId}/heartbeat

Path Parameters:

  • sessionId (UUID): Work session identifier

Request Body:

{
"user_id": "user-123"
}

Response: 200 OK

Note: Send every 10 seconds to maintain presence


GET /api/v1/presence/sessions/{sessionId}/users

Path Parameters:

  • sessionId (UUID): Work session identifier

Response: Array of active users

[
{
"user_id": "user-123",
"user_name": "John Doe",
"joined_at": "2025-01-16T10:00:00Z",
"last_seen": "2025-01-16T10:05:23Z"
}
]

POST /api/v1/locks/sessions/{sessionId}/acquire

Path Parameters:

  • sessionId (UUID): Work session identifier

Request Body:

{
"user_id": "user-123",
"ttl": 60
}

Response:

{
"acquired": true
}

Status: 200 if acquired, 409 if already locked


POST /api/v1/locks/sessions/{sessionId}/release

Path Parameters:

  • sessionId (UUID): Work session identifier

Request Body:

{
"user_id": "user-123"
}

Response: 200 OK


GET /api/v1/locks/sessions/{sessionId}/status

Path Parameters:

  • sessionId (UUID): Work session identifier

Response:

{
"locked": true,
"holder": "user-123",
"expires_at": "2025-01-16T10:06:00Z"
}

GET /api/v1/events?entity={entity}&entity_id={id}&kind={kind}&limit={limit}

Query Parameters (all optional):

  • entity (string): Filter by entity type (space, work_session, marker)
  • entity_id (UUID): Filter by specific entity
  • kind (string): Filter by event kind (created, updated, deleted)
  • limit (int): Maximum results (default: 100)

Response: Array of Event objects

[
{
"id": 1,
"kind": "created",
"entity": "marker",
"entity_id": "770e8400-e29b-41d4-a716-446655440002",
"payload": {
"label": "New marker",
"user_id": "user-123"
},
"created_at": "2025-01-16T10:00:00Z"
}
]

Currently not implemented. Future versions will support:

  • 1000 requests per minute per IP
  • 10,000 requests per hour per API key

Not currently supported. Planned for future releases.

API version is included in the URL path: /api/v1/

Breaking changes will increment the version number.

{
"error": "Validation Error",
"message": "Edge 1 too short: 0.003m (minimum 0.005m)",
"status": 400
}
{
"error": "Conflict",
"message": "Version mismatch: expected 3, got 2",
"status": 409
}
{
"error": "Not Found",
"message": "Marker not found",
"status": 404
}
  1. Use bulk endpoints for creating multiple markers
  2. Include version in updates for optimistic concurrency
  3. Filter lists with query parameters to reduce payload
  4. Handle 409 conflicts by refetching and retrying
  5. Calculate details in batch for better performance
  6. Send heartbeats regularly when using presence
  7. Release locks explicitly when done editing