Skip to main content

Control Plane API

The HatiData control plane exposes a RESTful API for all management operations. The dashboard is itself a client of these endpoints. Every request that is not a live query goes through the control plane.


Overview

Base URL

https://api.hatidata.com/v1

All endpoints are prefixed with /v1. Request and response bodies are JSON.

Authentication

Every request must include one of three authentication methods:

MethodHeaderUse Case
JWTAuthorization: Bearer <jwt_token>Dashboard users, SSO sessions
API KeyAuthorization: ApiKey hd_live_...Programmatic access, SDKs, agents
FederatedAuthorization: Bearer <cloud_token>AWS STS, GCP Workload Identity, Azure AD
# API key authentication
curl -H "Authorization: ApiKey hd_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" \
https://api.hatidata.com/v1/organizations/org_abc

# JWT authentication
curl -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
https://api.hatidata.com/v1/organizations/org_abc

Rate Limits

Rate limits are applied per authentication identity:

TierRequests/minBurst
Free6010
Cloud30050
Growth1,000100
Enterprise10,000500

Rate limit headers are included in every response:

X-RateLimit-Limit: 300
X-RateLimit-Remaining: 298
X-RateLimit-Reset: 1708000060

When rate limited, the API returns 429 Too Many Requests with a Retry-After header.

Error Format

All errors follow a consistent structure:

{
"error": {
"code": "VALIDATION_ERROR",
"message": "Field 'email' is required",
"details": { "field": "email", "constraint": "required" },
"request_id": "req_a1b2c3d4"
}
}
HTTP StatusCodeDescription
400VALIDATION_ERRORInvalid request body or parameters
401UNAUTHORIZEDMissing or invalid authentication
403FORBIDDENInsufficient permissions or scope
404NOT_FOUNDResource does not exist
409CONFLICTResource already exists or state conflict
422POLICY_VIOLATIONRequest blocked by ABAC policy
429RATE_LIMITEDToo many requests
500INTERNAL_ERRORUnexpected server error

Pagination

List endpoints use cursor-based pagination:

{
"data": [...],
"pagination": {
"cursor": "cur_next123",
"has_more": true,
"total": 1250
}
}

Pass ?limit=50&cursor=cur_xyz to paginate. Default limit is 50; maximum is 200.

Health Check

GET /health — public, no authentication required.

{ "status": "healthy", "version": "1.0.0", "uptime_seconds": 86400 }

Query Proxy

The proxy accepts SQL over the Postgres wire protocol (port 5439) and via REST. All paths share the same 15-stage pipeline: semaphore → table extract → policy check → cost estimate → quota check → row filter → vector embed → transpile → snapshot pin → execute → dirty track + WAL → AI heal → column mask → meter → audit.

Execute Query

POST /v1/environments/{env_id}/query

Execute SQL and receive results as JSON. Requires query:read scope (or query:write for DDL/DML).

Request:

curl -X POST https://api.hatidata.com/v1/environments/env_prod_x1y2/query \
-H "Authorization: ApiKey hd_live_..." \
-H "Content-Type: application/json" \
-d '{
"sql": "SELECT name, region FROM customers WHERE region = '\''US'\'' LIMIT 5",
"agent_id": "data-analyst-v2",
"agent_framework": "langchain"
}'

Response 200 OK:

{
"query_id": "qry_a1b2c3d4",
"columns": [
{ "name": "name", "type": "VARCHAR" },
{ "name": "region", "type": "VARCHAR" }
],
"rows": [["Alice Chen", "US"], ["Bob Smith", "US"]],
"row_count": 2,
"execution_time_ms": 8,
"credits_consumed": 1,
"columns_masked": [],
"cache_hit": false
}
FieldTypeRequiredDescription
sqlstringYesSQL query (Snowflake syntax auto-transpiled)
agent_idstringNoAgent identifier for policy targeting
agent_frameworkstringNoFramework name (langchain, crewai, etc.)
timeout_msintegerNoQuery timeout (default: 30000, max: 300000)
formatstringNojson (default), csv, or arrow

Execute Query — Arrow Format

POST /v1/environments/{env_id}/query/arrow

Execute SQL and receive results as base64-encoded Apache Arrow format. Eliminates JSON serialization overhead for large analytical result sets. Requires query:read scope. Available on Cloud and Enterprise tiers.

Request:

curl -X POST https://api.hatidata.com/v1/environments/env_prod_x1y2/query/arrow \
-H "Authorization: ApiKey hd_live_..." \
-H "Content-Type: application/json" \
-d '{ "sql": "SELECT * FROM orders LIMIT 10000" }'

Response 200 OK:

{
"format": "arrow_ipc_base64",
"data": "QVJST1cxAAAAAAoAAAAA...",
"rows": 10000,
"execution_time_ms": 14
}

Decode in Python: pyarrow.ipc.open_stream(io.BytesIO(base64.b64decode(result["data"]))).read_all().


Organizations

Organizations are the top-level resource. Every user, environment, policy, and API key belongs to an organization.

MethodPathDescriptionRole
POST/v1/organizationsCreate organizationAuthenticated
GET/v1/organizations/{org_id}Get organization detailsMember
PUT/v1/organizations/{org_id}Update name, billing email, settingsOwner / Admin

Create organization — request:

curl -X POST https://api.hatidata.com/v1/organizations \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Corp",
"slug": "acme-corp",
"billing_email": "billing@acme.com",
"cloud_region": "us-east-1"
}'

Response 201 Created:

{
"org_id": "org_a1b2c3d4",
"name": "Acme Corp",
"slug": "acme-corp",
"tier": "free",
"status": "active",
"cloud_region": "us-east-1",
"created_at": "2026-02-16T10:00:00Z"
}

Organization status values: active, pending_payment, provisioning, suspended, cancelled.

The slug and cloud_region fields are immutable after creation.


Users

Users belong to an organization and carry a role that governs all access decisions.

MethodPathDescriptionRole
GET/v1/organizations/{org_id}/usersList usersOwner / Admin
POST/v1/organizations/{org_id}/users/inviteInvite user by emailOwner / Admin
PUT/v1/organizations/{org_id}/users/{user_id}/roleChange roleOwner / Admin
DELETE/v1/organizations/{org_id}/users/{user_id}Remove userOwner / Admin

Available roles:

RoleDescription
ownerFull access including billing and org deletion
adminManage users, environments, policies, API keys
developerCreate and run queries; manage schemas; write access
analystRead-only query access to all non-restricted tables
auditorRead-only access to audit logs, policies, and compliance data
service_accountAccess governed by API key scopes (for programmatic integrations)

Invite user — request:

curl -X POST https://api.hatidata.com/v1/organizations/org_a1b2c3d4/users/invite \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{ "email": "bob@acme.com", "role": "developer" }'

Response 201 Created:

{
"user_id": "usr_a4b5c6",
"email": "bob@acme.com",
"role": "developer",
"status": "invited",
"invited_at": "2026-02-16T10:00:00Z"
}

API Keys

API keys are scoped to environments, hashed with Argon2id, and support rotation with a configurable grace period.

MethodPathDescriptionRole
GET/v1/environments/{env_id}/api-keysList keys (metadata only)Owner / Admin
POST/v1/environments/{env_id}/api-keysCreate keyOwner / Admin
POST/v1/environments/{env_id}/api-keys/{key_id}/rotateRotate keyOwner / Admin
DELETE/v1/environments/{env_id}/api-keys/{key_id}Revoke key immediatelyOwner / Admin

Create key — request:

curl -X POST https://api.hatidata.com/v1/environments/env_prod_x1y2/api-keys \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"name": "langchain-agent",
"scopes": ["query:read", "query:write", "schema:read", "agent:*"],
"ip_allowlist": ["10.0.1.0/24"],
"expires_in_days": 90
}'

Response 201 Created:

{
"key_id": "key_g7h8i9",
"name": "langchain-agent",
"key": "hd_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"scopes": ["query:read", "query:write", "schema:read", "agent:*"],
"expires_at": "2026-05-17T10:00:00Z",
"created_at": "2026-02-16T10:00:00Z"
}

The key field is returned only once. Key values cannot be retrieved after creation — rotate to replace a lost key.

Common scopes: query:read, query:write, schema:read, schema:write, policy:read, policy:write, audit:read, billing:read, agent:*. Use * suffix to grant all sub-scopes.

Rotate key — response:

{
"key_id": "key_a1b2c3",
"new_key": "hd_live_n3w5ecr3t...",
"old_key_expires_at": "2026-02-18T10:00:00Z",
"grace_period_hours": 48
}

Both old and new keys remain valid during the grace period (default 72 hours, max 168).


Policies

Two policy systems are available: standard policies (column masking and row-level security) and ABAC policies (attribute-based access control).

Standard Policies

MethodPathDescriptionRole
GET/v1/environments/{env_id}/policiesList policiesMember
POST/v1/environments/{env_id}/policiesCreate policyOwner / Admin
PUT/v1/environments/{env_id}/policies/{policy_id}Update policyOwner / Admin
DELETE/v1/environments/{env_id}/policies/{policy_id}Delete policyOwner / Admin

Create column masking policy — request:

curl -X POST https://api.hatidata.com/v1/environments/env_prod_x1y2/policies \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"name": "pii-masking",
"type": "column_masking",
"rules": [
{ "table": "customers", "column": "email", "function": "full", "exempt_roles": ["owner"] },
{ "table": "customers", "column": "ssn", "function": "hash", "exempt_roles": [] }
],
"enabled": true
}'

Masking functions: full (replace with ***), partial (show last N chars), hash (cryptographic hash hex), null (return NULL).

ABAC Policies

Deprecated

ABAC policy management endpoints are deprecated and will be removed in a future release. Use Organization Settings to configure access policies at the org level.

MethodPathDescriptionRole
GET/v1/environments/{env_id}/abac-policiesList ABAC policiesMember
POST/v1/environments/{env_id}/abac-policiesCreate ABAC policyOwner / Admin
POST/v1/environments/{env_id}/abac-policies/simulateSimulate policy evaluationOwner / Admin

Create ABAC policy — request:

curl -X POST https://api.hatidata.com/v1/environments/env_prod_x1y2/abac-policies \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"name": "weekend-read-only",
"rules": [
{
"condition": "DayOfWeek",
"values": ["Saturday", "Sunday"],
"action": "read_only"
}
],
"priority": 20,
"enabled": true
}'

Simulate — response:

{
"decision": "deny",
"reason": "Write operations are not permitted on weekends",
"matching_policies": [{ "policy_id": "abac_m3n4o5", "name": "weekend-read-only" }],
"evaluation_time_ms": 0.2
}

Audit

Two immutable audit trails: query audit (every SQL execution) and IAM audit (every administrative action, cryptographic hash-chained).

MethodPathDescriptionRole
GET/v1/environments/{env_id}/audit/queriesList query audit entriesOwner / Admin / Auditor
GET/v1/environments/{env_id}/audit/queries/{query_id}Get single query detailOwner / Admin / Auditor
GET/v1/environments/{env_id}/audit/adminList IAM audit eventsOwner / Admin / Auditor
GET/v1/environments/{env_id}/audit/admin/verify-chainVerify hash chain integrityOwner / Admin / Auditor
POST/v1/environments/{env_id}/audit/exportExport logs to object storageOwner / Admin

List query audit — request:

curl "https://api.hatidata.com/v1/environments/env_prod_x1y2/audit/queries?limit=20&agent_id=data-analyst-v2" \
-H "Authorization: Bearer <jwt>"

Response 200 OK:

{
"data": [
{
"query_id": "qry_a1b2c3d4",
"sql": "SELECT name, email FROM customers WHERE region = '[REDACTED]'",
"tables_accessed": ["customers"],
"rows_returned": 42,
"columns_masked": ["email"],
"execution_time_ms": 12,
"credits_consumed": 1,
"agent_metadata": { "agent_id": "data-analyst-v2", "framework": "langchain" },
"timestamp": "2026-02-16T10:30:00Z"
}
],
"pagination": { "cursor": "cur_abc123", "has_more": true, "total": 1250 }
}

Query parameters: start_date, end_date, user_id, agent_id, table, min_duration_ms, limit, cursor.

Export audit — request:

curl -X POST https://api.hatidata.com/v1/environments/env_prod_x1y2/audit/export \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"type": "query",
"start_date": "2026-02-01T00:00:00Z",
"end_date": "2026-02-15T23:59:59Z",
"format": "jsonl"
}'

Response: 202 Accepted with an export_id and the destination object storage path.


Billing

Credit-based billing. Queries consume credits based on complexity (tables scanned, rows returned, query type).

MethodPathDescriptionRole
GET/v1/organizations/{org_id}/billing/usageUsage for current billing periodOwner
GET/v1/organizations/{org_id}/billing/quotasCurrent quota limitsOwner
PUT/v1/organizations/{org_id}/billing/quotasUpdate alert thresholdsOwner

Get usage — response:

{
"org_id": "org_a1b2c3d4",
"tier": "cloud",
"billing_period": { "start": "2026-02-01T00:00:00Z", "end": "2026-02-28T23:59:59Z" },
"credits": {
"limit": 10000,
"used": 3250,
"remaining": 6750,
"usage_percent": 32.5
},
"breakdown": {
"queries": { "total": 45200, "select": 42100, "insert": 2800 },
"by_environment": [
{ "env_id": "env_prod_x1y2", "name": "production", "credits_used": 2800 }
]
}
}

Tier quotas:

QuotaFreeCloudGrowthEnterprise
Monthly credits1,00010,000100,000Custom
Concurrent queries10100500Custom
Max rows/query100,0001,000,00010,000,000Unlimited
Storage (GB)105005,000Custom
Environments1520Unlimited
Users325100Unlimited

Billing alerts are delivered via webhooks. Configure billing.warning and billing.critical event subscriptions to receive notifications.


Environments

Deprecated

Environment creation and management endpoints are deprecated. Environment configuration has moved to Organization Settings. Existing environments continue to function normally.

Environments provide isolated workspaces within an organization. Each has independent policies, API keys, and connection credentials.

MethodPathDescriptionRole
GET/v1/organizations/{org_id}/environmentsList environmentsMember
POST/v1/organizations/{org_id}/environmentsCreate environmentOwner / Admin
GET/v1/organizations/{org_id}/environments/{env_id}Get environmentMember
PUT/v1/organizations/{org_id}/environments/{env_id}Update settingsOwner / Admin
POST/v1/organizations/{org_id}/environments/{env_id}/promotePromote to next stageOwner / Admin
GET/v1/organizations/{org_id}/environments/{env_id}/connection-infoGet connection strings for psql, dbt, CLI, SDKMember

Create environment — request:

curl -X POST https://api.hatidata.com/v1/organizations/org_a1b2c3d4/environments \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"name": "staging",
"slug": "staging",
"settings": { "query_timeout_ms": 30000, "cache_enabled": true }
}'

Response 201 Created:

{
"env_id": "env_stg_a3b4",
"name": "staging",
"org_id": "org_a1b2c3d4",
"status": "active",
"connection": {
"host": "acme-corp-staging.proxy.hatidata.com",
"port": 5439,
"database": "hatidata"
},
"created_at": "2026-02-16T10:00:00Z"
}

Webhooks

Deprecated

Webhook management endpoints are deprecated. Use Semantic Triggers for event-driven notifications, or configure webhooks via Organization Settings.

Webhooks deliver real-time event notifications. Every payload is signed with HMAC-SHA256.

MethodPathDescriptionRole
GET/v1/organizations/{org_id}/webhooksList webhooksOwner / Admin
POST/v1/organizations/{org_id}/webhooksCreate webhookOwner / Admin
PUT/v1/organizations/{org_id}/webhooks/{webhook_id}Update events or URLOwner / Admin
DELETE/v1/organizations/{org_id}/webhooks/{webhook_id}Delete webhookOwner / Admin
POST/v1/organizations/{org_id}/webhooks/{webhook_id}/testSend test eventOwner / Admin

Create webhook — request:

curl -X POST https://api.hatidata.com/v1/organizations/org_a1b2c3d4/webhooks \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"url": "https://hooks.acme.com/hatidata",
"events": ["key.rotated", "billing.warning", "policy.changed"]
}'

Response 201 Created:

{
"webhook_id": "wh_d4e5f6",
"url": "https://hooks.acme.com/hatidata",
"events": ["key.rotated", "billing.warning", "policy.changed"],
"signing_secret": "whsec_a1b2c3d4...",
"status": "active"
}

The signing_secret is shown only once. Store it to verify incoming payloads.

Payload envelope:

{
"event_id": "evt_m3n4o5p6",
"event_type": "key.rotated",
"org_id": "org_a1b2c3d4",
"timestamp": "2026-02-16T10:00:00Z",
"data": { "key_id": "key_a1b2c3", "name": "analytics-dashboard" }
}

Signature verification (Python):

import hmac, hashlib

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)

Available event types: key.created/rotated/expiring/revoked, user.invited/removed/role_changed, policy.created/updated/deleted, billing.warning/critical/quota_exceeded, jit.requested/approved/denied, environment.created/promoted, auth.failed.

Failed deliveries are retried with exponential backoff (1 min → 5 min → 30 min → 2 hr → 12 hr) before the webhook is marked failed.


Provisioning

Three provisioning capabilities: JIT (Just-In-Time) temporary access, agent capability grants, and shadow mode for risk-free migration testing.

JIT Access

Deprecated

JIT Access endpoints are deprecated. Use the Agent Registry to manage agent trust levels and access promotion.

MethodPathDescriptionRole
GET/v1/environments/{env_id}/jit-accessList requestsOwner / Admin / Auditor
POST/v1/environments/{env_id}/jit-accessRequest JIT escalationAny authenticated user
POST/v1/environments/{env_id}/jit-access/{request_id}/approveApprove requestOwner / Admin
POST/v1/environments/{env_id}/jit-access/{request_id}/denyDeny requestOwner / Admin
POST/v1/environments/{env_id}/jit-access/{request_id}/revokeRevoke active grantOwner / Admin

Request JIT access:

curl -X POST https://api.hatidata.com/v1/environments/env_prod_x1y2/jit-access \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"requested_role": "admin",
"reason": "Update column masking policy for PCI audit",
"duration_minutes": 60
}'

Agent Capabilities

Fine-grained permissions for AI agents beyond API key scopes:

MethodPathDescriptionRole
POST/v1/environments/{env_id}/agent-capabilitiesGrant capabilityOwner / Admin
GET/v1/environments/{env_id}/agent-capabilitiesList grantsOwner / Admin
DELETE/v1/environments/{env_id}/agent-capabilities/{grant_id}Revoke grantOwner / Admin

Grant capability — request:

curl -X POST https://api.hatidata.com/v1/environments/env_prod_x1y2/agent-capabilities \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "data-analyst-v2",
"capabilities": {
"allowed_tables": ["public.customers", "public.orders"],
"allowed_operations": ["SELECT"],
"max_queries_per_hour": 500,
"max_rows_per_query": 10000
},
"expires_at": "2026-03-16T00:00:00Z"
}'

Shadow Mode

Replay production queries against HatiData to validate compatibility before cutting over.

MethodPathDescription
POST/v1/environments/{env_id}/shadow-mode/startStart session
GET/v1/environments/{env_id}/shadow-mode/statusGet live statistics
POST/v1/environments/{env_id}/shadow-mode/uploadUpload query log (JSONL)
POST/v1/environments/{env_id}/shadow-mode/replayReplay uploaded log
GET/v1/environments/{env_id}/shadow-mode/reportGet comparison report
POST/v1/environments/{env_id}/shadow-mode/stopStop session

Status response:

{
"statistics": {
"queries_replayed": 4200,
"match_rate": 0.988,
"avg_latency_source_ms": 450,
"avg_latency_hatidata_ms": 12
}
}

Authentication

Endpoints for user authentication, session management, and SSO. All login endpoints are unauthenticated; session management requires a valid JWT or API key.

MethodPathDescriptionAuth
POST/v1/auth/loginEmail/password login, returns JWTNone
POST/v1/auth/token/refreshRefresh expired JWTNone
POST/v1/auth/magic-linkSend magic link emailNone
GET/v1/auth/magic-link/callbackMagic link callbackNone
POST/v1/auth/verify-emailVerify email with tokenNone
POST/v1/auth/verify-email/resendResend verification emailNone
POST/v1/auth/forgot-passwordInitiate password resetNone
POST/v1/auth/reset-passwordComplete password resetNone
GET/v1/auth/meGet current user profileJWT / API Key
POST/v1/auth/logoutLogout (invalidate session)JWT / API Key
POST/v1/auth/sso/initiateInitiate SSO flow (Clerk)None
GET/v1/auth/sso/callbackSSO callback handlerNone
POST/v1/auth/exchange-tokenExchange external token for JWTNone

Login — request:

curl -X POST https://api.hatidata.com/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "alice@acme.com",
"password": "s3cur3P@ssword"
}'

Response 200 OK:

{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"refresh_token": "rt_a1b2c3d4e5f6...",
"expires_in": 3600,
"token_type": "Bearer",
"user": {
"user_id": "usr_a1b2c3",
"email": "alice@acme.com",
"org_id": "org_a1b2c3d4",
"role": "admin"
}
}

Signup

Create a new account and organization. For paid tiers, the response includes a Stripe checkout URL for payment.

MethodPathDescriptionAuth
POST/v1/signupCreate account + org; optionally redirect to Stripe checkoutNone

Signup — request:

curl -X POST https://api.hatidata.com/v1/signup \
-H "Content-Type: application/json" \
-d '{
"email": "alice@acme.com",
"password": "s3cur3P@ssword",
"org_name": "Acme Corp",
"tier": "cloud"
}'

Response 201 Created:

{
"user_id": "usr_a1b2c3",
"org_id": "org_a1b2c3d4",
"tier": "cloud",
"status": "pending_payment",
"checkout_url": "https://checkout.stripe.com/c/pay/cs_live_..."
}

For free tier signups, status is active and no checkout_url is returned.


Agent Registry

The agent registry tracks all AI agents that connect to HatiData. Agents are auto-registered on first connection via the proxy and can be managed through these endpoints.

MethodPathDescriptionRole
GET/v1/agentsList registered agentsMember
GET/v1/agents/{agent_id}Get agent detailMember
PATCH/v1/agents/{agent_id}Update agent metadataOwner / Admin
POST/v1/agents/{agent_id}/promotePromote trust levelOwner / Admin
POST/v1/agents/{agent_id}/suspendSuspend agentOwner / Admin
POST/v1/agents/{agent_id}/revokeRevoke agent permanentlyOwner / Admin
POST/v1/agents/{agent_id}/keysGenerate agent-scoped API keyOwner / Admin
POST/v1/internal/agent-connectAuto-register on connect (proxy internal)Internal

List agents — request:

curl https://api.hatidata.com/v1/agents \
-H "Authorization: ApiKey hd_live_..."

Response 200 OK:

{
"data": [
{
"agent_id": "data-analyst-v2",
"framework": "langchain",
"trust_level": "standard",
"status": "active",
"fingerprint": "fp_a1b2c3d4",
"last_seen_at": "2026-03-07T10:30:00Z",
"registered_at": "2026-02-16T10:00:00Z"
}
],
"pagination": { "cursor": null, "has_more": false, "total": 1 }
}

Promote trust level — request:

curl -X POST https://api.hatidata.com/v1/agents/data-analyst-v2/promote \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{ "trust_level": "elevated", "reason": "Verified production agent" }'

Trust levels: untrusted, standard, elevated, admin. Newly auto-registered agents start at standard. The agent_registration_policy in Organization Settings controls whether auto-registration is open, approval-required, or disabled.

Generate agent-scoped key — request:

curl -X POST https://api.hatidata.com/v1/agents/data-analyst-v2/keys \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"scopes": ["query:read", "schema:read", "agent:*"],
"expires_in_days": 90
}'

Response 201 Created:

{
"key_id": "agk_x1y2z3",
"key": "hd_agent_a1b2c3d4e5f6...",
"agent_id": "data-analyst-v2",
"scopes": ["query:read", "schema:read", "agent:*"],
"expires_at": "2026-06-07T10:00:00Z"
}

Agent Keys

Agent keys are identity-scoped API keys tied to a specific AI agent. They carry metadata about the agent's framework and restrict access to specific tables.

MethodPathDescriptionRole
POST/v1/organizations/{org_id}/agent-keysCreate agent-specific API keyOwner / Admin
GET/v1/organizations/{org_id}/agent-keysList agent keysOwner / Admin
GET/v1/organizations/{org_id}/agent-keys/{key_id}Get agent key detailsOwner / Admin
PUT/v1/organizations/{org_id}/agent-keys/{key_id}Update agent keyOwner / Admin
POST/v1/organizations/{org_id}/agent-keys/{key_id}/rotateRotate agent keyOwner / Admin
DELETE/v1/organizations/{org_id}/agent-keys/{key_id}Revoke agent keyOwner / Admin

Create agent key — request:

curl -X POST https://api.hatidata.com/v1/organizations/org_a1b2c3d4/agent-keys \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"agent_name": "data-analyst-v2",
"framework": "langchain",
"allowed_tables": ["public.customers", "public.orders"],
"scopes": ["query:read", "schema:read"],
"expires_in_days": 90
}'

Response 201 Created:

{
"key_id": "agk_a1b2c3d4",
"agent_name": "data-analyst-v2",
"key": "hd_agent_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"framework": "langchain",
"allowed_tables": ["public.customers", "public.orders"],
"scopes": ["query:read", "schema:read"],
"expires_at": "2026-06-07T10:00:00Z",
"created_at": "2026-03-07T10:00:00Z"
}

The key field is returned only once. Agent keys use the hd_agent_ prefix to distinguish them from environment API keys.


Agent Memory

Long-term agent memory with hybrid search (SQL + vector). Memories are stored per-organization and searchable by content, agent, or metadata.

MethodPathDescriptionRole
GET/v1/organizations/{org_id}/agent-memoryList agent memoriesMember
POST/v1/organizations/{org_id}/agent-memoryStore new memoryMember
GET/v1/organizations/{org_id}/agent-memory/searchHybrid search (vector + text)Member
DELETE/v1/organizations/{org_id}/agent-memory/{memory_id}Delete memoryMember

Search memory — request:

curl "https://api.hatidata.com/v1/organizations/org_a1b2c3d4/agent-memory/search?q=customer+churn+analysis&agent_id=data-analyst-v2&limit=5" \
-H "Authorization: Bearer <jwt>"

Response 200 OK:

{
"data": [
{
"memory_id": "mem_x1y2z3",
"agent_id": "data-analyst-v2",
"content": "Customer churn correlates with support ticket count > 5 in last 30 days",
"relevance_score": 0.92,
"created_at": "2026-03-01T14:30:00Z"
}
],
"pagination": { "cursor": null, "has_more": false, "total": 1 }
}

Branches

Schema-based branch isolation for agents. Branches provide zero-copy-on-create workspaces that are merged back to main after validation.

MethodPathDescriptionRole
GET/v1/organizations/{org_id}/branchesList branchesMember
POST/v1/organizations/{org_id}/branchesCreate branchMember
GET/v1/organizations/{org_id}/branches/{branch_id}Get branch detailsMember
DELETE/v1/organizations/{org_id}/branches/{branch_id}Discard branchMember
POST/v1/organizations/{org_id}/branches/{branch_id}/mergeMerge to mainMember
GET/v1/organizations/{org_id}/branches/{branch_id}/diffGet diff from mainMember
GET/v1/organizations/{org_id}/branches/{branch_id}/conflictsGet merge conflictsMember

Create branch — request:

curl -X POST https://api.hatidata.com/v1/organizations/org_a1b2c3d4/branches \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"name": "experiment-churn-model",
"agent_id": "data-analyst-v2",
"ttl_hours": 24
}'

Response 201 Created:

{
"branch_id": "br_a1b2c3d4",
"name": "experiment-churn-model",
"agent_id": "data-analyst-v2",
"status": "active",
"schema": "branch_a1b2c3d4",
"expires_at": "2026-03-08T10:00:00Z",
"created_at": "2026-03-07T10:00:00Z"
}

Semantic Triggers

Event-driven rules that fire when query content or agent behavior matches a semantic concept. Triggers use two-stage evaluation: ANN pre-filter followed by exact cosine verification.

MethodPathDescriptionRole
GET/v1/organizations/{org_id}/triggersList triggersMember
POST/v1/organizations/{org_id}/triggersCreate triggerMember
PUT/v1/organizations/{org_id}/triggers/{trigger_id}Update triggerMember
DELETE/v1/organizations/{org_id}/triggers/{trigger_id}Delete triggerMember
POST/v1/organizations/{org_id}/triggers/{trigger_id}/testTest trigger (dry-run)Member

Create trigger — request:

curl -X POST https://api.hatidata.com/v1/organizations/org_a1b2c3d4/triggers \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"name": "pii-access-alert",
"concept": "accessing personally identifiable information",
"threshold": 0.85,
"action": "webhook",
"action_config": { "url": "https://hooks.acme.com/pii-alert" },
"cooldown_seconds": 300
}'

Response 201 Created:

{
"trigger_id": "trg_a1b2c3d4",
"name": "pii-access-alert",
"concept": "accessing personally identifiable information",
"threshold": 0.85,
"action": "webhook",
"cooldown_seconds": 300,
"status": "active",
"created_at": "2026-03-07T10:00:00Z"
}

Chain-of-Thought

Immutable, hash-chained reasoning traces for AI agent decision audit. Each step is SHA-256 linked to the previous step in its session, forming a tamper-evident ledger.

MethodPathDescriptionRole
GET/v1/cot/sessionsList CoT sessionsMember
POST/v1/cot/ingestIngest reasoning tracesMember
GET/v1/cot/sessions/{session_id}/replayReplay full sessionMember
GET/v1/cot/sessions/{session_id}/verifyVerify hash chainMember
POST/v1/cot/approvalsRecord human approval/rejectionAdmin

Ingest reasoning trace — request:

curl -X POST https://api.hatidata.com/v1/cot/ingest \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"session_id": "ses_a1b2c3d4",
"agent_id": "data-analyst-v2",
"steps": [
{
"step_type": "reasoning",
"content": "User asked for churn analysis. I need to query customer and support_tickets tables.",
"timestamp": "2026-03-07T10:00:00Z"
},
{
"step_type": "tool_call",
"content": "SELECT c.name, COUNT(t.id) FROM customers c JOIN support_tickets t ON c.id = t.customer_id GROUP BY c.name",
"timestamp": "2026-03-07T10:00:01Z"
}
]
}'

Response 201 Created:

{
"ingested": 2,
"session_id": "ses_a1b2c3d4",
"chain_valid": true,
"latest_hash": "sha256:a1b2c3d4e5f6..."
}

Sessions

Manage active user and agent sessions. Sessions are created on login and can be individually or bulk revoked.

MethodPathDescriptionRole
GET/v1/sessionsList active sessionsMember
DELETE/v1/sessions/{session_id}Revoke sessionMember
DELETE/v1/sessionsRevoke all sessionsMember

List sessions — response:

{
"data": [
{
"session_id": "ses_a1b2c3",
"user_id": "usr_a1b2c3",
"ip_address": "10.0.1.42",
"user_agent": "Mozilla/5.0...",
"created_at": "2026-03-07T08:00:00Z",
"last_active_at": "2026-03-07T09:45:00Z"
}
]
}

Federation

Configure federated identity providers for cloud-native authentication. Supports AWS STS, GCP Workload Identity, and Azure Managed Identity.

MethodPathDescriptionRole
POST/v1/organizations/{org_id}/federationConfigure federation providerOwner / Admin
GET/v1/organizations/{org_id}/federationList providersOwner / Admin
DELETE/v1/organizations/{org_id}/federation/{provider}Remove providerOwner / Admin
POST/v1/organizations/{org_id}/federation/{provider}/testTest connectionOwner / Admin

Configure GCP Workload Identity — request:

curl -X POST https://api.hatidata.com/v1/organizations/org_a1b2c3d4/federation \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"provider": "gcp",
"config": {
"project_id": "acme-analytics",
"workload_identity_pool": "projects/123456/locations/global/workloadIdentityPools/hatidata",
"allowed_service_accounts": ["agent@acme-analytics.iam.gserviceaccount.com"]
}
}'

Response 201 Created:

{
"provider": "gcp",
"status": "active",
"config": {
"project_id": "acme-analytics",
"workload_identity_pool": "projects/123456/locations/global/workloadIdentityPools/hatidata"
},
"created_at": "2026-03-07T10:00:00Z"
}

Tenants (Multi-Tenancy)

Hierarchical multi-tenancy for SaaS platforms. Parent organizations can create child tenants with isolated data and policies.

MethodPathDescriptionRole
POST/v1/organizations/{org_id}/tenantsCreate child tenantOwner / Admin
GET/v1/organizations/{org_id}/tenantsList child tenantsOwner / Admin
PUT/v1/organizations/{org_id}/tenants/configConfigure isolationOwner / Admin

Create tenant — request:

curl -X POST https://api.hatidata.com/v1/organizations/org_a1b2c3d4/tenants \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"name": "Tenant Alpha",
"slug": "tenant-alpha",
"isolation": "schema"
}'

Response 201 Created:

{
"tenant_id": "tnt_a1b2c3d4",
"name": "Tenant Alpha",
"slug": "tenant-alpha",
"isolation": "schema",
"parent_org_id": "org_a1b2c3d4",
"status": "active",
"created_at": "2026-03-07T10:00:00Z"
}

Cost Intelligence

Query cost analysis and optimization recommendations. Tracks credit consumption at the query, environment, and organization level.

MethodPathDescriptionRole
GET/v1/organizations/{org_id}/cost/summaryCost summaryOwner / Admin
GET/v1/organizations/{org_id}/cost/dailyDaily breakdownOwner / Admin
GET/v1/organizations/{org_id}/cost/top-queriesTop expensive queriesOwner / Admin
GET/v1/organizations/{org_id}/cost/optimizationsOptimization recommendationsOwner / Admin

Cost summary — response:

{
"org_id": "org_a1b2c3d4",
"period": { "start": "2026-03-01T00:00:00Z", "end": "2026-03-07T23:59:59Z" },
"total_credits": 1250,
"estimated_monthly": 5360,
"top_cost_drivers": [
{ "category": "full_table_scans", "credits": 420, "query_count": 15 },
{ "category": "large_result_sets", "credits": 310, "query_count": 8 }
]
}

Performance Analytics

Query performance metrics including latency timelines, cache hit rates, slow query analysis, and per-stage pipeline latency.

MethodPathDescriptionRole
GET/v1/environments/{env_id}/performance/latency-timelineLatency over timeMember
GET/v1/environments/{env_id}/performance/cache-metricsL1/L2/L3 cache statsMember
GET/v1/environments/{env_id}/performance/slow-queriesTop slow queriesMember
GET/v1/environments/{env_id}/performance/pipeline-stagesPipeline stage latencyMember

Cache metrics — response:

{
"env_id": "env_prod_x1y2",
"period": "last_24h",
"memory_cache": { "hit_rate": 0.42, "entries": 1250, "size_mb": 128 },
"disk_cache": { "hit_rate": 0.78, "entries": 340, "size_mb": 2048 },
"object_cache": { "hit_rate": 0.95, "entries": 45, "size_mb": 512 },
"overall_hit_rate": 0.72
}

Settings

Organization-level configuration including general settings, agent registration policy, GDPR data export, and account deletion.

MethodPathDescriptionRole
GET/v1/organizations/{org_id}/settingsGet org settingsOwner / Admin
PATCH/v1/organizations/{org_id}/settingsUpdate settingsOwner / Admin
POST/v1/organizations/{org_id}/settings/export-dataGDPR data exportOwner
POST/v1/organizations/{org_id}/settings/deleteDelete organizationOwner

Update settings — request:

curl -X PATCH https://api.hatidata.com/v1/organizations/org_a1b2c3d4/settings \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"default_query_timeout_ms": 30000,
"audit_retention_days": 365,
"require_mfa": true,
"allowed_ip_ranges": ["10.0.0.0/8", "172.16.0.0/12"],
"agent_registration_policy": "open"
}'

Response 200 OK:

{
"org_id": "org_a1b2c3d4",
"settings": {
"default_query_timeout_ms": 30000,
"audit_retention_days": 365,
"require_mfa": true,
"allowed_ip_ranges": ["10.0.0.0/8", "172.16.0.0/12"],
"agent_registration_policy": "open"
},
"updated_at": "2026-03-07T10:00:00Z"
}

The agent_registration_policy field controls how new agents are handled when they first connect:

ValueBehavior
openAgents auto-register on first connect (default)
approval_requiredAgents are queued for admin approval before they can execute queries
disabledOnly pre-registered agents (created via the Agent Registry API) can connect

---

## AI Providers (BYOL)

Bring Your Own LLM (BYOL) configuration. Organizations can configure their own embedding models and LLMs for agent memory, semantic triggers, and AI healing.

| Method | Path | Description | Role |
|--------|------|-------------|------|
| `GET` | `/v1/organizations/{org_id}/ai-providers` | Get configured providers | Owner / Admin |
| `PUT` | `/v1/organizations/{org_id}/ai-providers/embedding` | Configure embedding model | Owner / Admin |
| `PUT` | `/v1/organizations/{org_id}/ai-providers/llm` | Configure LLM | Owner / Admin |
| `POST` | `/v1/organizations/{org_id}/ai-providers/test` | Test provider connection | Owner / Admin |

**Configure embedding provider — request:**

```bash
curl -X PUT https://api.hatidata.com/v1/organizations/org_a1b2c3d4/ai-providers/embedding \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"provider": "openai",
"model": "text-embedding-3-small",
"api_key": "sk-...",
"dimensions": 1536
}'

Response 200 OK:

{
"provider": "openai",
"model": "text-embedding-3-small",
"dimensions": 1536,
"status": "verified",
"updated_at": "2026-03-07T10:00:00Z"
}

Internal Endpoints

These endpoints are used by the proxy for communication with the control plane. They are not intended for external use but are documented here for self-hosted operators.

MethodPathDescriptionAuth
POST/v1/internal/meteringIngest query metering recordsInternal
POST/v1/internal/agent-activityIngest agent activity telemetryInternal
POST/v1/internal/agent-connectAuto-register agent on first connectionInternal
GET/v1/internal/syncFetch policy/quota sync bundleInternal
POST/v1/internal/validate-keyValidate API key hashInternal

Internal endpoints authenticate via a shared secret (X-Internal-Token header) configured between the proxy and control plane. They are not exposed through the public API gateway.

Sync bundle — response:

{
"policies": [ { "policy_id": "pol_a1b2c3", "type": "column_masking", "rules": [...] } ],
"quotas": { "monthly_credit_limit": 10000, "used": 3250 },
"abac_policies": [...],
"agent_capabilities": [...],
"last_updated_at": "2026-03-07T10:00:00Z"
}

Stay in the loop

Product updates, engineering deep-dives, and agent-native insights. No spam.