Skip to content

API Specification: Mappings

REST API specification for Mapping resource management in the Graph OLAP Platform Control Plane.

  • api.common.spec.md - Authentication, base URL, data formats, response patterns, error codes
  • requirements.md - Mapping definition structure (node_definitions, edge_definitions JSON schema)
  • data.model.spec.md - Database schema for mappings and mapping_versions

MethodPathDescription
GET/mappingsList mappings with filters
POST/mappingsCreate a new mapping
GET/mappings/{id}Get mapping with current version
PUT/mappings/{id}Update mapping (creates new version)
DELETE/mappings/{id}Delete mapping
POST/mappings/{id}/copyCopy mapping to new owner
PUT/mappings/{id}/lifecycleUpdate TTL and timeout
GET/mappings/{id}/treeGet resource tree (versions → snapshots → instances)
GET/mappings/{id}/versionsList all versions
GET/mappings/{id}/versions/{v}Get specific version
GET/mappings/{id}/versions/{v1}/diff/{v2}Compare two versions
GET/mappings/{id}/instancesList instances for mapping

GET /mappings

Query Parameters:

ParameterTypeDefaultDescription
ownerstring-Filter by owner_username
searchstring-Text search on name, description
created_aftertimestamp-Filter by created_at >= value
created_beforetimestamp-Filter by created_at <= value
sort_bystringcreated_atSort field: name, created_at, current_version
sort_orderstringdescasc or desc
offsetinteger0Records to skip
limitinteger50Max records (max: 100)

Response: 200 OK

{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"owner_username": "alice.smith",
"name": "Customer Transactions",
"description": "Graph mapping for customer purchase behavior",
"current_version": 3,
"created_at": "2025-01-10T08:00:00Z",
"updated_at": "2025-01-15T10:30:00Z",
"ttl": null,
"inactivity_timeout": "P30D",
"snapshot_count": 5
}
],
"meta": {
"request_id": "req-uuid",
"total": 42,
"offset": 0,
"limit": 50
}
}

GET /mappings/:id

Returns mapping header with current version details.

Response: 200 OK (see requirements.md for node_definitions/edge_definitions schema)

{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"owner_username": "alice.smith",
"name": "Customer Transactions",
"description": "Graph mapping for customer purchase behavior",
"current_version": 3,
"created_at": "2025-01-10T08:00:00Z",
"updated_at": "2025-01-15T10:30:00Z",
"ttl": null,
"inactivity_timeout": "P30D",
"version": {
"version": 3,
"change_description": "Added product category property",
"node_definitions": ["..."],
"edge_definitions": ["..."],
"created_at": "2025-01-15T10:30:00Z",
"created_by": "user-uuid",
"created_by_name": "Alice Smith"
}
}
}

Response: 404 Not Found

{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "Mapping not found",
"details": {"id": "550e8400-e29b-41d4-a716-446655440000"}
}
}

POST /mappings

Request Body: (see requirements.md for node_definitions/edge_definitions schema)

{
"name": "Customer Transactions",
"description": "Graph mapping for customer purchase behavior",
"node_definitions": ["..."],
"edge_definitions": ["..."],
"ttl": null,
"inactivity_timeout": "P30D"
}

Response: 201 Created

{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"owner_username": "alice.smith",
"name": "Customer Transactions",
"current_version": 1,
"created_at": "2025-01-15T10:30:00Z"
}
}

Response: 400 Bad Request

{
"error": {
"code": "VALIDATION_FAILED",
"message": "Invalid request body",
"details": {
"errors": [
{"field": "node_definitions[0].label", "message": "Label is required"},
{"field": "edge_definitions[0].from_node", "message": "Referenced node 'Customer' not found in node_definitions"}
]
}
}
}

PUT /mappings/:id

Creates a new immutable version. Requires change_description.

Request Body:

{
"name": "Customer Transactions v2",
"description": "Updated description",
"change_description": "Added product category property",
"node_definitions": ["..."],
"edge_definitions": ["..."]
}

Response: 200 OK

{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"current_version": 4,
"updated_at": "2025-01-15T11:00:00Z"
}
}

Response: 400 Bad Request (missing change_description)

{
"error": {
"code": "VALIDATION_FAILED",
"message": "change_description is required when updating mapping definitions",
"details": {"field": "change_description"}
}
}

Response: 403 Forbidden

{
"error": {
"code": "PERMISSION_DENIED",
"message": "Only owner or admin can update this mapping",
"details": {"owner_username": "other.user", "your_role": "analyst"}
}
}

DELETE /mappings/:id

Fails if any snapshots exist for any version.

Response: 200 OK

{
"data": {"deleted": true}
}

Response: 409 Conflict

{
"error": {
"code": "RESOURCE_HAS_DEPENDENCIES",
"message": "Cannot delete mapping with existing snapshots",
"details": {"snapshot_count": 3}
}
}

POST /mappings/:id/copy

Creates a new mapping with the current version’s definitions. Caller becomes owner.

Request Body:

{
"name": "My Copy of Customer Transactions"
}

Response: 201 Created

{
"data": {
"id": "new-mapping-uuid",
"owner_username": "alice.smith",
"name": "My Copy of Customer Transactions",
"current_version": 1,
"created_at": "2025-01-15T10:30:00Z"
}
}

PUT /mappings/:id/lifecycle

Request Body:

{
"ttl": "P90D",
"inactivity_timeout": "P30D"
}

Response: 200 OK

{
"data": {
"id": "mapping-uuid",
"ttl": "P90D",
"inactivity_timeout": "P30D",
"updated_at": "2025-01-15T10:30:00Z"
}
}

Response: 400 Bad Request (exceeds hard limit)

{
"error": {
"code": "VALIDATION_FAILED",
"message": "TTL exceeds maximum allowed",
"details": {"requested": "P400D", "max_allowed": "P365D"}
}
}

GET /mappings/:id/versions

Query Parameters:

ParameterTypeDefaultDescription
offsetinteger0Records to skip
limitinteger50Max records (max: 100)

Response: 200 OK

{
"data": [
{
"version": 3,
"change_description": "Added product category property",
"created_at": "2025-01-15T10:30:00Z",
"created_by": "user-uuid",
"created_by_name": "Alice Smith"
},
{
"version": 2,
"change_description": "Fixed customer SQL query",
"created_at": "2025-01-12T14:00:00Z",
"created_by": "user-uuid",
"created_by_name": "Alice Smith"
},
{
"version": 1,
"change_description": null,
"created_at": "2025-01-10T08:00:00Z",
"created_by": "user-uuid",
"created_by_name": "Alice Smith"
}
],
"meta": {"total": 3, "offset": 0, "limit": 50}
}

GET /mappings/:id/versions/:version

Response: 200 OK

{
"data": {
"mapping_id": "mapping-uuid",
"version": 2,
"change_description": "Fixed customer SQL query",
"node_definitions": ["..."],
"edge_definitions": ["..."],
"created_at": "2025-01-12T14:00:00Z",
"created_by": "user-uuid",
"created_by_name": "Alice Smith"
}
}

Response: 404 Not Found

{
"error": {
"code": "MAPPING_VERSION_NOT_FOUND",
"message": "Version 5 not found for mapping",
"details": {"mapping_id": "mapping-uuid", "version": 5, "latest_version": 3}
}
}

GET /mappings/:id/versions/:v1/diff/:v2

Returns a diff between two versions of a mapping, showing added, removed, and modified node/edge definitions.

Response: 200 OK

{
"data": {
"mapping_id": "mapping-uuid",
"from_version": 2,
"to_version": 3,
"summary": {
"nodes_added": 1,
"nodes_removed": 0,
"nodes_modified": 1,
"edges_added": 0,
"edges_removed": 0,
"edges_modified": 1
},
"changes": {
"nodes": [
{
"label": "Customer",
"change_type": "modified",
"fields_changed": ["sql", "properties"],
"from": {
"sql": "SELECT customer_id, name FROM analytics.customers",
"properties": [{"name": "name", "type": "STRING"}]
},
"to": {
"sql": "SELECT customer_id, name, city FROM analytics.customers",
"properties": [
{"name": "name", "type": "STRING"},
{"name": "city", "type": "STRING"}
]
}
},
{
"label": "Supplier",
"change_type": "added",
"from": null,
"to": {
"label": "Supplier",
"sql": "SELECT supplier_id, name FROM analytics.suppliers",
"primary_key": {"name": "supplier_id", "type": "STRING"},
"properties": [{"name": "name", "type": "STRING"}]
}
}
],
"edges": [
{
"type": "PURCHASED",
"change_type": "modified",
"fields_changed": ["properties"],
"from": {
"properties": [{"name": "amount", "type": "DOUBLE"}]
},
"to": {
"properties": [
{"name": "amount", "type": "DOUBLE"},
{"name": "purchase_date", "type": "DATE"}
]
}
}
]
}
}
}

Response: 404 Not Found

{
"error": {
"code": "MAPPING_VERSION_NOT_FOUND",
"message": "Version 5 not found for mapping",
"details": {"mapping_id": "mapping-uuid", "version": 5, "latest_version": 3}
}
}

GET /mappings/:id/tree

Returns the full hierarchy of versions, snapshots, and instances for a mapping.

Query Parameters:

ParameterTypeDefaultDescription
include_instancesbooleantrueInclude instance details in response
statusstring-Filter snapshots by status

Response: 200 OK

{
"data": {
"id": "mapping-uuid",
"name": "Customer Transactions",
"owner_username": "alice.smith",
"current_version": 3,
"versions": [
{
"version": 3,
"change_description": "Added product category property",
"created_at": "2025-01-15T10:30:00Z",
"snapshot_count": 1,
"snapshots": [
{
"id": "snapshot-uuid-3",
"name": "Latest Snapshot",
"status": "ready",
"created_at": "2025-01-15T11:00:00Z",
"instance_count": 2,
"instances": [
{"id": "instance-uuid-1", "name": "Analysis 1", "status": "running"},
{"id": "instance-uuid-2", "name": "Analysis 2", "status": "starting"}
]
}
]
},
{
"version": 2,
"change_description": "Fixed customer SQL query",
"created_at": "2025-01-12T14:00:00Z",
"snapshot_count": 2,
"snapshots": [
{
"id": "snapshot-uuid-2",
"name": "January Snapshot",
"status": "ready",
"created_at": "2025-01-12T15:00:00Z",
"instance_count": 0,
"instances": []
},
{
"id": "snapshot-uuid-1",
"name": "Test Snapshot",
"status": "failed",
"created_at": "2025-01-12T14:30:00Z",
"instance_count": 0,
"instances": []
}
]
},
{
"version": 1,
"change_description": null,
"created_at": "2025-01-10T08:00:00Z",
"snapshot_count": 0,
"snapshots": []
}
],
"totals": {
"version_count": 3,
"snapshot_count": 3,
"instance_count": 2
}
}
}

GET /mappings/:id/instances

Returns all instances created from any snapshot of this mapping.

Query Parameters:

ParameterTypeDefaultDescription
offsetinteger0Records to skip
limitinteger50Max records (max: 100)

Response: 200 OK

{
"data": [
{
"id": "instance-uuid",
"snapshot_id": "snapshot-uuid",
"snapshot_name": "January 2025 Snapshot",
"owner_username": "alice.smith",
"wrapper_type": "ryugraph",
"name": "My Analysis Instance",
"status": "running",
"created_at": "2025-01-15T10:30:00Z"
}
],
"meta": {"total": 3, "offset": 0, "limit": 50}
}

Notes:

  • Returns instances across all versions of the mapping (via snapshot relationships)
  • Use this to find all active graph instances associated with a mapping

CodeHTTP StatusDescription
VALIDATION_FAILED400Request body validation failed
RESOURCE_NOT_FOUND404Mapping not found
MAPPING_VERSION_NOT_FOUND404Requested version does not exist
PERMISSION_DENIED403User not authorized (not owner, not admin)
RESOURCE_HAS_DEPENDENCIES409Cannot delete (snapshots exist)