Sandbox workspace service#

Service for managing demo workbooks in sandbox workspaces. All endpoints validate that the provided workspace has the human-readable ID “sandbox”.

OpenAPI file: SandboxWorkspaceService.json

Endpoints#

Get demo workbooks#

GET /scout/v1/sandbox-workspace/{workspaceRid}/demo-workbooks

Returns the list of demo workbook RIDs for the given sandbox workspace.

Path parameters

workspaceRid string (RID) required

​

Response

notebookRids array of string (RID)

​

Request

curl "https://api.gov.nominal.io/api/scout/v1/sandbox-workspace/<workspace rid>/demo-workbooks" \
  -H "Authorization: Bearer <api key>"
import requests

response = requests.get(
    "https://api.gov.nominal.io/api/scout/v1/sandbox-workspace/<workspace rid>/demo-workbooks",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.get(
    "https://api.gov.nominal.io/api/scout/v1/sandbox-workspace/<workspace rid>/demo-workbooks",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.get(
            "https://api.gov.nominal.io/api/scout/v1/sandbox-workspace/<workspace rid>/demo-workbooks",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "notebookRids": [
    "<notebook rid>"
  ]
}

Set demo workbooks#

PUT /scout/v1/sandbox-workspace/{workspaceRid}/demo-workbooks

Sets the list of demo workbook RIDs for the given sandbox workspace, replacing any existing entries.

Path parameters

workspaceRid string (RID) required

​

Body

notebookRids array of string (RID)

​

Response

No content (HTTP 204).

Request

curl -X PUT "https://api.gov.nominal.io/api/scout/v1/sandbox-workspace/<workspace rid>/demo-workbooks" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "notebookRids": [
    "<notebook rid>"
  ]
}'
import requests

response = requests.put(
    "https://api.gov.nominal.io/api/scout/v1/sandbox-workspace/<workspace rid>/demo-workbooks",
    headers={"Authorization": "Bearer <api key>"},
    json={"notebookRids": ["<notebook rid>"]},
)
response.raise_for_status()
import httpx

response = httpx.put(
    "https://api.gov.nominal.io/api/scout/v1/sandbox-workspace/<workspace rid>/demo-workbooks",
    headers={"Authorization": "Bearer <api key>"},
    json={"notebookRids": ["<notebook rid>"]},
)
response.raise_for_status()
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.put(
            "https://api.gov.nominal.io/api/scout/v1/sandbox-workspace/<workspace rid>/demo-workbooks",
            headers={"Authorization": "Bearer <api key>"},
            json={"notebookRids": ["<notebook rid>"]},
        ) as response:
            response.raise_for_status()


asyncio.run(main())

Response: 204

No content.

Add demo workbooks#

POST /scout/v1/sandbox-workspace/{workspaceRid}/demo-workbooks

Appends workbooks to the existing demo workbook list. If archiveOnLabelConflict is true, existing workbooks with an exact label-set match are archived along with all related resources instead of raising an error. The cascade performs a full graph traversal: starting from the workbook’s data scope (asset RIDs or run RIDs), it alternates between discovering runs linked to assets and assets linked to runs until convergence. All discovered assets, runs, datasets (from both asset and run data scopes), and events (from snapshot refs and from all discovered assets) are then archived. This ensures no orphaned resources remain when demo workbooks are replaced. Partial (subset/superset) label conflicts always raise an error.

Path parameters

workspaceRid string (RID) required

​

Body

notebookRids array of string (RID)

​

archiveOnLabelConflict boolean

When true, existing workbooks with an exact label-set match are archived instead of raising an error, along with all related resources discovered via full graph traversal: the workbook’s data scope seeds initial assets or runs, then the system alternates between discovering runs linked to assets and assets linked to runs until no new resources are found. All discovered assets, runs, datasets (from both asset and run data scopes), and events (from the workbook’s snapshot refs and from all discovered assets) are archived. This is intended for demo workbook replacement flows where all resources are recreated from scratch. Partial (subset/superset) label conflicts always raise an error. Defaults to false.

Response

No content (HTTP 204).

Request

curl -X POST "https://api.gov.nominal.io/api/scout/v1/sandbox-workspace/<workspace rid>/demo-workbooks" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "notebookRids": [
    "<notebook rid>"
  ],
  "archiveOnLabelConflict": true
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/scout/v1/sandbox-workspace/<workspace rid>/demo-workbooks",
    headers={"Authorization": "Bearer <api key>"},
    json={"notebookRids": ["<notebook rid>"], "archiveOnLabelConflict": True},
)
response.raise_for_status()
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/scout/v1/sandbox-workspace/<workspace rid>/demo-workbooks",
    headers={"Authorization": "Bearer <api key>"},
    json={"notebookRids": ["<notebook rid>"], "archiveOnLabelConflict": True},
)
response.raise_for_status()
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/scout/v1/sandbox-workspace/<workspace rid>/demo-workbooks",
            headers={"Authorization": "Bearer <api key>"},
            json={"notebookRids": ["<notebook rid>"], "archiveOnLabelConflict": True},
        ) as response:
            response.raise_for_status()


asyncio.run(main())

Response: 204

No content.

Errors#

Errors shows how these errors are sent.

Each error’s errorName is SandboxWorkspace: followed by its name below.

Status

Name

Notes

400

DemoWorkbookAlreadyArchived

400

DemoWorkbookDescriptionRequired

400

DemoWorkbookDuplicateLabels

400

DemoWorkbookLabelsRequired

400

DemoWorkbookMustBePublished

400

DemoWorkbookTitleRequired

400

WorkspaceNotSandbox

Page design based on Scalar, MIT License.