Jacaranda API quickstart

Go from an API key and published world ID to a server-observed, evidence-grounded grade using plain HTTP. No SDK is required. The OpenAPI 3.1 contract is authoritative; this page is a copyable walkthrough of that contract.

What you need

Keep the API key out of source files and shell history. The prompt below reads it without displaying it. Replace the base URL and world ID with values supplied for your team.

export JACARANDA_API_URL="https://api.your-deployment.example"
export JACARANDA_WORLD_ID="YOUR_PUBLISHED_WORLD_ID"
read -r -s -p "Jacaranda API key: " JACARANDA_API_KEY; printf '\n'
export JACARANDA_API_KEY

export JACARANDA_OPERATION_ID="quickstart-$(date +%s)"
export JACARANDA_WORK_DIR="$(mktemp -d)"
trap 'rm -rf "$JACARANDA_WORK_DIR"' EXIT

1. Create a rollout

operation_id is the idempotency identity. Retrying this exact request with the same operation ID and world ID recovers the same rollout; do not reuse it for a different world.

python3 - "$JACARANDA_WORLD_ID" "$JACARANDA_OPERATION_ID" \
  > "$JACARANDA_WORK_DIR/make-request.json" <<'PY'
import json
import sys

json.dump({"world_id": sys.argv[1], "operation_id": sys.argv[2]}, sys.stdout)
PY

curl -sS -D "$JACARANDA_WORK_DIR/make.headers" \
  -o "$JACARANDA_WORK_DIR/make.json" \
  -X POST "$JACARANDA_API_URL/v1/rollouts" \
  -H "Authorization: Bearer $JACARANDA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @"$JACARANDA_WORK_DIR/make-request.json"

python3 -m json.tool "$JACARANDA_WORK_DIR/make.json"
export JACARANDA_ROLLOUT_ID="$(python3 -c \
  'import json,sys; print(json.load(open(sys.argv[1]))["rollout_id"])' \
  "$JACARANDA_WORK_DIR/make.json")"
export JACARANDA_DATA_URL="$(python3 -c \
  'import json,sys; print(json.load(open(sys.argv[1]))["data_plane_url"].rstrip("/"))' \
  "$JACARANDA_WORK_DIR/make.json")"

Use the returned data_plane_url for warehouse, app, and file traffic. Keep using the API base URL for rollout lifecycle, task, and grade operations.

2. Get the assigned task

curl -sS -D "$JACARANDA_WORK_DIR/task.headers" \
  -o "$JACARANDA_WORK_DIR/task.json" \
  -X GET \
  "$JACARANDA_API_URL/v1/rollouts/$JACARANDA_ROLLOUT_ID/tasks/next" \
  -H "Authorization: Bearer $JACARANDA_API_KEY"

python3 -m json.tool "$JACARANDA_WORK_DIR/task.json"
export JACARANDA_TASK_ID="$(python3 -c \
  'import json,sys; print(json.load(open(sys.argv[1]))["task_id"])' \
  "$JACARANDA_WORK_DIR/task.json")"
export JACARANDA_PERIOD_START="$(python3 -c \
  'import json,sys; print(json.load(open(sys.argv[1]))["estimand"]["period_start"])' \
  "$JACARANDA_WORK_DIR/task.json")"
export JACARANDA_PERIOD_END="$(python3 -c \
  'import json,sys; print(json.load(open(sys.argv[1]))["estimand"]["period_end"])' \
  "$JACARANDA_WORK_DIR/task.json")"

Read prompt, estimand, and deliverable_format before investigating. The examples below demonstrate all three data surfaces. Adapt the SQL, API filters, and selected file to the assigned task, and cite only reads that actually support your conclusion.

3. Investigate through the served estate

Warehouse SQL

Queries are read-only DuckDB SQL with positional parameters and bounded pages. This example summarizes the ledger over the task's period.

python3 - "$JACARANDA_PERIOD_START" "$JACARANDA_PERIOD_END" \
  > "$JACARANDA_WORK_DIR/warehouse-request.json" <<'PY'
import json
import sys

json.dump(
    {
        "sql": (
            "SELECT account_code, SUM(debit_cents - credit_cents) AS net_debit_cents "
            "FROM general_ledger WHERE period BETWEEN ? AND ? "
            "GROUP BY account_code ORDER BY account_code"
        ),
        "params": [sys.argv[1], sys.argv[2]],
        "row_limit": 100,
        "evidence_locator": "quickstart-ledger-summary",
    },
    sys.stdout,
)
PY

curl -sS -D "$JACARANDA_WORK_DIR/warehouse.headers" \
  -o "$JACARANDA_WORK_DIR/warehouse.json" \
  -X POST "$JACARANDA_DATA_URL/v1/rollouts/$JACARANDA_ROLLOUT_ID/warehouse/query" \
  -H "Authorization: Bearer $JACARANDA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @"$JACARANDA_WORK_DIR/warehouse-request.json"

python3 -m json.tool "$JACARANDA_WORK_DIR/warehouse.json"

Vendor-shaped app API

curl -sS -D "$JACARANDA_WORK_DIR/app.headers" \
  -o "$JACARANDA_WORK_DIR/app.json" \
  -X GET "$JACARANDA_DATA_URL/v1/rollouts/$JACARANDA_ROLLOUT_ID/apps/netsuite/general-ledger?limit=100" \
  -H "Authorization: Bearer $JACARANDA_API_KEY"

python3 -m json.tool "$JACARANDA_WORK_DIR/app.json"

Files

curl -sS -D "$JACARANDA_WORK_DIR/files.headers" \
  -o "$JACARANDA_WORK_DIR/files.json" \
  -X GET "$JACARANDA_DATA_URL/v1/rollouts/$JACARANDA_ROLLOUT_ID/files?recursive=true&limit=100" \
  -H "Authorization: Bearer $JACARANDA_API_KEY"

python3 -m json.tool "$JACARANDA_WORK_DIR/files.json"
export JACARANDA_FILE_PATH="$(python3 -c \
  'import json,sys; print(json.load(open(sys.argv[1]))["items"][0]["path"])' \
  "$JACARANDA_WORK_DIR/files.json")"
export JACARANDA_FILE_PATH_ENCODED="$(python3 -c \
  'import sys,urllib.parse; print(urllib.parse.quote(sys.argv[1], safe="/"))' \
  "$JACARANDA_FILE_PATH")"

curl -sS -D "$JACARANDA_WORK_DIR/file.headers" \
  -o "$JACARANDA_WORK_DIR/file.bin" \
  -X GET "$JACARANDA_DATA_URL/v1/rollouts/$JACARANDA_ROLLOUT_ID/files/$JACARANDA_FILE_PATH_ENCODED" \
  -H "Authorization: Bearer $JACARANDA_API_KEY"

4. Cite the server-observed evidence

Every completed REST read returns a content-bound Jacaranda-Trace-Event-ID. Extract the receipts from the response headers; never invent them. For paginated operations, follow next_cursor and collect the complete logical receipt from the final page.

export JACARANDA_WAREHOUSE_TRACE_ID="$(python3 -c '
import sys
for line in open(sys.argv[1], encoding="iso-8859-1"):
    name, separator, value = line.partition(":")
    if separator and name.lower() == "jacaranda-trace-event-id":
        print(value.strip())
' "$JACARANDA_WORK_DIR/warehouse.headers")"

export JACARANDA_APP_TRACE_ID="$(python3 -c '
import sys
for line in open(sys.argv[1], encoding="iso-8859-1"):
    name, separator, value = line.partition(":")
    if separator and name.lower() == "jacaranda-trace-event-id":
        print(value.strip())
' "$JACARANDA_WORK_DIR/app.headers")"

export JACARANDA_FILE_TRACE_ID="$(python3 -c '
import sys
for line in open(sys.argv[1], encoding="iso-8859-1"):
    name, separator, value = line.partition(":")
    if separator and name.lower() == "jacaranda-trace-event-id":
        print(value.strip())
' "$JACARANDA_WORK_DIR/file.headers")"

A ceremonial citation does not earn grounding. Your cited reads must support the answer. The gateway, not the client, is trace authority.

5. Submit the answer and inspect the grade

Enter the answer as JSON in the exact shape requested by deliverable_format: for example, a JSON number, string, or object. The evidence claim below binds that conclusion to the three server-issued receipts.

read -r -p "Answer as JSON: " JACARANDA_ANSWER_JSON
export JACARANDA_ANSWER_JSON

python3 - "$JACARANDA_TASK_ID" \
  "$JACARANDA_WAREHOUSE_TRACE_ID" \
  "$JACARANDA_APP_TRACE_ID" \
  "$JACARANDA_FILE_TRACE_ID" \
  > "$JACARANDA_WORK_DIR/grade-request.json" <<'PY'
import json
import os
import sys

answer = json.loads(os.environ["JACARANDA_ANSWER_JSON"])
trace_ids = [value for value in sys.argv[2:] if value]
json.dump(
    {
        "task_id": sys.argv[1],
        "answer": {
            "value": answer,
            "evidence_claims": [
                {
                    "conclusion": answer,
                    "cited_trace_event_ids": trace_ids,
                }
            ],
        },
    },
    sys.stdout,
)
PY

curl -sS -D "$JACARANDA_WORK_DIR/grade.headers" \
  -o "$JACARANDA_WORK_DIR/grade.json" \
  -X POST "$JACARANDA_API_URL/v1/rollouts/$JACARANDA_ROLLOUT_ID/grade" \
  -H "Authorization: Bearer $JACARANDA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @"$JACARANDA_WORK_DIR/grade-request.json"

python3 -m json.tool "$JACARANDA_WORK_DIR/grade.json"

The response contains score, value_ok, grounding_ok, trap_hit, and explanation. A correctness-clean answer with task-relevant citations returns value_ok: true and grounding_ok: true. Eval-class responses also expose score-query usage in the Jacaranda-Evaluation-Budget-Limit, -Used, and -Remaining headers.

6. Delete the exact rollout

Cleanup is explicit. A successful delete returns HTTP 204 with no response body.

curl -sS -D "$JACARANDA_WORK_DIR/delete.headers" \
  -o /dev/null \
  -X DELETE "$JACARANDA_API_URL/v1/rollouts/$JACARANDA_ROLLOUT_ID" \
  -H "Authorization: Bearer $JACARANDA_API_KEY"

Pagination

Errors and safe retries

JSON errors have exactly code, message, and request_id. Preserve the request ID when asking for support. The published contract documents HTTP 400, 401, 403, 404, 405, 409, 413, 415, 429, and 500. A 429 can mean the rate limit or eval score-query budget is exhausted.

Generic MCP over HTTP

MCP wraps the same registered operations at POST /mcp. A generic MCP client initializes, lists tools, and calls a tool. Tool arguments include REST path parameters such as rollout_id. For tool calls, the trace receipt is result._meta.trace_event_id, not an HTTP trace header.

Initialize

curl -sS -X POST "$JACARANDA_API_URL/mcp" \
  -H "Authorization: Bearer $JACARANDA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary '{"jsonrpc":"2.0","id":"init-1","method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"plain-http","version":"1"}}}'

curl -sS -X POST "$JACARANDA_API_URL/mcp" \
  -H "Authorization: Bearer $JACARANDA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary '{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}'

List registered tools

curl -sS -X POST "$JACARANDA_API_URL/mcp" \
  -H "Authorization: Bearer $JACARANDA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary '{"jsonrpc":"2.0","id":"list-1","method":"tools/list","params":{}}'

Call a tool

python3 - "$JACARANDA_ROLLOUT_ID" \
  > "$JACARANDA_WORK_DIR/mcp-call.json" <<'PY'
import json
import sys

json.dump(
    {
        "jsonrpc": "2.0",
        "id": "call-1",
        "method": "tools/call",
        "params": {
            "name": "warehouse.schema",
            "arguments": {"rollout_id": sys.argv[1]},
        },
    },
    sys.stdout,
)
PY

curl -sS -X POST "$JACARANDA_API_URL/mcp" \
  -H "Authorization: Bearer $JACARANDA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @"$JACARANDA_WORK_DIR/mcp-call.json"

Use the OpenAPI contract

Download /openapi.json and select operations by operationId. Each operation declares its bearer authentication, request and response schemas, error responses, matching x-mcp-tool, x-pagination where applicable, and x-trace-receipt. Treat those machine-readable fields as authoritative when this prose and the contract differ.