API Reference
Canonical reference for building automation against the TATER REST API. Covers authentication, the structured error catalog, key scoping, and ready-to-paste snippets in curl, PowerShell, and Python.
Authentication
The TATER API uses a single header for programmatic authentication:
X-API-Key: tater_<32-hex-chars>
Authorization: Bearer ... for API key auth. The
Authorization header is reserved for Entra ID JWT bearer tokens issued to the
browser app. The API explicitly rejects any non-JWT value in Authorization
with HTTP 401 and a structured error. This is by design - see
Common Errors below.
API key format:
- Prefix:
tater_ - Body: 32 lowercase hex characters (16 bytes of cryptographic randomness)
- Example:
tater_3fd88c926edd3a6f66a925de7df4cfe4
Generate keys from Manage → Connections → API Keys in the TATER app. The full key is shown once at creation time - only the prefix is stored after that and shown in the Key list. Keys are SHA-256 hashed at rest in Cosmos DB.
Org-scoped vs unbound keys
Where you generate the key determines what data it can reach:
| Key context at creation | Behavior | Org header required? |
|---|---|---|
| Org-scoped - generated while a specific org is selected in the org switcher | All API calls are auto-scoped to that organization. The key cannot read or write any other org's data even within the same tenant. | No |
| Unbound - generated while no org context is active (rare; SuperAdmin only) | For most endpoints, an unbound key against a multi-org tenant will return 400 AMBIGUOUS_ORG. Use only for tenant-wide cron jobs that loop through orgs. |
Yes - pass ?organizationId=<org-id> on each request |
organizationId through every request.
Full endpoint reference (OpenAPI + Swagger UI)
The complete API surface is published as a machine-readable OpenAPI 3.1 contract, browsable in an interactive Swagger UI:
- Swagger UI: https://api.tatersecurity.com/api/docs — browse and filter every endpoint, with parameters and methods
- OpenAPI document: https://api.tatersecurity.com/api/openapi.json — the raw OpenAPI 3.1 spec (900+ paths), suitable for client generation and import into Postman or similar tools
Both are public and require no authentication — the contract describes the shape of the API, not your data. The spec is regenerated from the API's route declarations and republished with every API deployment, so it always reflects the live surface.
What can I call with an API key?
Not every endpoint in the contract accepts API-key authentication (many are JWT-only browser endpoints). The most useful API-key-friendly surfaces for integrators are:
| Surface | Endpoint(s) | Notes |
|---|---|---|
| BI / flat data | GET /api/reports/powerbi |
21 flat datasets (controls, scans, risks, GRC registers, device fleet, vulnerabilities), JSON or format=csv. See the Power BI Integration guide. |
| Insights reports | GET /api/insights/reports/{id}GET /api/insights/reports/{id}/export |
Run any built-in Insights report and export it as CSV. |
| Endpoint scan data | GET /api/endpoint-scansGET /api/endpoint-scans/latestGET /api/cisa-kev |
Raw endpoint vulnerability scan documents and the CISA KEV catalog. |
| Scan ingestion | POST /api/scans/upload |
Push scan results from external tooling (the runbook ingestion path — see the code examples below). |
| Calendar feed | GET /api/calendar/{token}.jsonGET /api/calendar/{token}.ics |
Compliance-deadline feed. Token-gated rather than API-key: generate the subscription URL in-app, no header needed. |
Beyond these, many operational surfaces (ops tickets, remediations, patch management, evidence jobs, and more) also accept X-API-Key — check the endpoint in the Swagger UI and test with your key.
Common errors
All TATER API errors return a JSON body with error (machine code) and
message (human description). Status codes follow standard semantics.
The five auth-related cases you will see in practice:
| Status | Error code | Trigger | What to do |
|---|---|---|---|
| 401 | UNAUTHORIZED / "Missing API key" |
No X-API-Key header on the request |
Add the header |
| 401 | UNAUTHORIZED / "Invalid authorization header format" |
You sent Authorization: Bearer tater_… or similar |
Move the key value into the X-API-Key header. Do not use Authorization. |
| 401 | UNAUTHORIZED / "Invalid token" |
The key in X-API-Key is malformed, revoked, or does not exist |
Regenerate from Manage → Connections → API Keys |
| 401 | UNAUTHORIZED / "Unbound API key may not scope to a specific org" |
Unbound key tried to access an org-scoped endpoint without setup | Regenerate the key with an org selected, OR pass ?organizationId= for read-only endpoints that accept it |
| 400 | AMBIGUOUS_ORG |
Unbound key against a multi-org tenant, no organizationId hint |
Bind the key to an org, or supply ?organizationId= |
| 400 | VALIDATION_ERROR |
Auth succeeded; request body or query is malformed | Inspect message field for the specific field that failed validation |
Code examples
curl
curl -X POST "https://api.tatersecurity.com/api/scans/upload?tenantId=$TENANT_ID&organizationId=$ORG_ID" \
-H "X-API-Key: tater_3fd88c926edd3a6f66a925de7df4cfe4" \
-H "Content-Type: application/json" \
--data @scan-payload.json
PowerShell
$apiKey = 'tater_3fd88c926edd3a6f66a925de7df4cfe4'
$tenantId = '00000000-0000-0000-0000-000000000000'
$orgId = 'org-9c305e0e-cf02-4028-8ef1-edead8fdaee5'
$headers = @{
'X-API-Key' = $apiKey
'Content-Type' = 'application/json'
}
$body = Get-Content -Raw scan-payload.json
$uri = "https://api.tatersecurity.com/api/scans/upload?tenantId=$tenantId&organizationId=$orgId"
$response = Invoke-WebRequest -Uri $uri -Method POST -Headers $headers -Body $body
$response.Content | ConvertFrom-Json
Python
import requests, json
api_key = 'tater_3fd88c926edd3a6f66a925de7df4cfe4'
tenant_id = '00000000-0000-0000-0000-000000000000'
org_id = 'org-9c305e0e-cf02-4028-8ef1-edead8fdaee5'
with open('scan-payload.json') as f:
payload = json.load(f)
r = requests.post(
'https://api.tatersecurity.com/api/scans/upload',
params = {'tenantId': tenant_id, 'organizationId': org_id},
headers = {'X-API-Key': api_key},
json = payload,
timeout = 60,
)
r.raise_for_status()
print(r.json())
Key management best practices
- Per-integration key - generate a separate API key for each automation (RMM, SIEM enrichment, Power Automate flow, internal script). Revoking one will not break the others.
- Store as a secret - never check API keys into source control. Use Key Vault, Azure DevOps Library variables, GitHub Secrets, etc.
- Audit log shows usage - every API-key-authenticated write is logged with
via=apiand the key'skeyIdin the audit trail. Filter on Activity Log → Channel → API to review automated writes. - Rotate yearly - generate a new key, deploy it to the integration, verify it works, then revoke the old key from Manage → Connections → API Keys.
Related guides
- Swagger UI / openapi.json - the live, machine-readable endpoint reference
- Power BI Integration - flat data endpoint at
GET /api/reports/powerbi - Power Automate Integration - custom connector +
scan.completedwebhook trigger - MCP Server Setup - Claude / Copilot agent integration via Model Context Protocol
- Settings Reference - where to manage API keys in the app
- Developer Troubleshooting - full pitfall catalog
TATER