Curiosity

API Usage and Tokens

This page is the practical guide to calling the Workspace from external code: how to authenticate, how to invoke endpoints, how to handle errors, pagination, retries, and versioning. For the conceptual map of API surfaces, see API Overview. For the exact contract of each built-in route, see the REST API reference.

Picking the right token

Three token types — pick the smallest blast radius that fits the caller:

Caller Token type Where it comes from
A user signed into the UI or a custom interface Session JWT The login flow (POST /api/login/create, or SSO).
A connector running on your CI server or a job runner API token, scoped to ingestion Settings → API Tokens in the workspace UI.
A third-party system that only calls one of your endpoints Endpoint token, scoped to the endpoint path Settings → Custom Endpoints → → Tokens.

The complete scope matrix and rotation procedure is on Token scopes.

Creating an API token

  1. Sign in as an admin.
  2. Settings → API Tokens → Create token.
  3. Name the token after the caller (e.g., crm-sync-connector).
  4. Pick the smallest set of scopes the caller needs (ingestion, read, search, endpoints:run, …).
  5. Copy the token — it's displayed once and can't be recovered.
  6. Store the token in your secret manager. Reference it from runtime config; never commit it to source.

Sending requests

All authenticated requests use a bearer header:

Authorization: Bearer <token>
Content-Type: application/json
Accept: application/json

Bodies are JSON. Avoid query-string tokens — they leak into proxy logs.

Calling a custom endpoint (curl)

curl -X POST "https://workspace.example.com/api/endpoints/run/similar-tickets" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "screen flicker after firmware update",
    "productSku": "PRO-14",
    "limit": 5
  }'

Calling a custom endpoint with an endpoint token

curl -X POST "https://workspace.example.com/api/endpoints/token/run/similar-tickets" \
  -H "Authorization: Bearer $ENDPOINT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "query": "..." }'

Calling from C# (Curiosity.Library)

using var workspace = await Workspace.ConnectAsync(
    baseUrl: "https://workspace.example.com",
    apiToken: Environment.GetEnvironmentVariable("WORKSPACE_TOKEN"));

// Inside the workspace — your connector code uses the SDK directly.
await workspace.Graph.CreateNodeSchemaAsync<Ticket>();
workspace.Graph.TryAdd(new Ticket { Id = "T-1", Subject = "..." });
await workspace.Graph.CommitPendingAsync();

Calling from Python

import os, requests

token = os.environ["WORKSPACE_TOKEN"]
r = requests.post(
    "https://workspace.example.com/api/endpoints/run/similar-tickets",
    headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"},
    json={"query": "screen flicker", "limit": 5},
    timeout=30,
)
r.raise_for_status()
print(r.json())

Response shape

Successful responses are bare JSON values shaped by your endpoint:

[
  {
    "UID": "abc123…",
    "Type": "Ticket",
    "Id": "T-9182",
    "Subject": "Screen flicker after 5.1.2 firmware"
  }
]

Errors share a standard envelope (see Error codes):

{
  "error": {
    "code": "insufficient_scope",
    "message": "Token is valid but missing the 'ingestion' scope.",
    "details": { "required": "ingestion", "granted": ["read"] }
  },
  "traceId": "0HMVGB1J8K8I3:00000007"
}

Always log the traceId from error responses — it correlates 1:1 with server-side logs.

Pagination

List-style endpoints accept skip and take query parameters and return:

{ "items": [...], "total": 1248, "skip": 0, "take": 50 }

Treat total as advisory for large traversals. The robust pattern:

skip, take = 0, 100
while True:
    page = requests.post(url, json={"skip": skip, "take": take}, ...).json()
    for item in page["items"]:
        process(item)
    if len(page["items"]) < take:
        break
    skip += take

Rate limiting and retries

The workspace can return 429 Too Many Requests with a Retry-After: <seconds> header. The recommended client retry policy:

  • Retry on 429, 502, 503, 504, and other transient 5xx responses with no error.code set.
  • Use exponential backoff with jitter capped at 60 seconds.
  • Stop after 5 attempts and surface the failure.

A C# helper is in Error codes → Retry policy template.

Do not retry:

  • 400, 401, 403, 404, 409, 422 — these need a code change or a config change, not another attempt.

Versioning

  • Built-in routes are versioned by the workspace image tag (curiosityai/curiosity:vX.Y.Z). Breaking changes ship with a major version bump.
  • Your custom endpoints are versioned by you. The recommended convention is to put the version in the endpoint name (similar-tickets-v2) and keep the previous version live during the deprecation window.
  • Endpoint and AI tool definitions can be exported from the workspace and stored in git, so promotions across environments are reviewable diffs.

What to put behind a custom endpoint vs an API call

Need Surface
Insert/update graph data on a schedule API call via Curiosity.Library SDK from your connector
Run a domain-specific search that combines facets, graph constraints, and ranking Custom endpoint
Expose graph queries to an external dashboard Custom endpoint with an endpoint token
Let the chat assistant retrieve data AI tool
Periodic enrichment / reindex / aggregate Scheduled task

Next steps

© 2026 Curiosity. All rights reserved.
Powered by Neko