Capabilities / Developers

API quickstart

Create an API key, discover your reports and schema, and make your first request with cURL, Python, or JavaScript.

X4 Tech SolutionsUpdated September 10, 20267 min read

Use the Unity API to inspect reports, discover their data models, execute read-only SQL, and start assistant work from your own application. Requests run as the account that created the API key and respect that account's resource permissions.

This guide takes you from creating a key to your first query. For individual operations, see the HTTP API reference. For every operation available to Unity's assistant, see the agent tool reference.

Create an API key

  1. Sign in to Unity with a regular account. Demo accounts cannot create API keys.
  2. Open the account icon in the header and select API access & sessions.
  3. Enter a recognizable Token name, such as Local development.
  4. Set Expires in days to a value from 1 to 90. The default is 30 days.
  5. Leave Allow changes and assistant runs unchecked for workspace:read. Check it to include workspace:write, which is needed for queries, previews, assistant runs, and workspace changes.
  6. Click Create API token, then Copy token. Unity displays the secret once. If you lose it, revoke that key and create another.

Keep the key in a server environment variable or secret store. Send it in the Authorization header. Do not place it in a URL, commit it to source control, or include it in browser code delivered to your users.

API access and sessions

The menu manages personal API keys and account sign-out. Browser sessions keep the interactive application signed in; API keys authenticate scripts and integrations. Revoke disables one API key. Sign out everywhere revokes all of your browser sessions and API keys. Ordinary sign-out ends the current browser session.

Each key belongs to your account. It is not a separate customer identity or a report-specific grant. When another person needs independent access, give their account the intended report permissions and have them create their own key.

Configure your environment

The hosted API base URL is https://unityapp-backend.azurewebsites.net. Use the backend URL for your environment when running a local or private deployment. The website URL and the API URL can be different.

In a Bash-compatible terminal, set the base URL and enter the key without displaying it:

cURL
export UNITY_API_BASE="https://unityapp-backend.azurewebsites.net"
read -rsp "Unity API key: " UNITY_API_KEY
export UNITY_API_KEY
printf '\n'

In PowerShell, set the same variables:

PowerShell
$env:UNITY_API_BASE = "https://unityapp-backend.azurewebsites.net"
$secret = Read-Host "Unity API key" -AsSecureString
$env:UNITY_API_KEY = [System.Net.NetworkCredential]::new("", $secret).Password
Remove-Variable secret

The examples below use cURL, Python's standard library, or the built-in fetch in Node.js 18 or later. No Unity SDK is required. Run the JavaScript examples as .mjs files in Node, where your key stays on the server.

Make your first request

List the reports your account can access. This request requires workspace:read and does not change a report.

cURL
curl --fail-with-body "$UNITY_API_BASE/api/reports" \
  -H "Authorization: Bearer $UNITY_API_KEY"
Python
import json
import os
from urllib.request import Request, urlopen

base = os.environ["UNITY_API_BASE"].rstrip("/")
request = Request(
    f"{base}/api/reports",
    headers={"Authorization": f"Bearer {os.environ['UNITY_API_KEY']}"},
)
with urlopen(request, timeout=30) as response:
    print(json.dumps(json.load(response), indent=2))
JavaScript
const base = process.env.UNITY_API_BASE.replace(/\/$/, "");
const response = await fetch(`${base}/api/reports`, {
  headers: { Authorization: `Bearer ${process.env.UNITY_API_KEY}` },
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
console.log(await response.json());

The response is a JSON array of accessible reports. An empty array means the account has no reports to list. Use an ID from this response for subsequent requests. Caller identity comes from the key, so you do not need to submit a userId or browser cookie.

Discover a report and its schema

A key identifies the caller; it does not contain a schema. Ask Unity for the report workspace and its attached connections, then inspect the model for the connection you want to query.

Set UNITY_REPORT_ID to a report ID returned by the previous request. UNITY_CONNECTION_ID must identify a connection attached to that report.

cURL
export UNITY_REPORT_ID="YOUR_REPORT_ID"

curl --fail-with-body \
  "$UNITY_API_BASE/api/reports/$UNITY_REPORT_ID/workspace" \
  -H "Authorization: Bearer $UNITY_API_KEY"

# Set this to a connection ID from your report workspace.
export UNITY_CONNECTION_ID="YOUR_CONNECTION_ID"

curl --fail-with-body --get \
  "$UNITY_API_BASE/api/connection-models/$UNITY_CONNECTION_ID/catalog" \
  -H "Authorization: Bearer $UNITY_API_KEY" \
  --data-urlencode "reportId=$UNITY_REPORT_ID" \
  --data-urlencode "kind=entity" \
  --data-urlencode "limit=20"

The model catalogue exposes entities and their fields. Use kind=field to search fields, or kind=relationship to inspect relationships. Set query to search by name. Follow the returned pagination metadata when more matches are available.

For the selected schema in its table-and-column form, request GET /get-selected-schema/{report_id}?connectionId={connection_id}. Report discovery is also available through GET /api/reports/{report_id}/catalog, where you can search pages, visuals, and attached connections.

Execute a query

Use POST /api/sql/execute with your report ID, connection ID, and SQL. This endpoint accepts a single read-only query. It still requires workspace:write, because the current token policy classifies all POST requests as write operations.

The examples assume your model exposes an entity named orders with fields region and amount. Replace those names with exact identifiers from your model catalogue. Model entity names can differ from physical database table names. Use the SQL dialect supported by the connected source.

cURL
curl --fail-with-body "$UNITY_API_BASE/api/sql/execute" \
  -H "Authorization: Bearer $UNITY_API_KEY" \
  -H "Content-Type: application/json" \
  --data "{\"reportId\":\"$UNITY_REPORT_ID\",\"connectionId\":$UNITY_CONNECTION_ID,\"sqlQuery\":\"SELECT region, SUM(amount) AS revenue FROM orders GROUP BY region ORDER BY region\",\"rowLimit\":5}"
Python
import json
import os
from urllib.request import Request, urlopen

payload = {
    "reportId": os.environ["UNITY_REPORT_ID"],
    "connectionId": int(os.environ["UNITY_CONNECTION_ID"]),
    "sqlQuery": (
        "SELECT region, SUM(amount) AS revenue "
        "FROM orders GROUP BY region ORDER BY region"
    ),
    "rowLimit": 5,
}
request = Request(
    os.environ["UNITY_API_BASE"].rstrip("/") + "/api/sql/execute",
    data=json.dumps(payload).encode(),
    headers={
        "Authorization": f"Bearer {os.environ['UNITY_API_KEY']}",
        "Content-Type": "application/json",
    },
    method="POST",
)
with urlopen(request, timeout=60) as response:
    print(json.dumps(json.load(response), indent=2))
JavaScript
const base = process.env.UNITY_API_BASE.replace(/\/$/, "");
const response = await fetch(`${base}/api/sql/execute`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.UNITY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    reportId: process.env.UNITY_REPORT_ID,
    connectionId: Number(process.env.UNITY_CONNECTION_ID),
    sqlQuery: "SELECT region, SUM(amount) AS revenue FROM orders GROUP BY region ORDER BY region",
    rowLimit: 5,
  }),
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
console.log(await response.json());

Illustrative response, shortened to the result fields:

JSON
{
  "columns": ["region", "revenue"],
  "rows": [["North", "1775.00"], ["South", "1835.00"]],
  "rowLimit": 5,
  "limitApplied": true
}

Rows follow the order of columns. Numeric values can be serialized as strings, depending on the source type. Use rowLimit to bound returned rows; it does not bound database scan cost. SQL execution reads connected data and does not automatically create a visual.

Discover agent tools

The running backend provides its own documentation. Retrieve all registered tools, then request one tool's exact input schema:

cURL
curl --fail-with-body \
  "$UNITY_API_BASE/api/agent/documentation?topic=tools" \
  -H "Authorization: Bearer $UNITY_API_KEY"

curl --fail-with-body \
  "$UNITY_API_BASE/api/agent/documentation?toolName=InspectDataModel" \
  -H "Authorization: Bearer $UNITY_API_KEY"

These are discovery requests. Tool names such as InspectDataModel and CreateVisual describe operations used by Unity's assistant; they are not URLs that you can POST to directly. To have Unity plan and execute tool calls, create an agent run. To implement a deterministic integration, call the documented HTTP endpoints yourself.

Understand permissions

Credential or scopeWhat it permits
workspace:readGET and HEAD requests for workspace resources your account can access.
workspace:writeOther workspace methods, including SQL execution, previews, agent runs, and supported edits. Write keys also include read access.
Browser sessionInteractive account management, API key management, billing, sharing grants, and collaboration administration. An API key cannot perform these browser-only operations.

Scopes do not override report roles, connection ownership, or administrator checks. A write key does not turn a View-only report into an editable report. Database permissions still come from the configured connection, and a semantic model is not a substitute for source-level row security.

Revoke the test key

Return to API access & sessions, find your key, and select Revoke. Subsequent requests using it return 401. Revocation also prevents subsequent steps of assistant work associated with the credential; an operation already executing may finish. Revoking a key does not undo saved edits.

To rotate a key, create a replacement, update your integration, verify a request, and revoke the old key. A lost secret cannot be displayed again.

Continue with the HTTP API reference for parameters, response handling, streaming, and errors, or browse the complete agent tool reference.

Questions about your environment? Contact us.