Query Proxy
HatiData provides two ways to execute SQL queries: the Postgres wire protocol (port 5439) for standard database clients, and the REST API for programmatic execution. Both methods go through the same 13-step query pipeline with transpilation, policy enforcement, and auditing.
Postgres Wire Protocol
The primary way to connect to HatiData is via the Postgres wire protocol on port 5439. Any Postgres-compatible client (psql, pgAdmin, DBeaver, language drivers) works out of the box.
Connection Parameters
| Parameter | Value |
|---|---|
| Host | your-org.proxy.hatidata.com (cloud) or localhost (local) |
| Port | 5439 |
| Database | hatidata |
| Username | Your user ID or API key prefix |
| Password | Your API key (hd_live_... or hd_test_...) |
| SSL | Required in cloud mode (TLS 1.3) |
Connection Examples
# psql
psql "host=your-org.proxy.hatidata.com port=5439 dbname=hatidata user=admin password=hd_live_a1b2c3d4..."
# Local mode
psql -h localhost -p 5439 -U admin -d hatidata
# Python (psycopg2)
import psycopg2
conn = psycopg2.connect(
host="your-org.proxy.hatidata.com",
port=5439,
dbname="hatidata",
user="admin",
password="hd_live_a1b2c3d4...",
sslmode="require"
)
cursor = conn.cursor()
cursor.execute("SELECT * FROM customers LIMIT 10")
rows = cursor.fetchall()
// Node.js (pg)
import { Client } from 'pg';
const client = new Client({
host: 'your-org.proxy.hatidata.com',
port: 5439,
database: 'hatidata',
user: 'admin',
password: 'hd_live_a1b2c3d4...',
ssl: { rejectUnauthorized: true }
});
await client.connect();
const result = await client.query('SELECT * FROM customers LIMIT 10');
console.log(result.rows);
// Java (JDBC)
String url = "jdbc:postgresql://your-org.proxy.hatidata.com:5439/hatidata?ssl=true";
Connection conn = DriverManager.getConnection(url, "admin", "hd_live_a1b2c3d4...");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM customers LIMIT 10");
Agent Connection
When connecting as an AI agent, include agent metadata in the connection properties:
from hatidata_agent import HatiDataAgent
agent = HatiDataAgent(
host="your-org.proxy.hatidata.com",
port=5439,
api_key="hd_live_a1b2c3d4...",
agent_id="data-analyst-v2",
framework="langchain",
)
rows = agent.query("SELECT * FROM customers WHERE region = 'US'")
Agent metadata is used by the policy engine for agent-specific masking, RLS, and ABAC evaluation.
REST API Query Execution
Execute Query
POST /v1/environments/{env_id}/query
Execute a SQL query via the REST API. Returns 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 "X-API-Key: hd_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" \
-H "Content-Type: application/json" \
-d '{
"sql": "SELECT name, email, 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": "email", "type": "VARCHAR" },
{ "name": "region", "type": "VARCHAR" }
],
"rows": [
["Alice Chen", "***", "US"],
["Bob Smith", "***", "US"],
["Carol Davis", "***", "US"]
],
"row_count": 3,
"execution_time_ms": 8,
"transpilation_time_ms": 0.4,
"cache_hit": false,
"credits_consumed": 1,
"columns_masked": ["email"],
"warnings": []
}
| Field | Type | Required | Description |
|---|---|---|---|
sql | string | Yes | SQL query to execute |
agent_id | string | No | Agent identifier (for agent-specific policies) |
agent_framework | string | No | Agent framework name |
timeout_ms | integer | No | Query timeout (default: 30000, max: 300000) |
format | string | No | Result format: json (default), csv, arrow |
You can use Snowflake-compatible SQL syntax. HatiData automatically transpiles functions like NVL, IFF, DATEDIFF, DATEADD, types like VARIANT, TIMESTAMP_NTZ, and constructs like QUALIFY and FLATTEN to DuckDB equivalents.
Agent Analytics
Get Agent Activity
GET /v1/environments/{env_id}/agents/{agent_id}/activity
Returns activity metrics for a specific agent. Requires Owner, Admin, or Auditor role.
Request:
curl https://api.hatidata.com/v1/environments/env_prod_x1y2/agents/data-analyst-v2/activity \
-H "Authorization: Bearer <jwt>"
Response 200 OK:
{
"agent_id": "data-analyst-v2",
"framework": "langchain",
"activity": {
"total_queries": 12500,
"queries_today": 320,
"queries_this_hour": 42,
"avg_execution_time_ms": 15,
"tables_accessed": ["customers", "orders", "products"],
"credits_consumed_today": 320,
"last_query_at": "2026-02-16T10:30:00Z"
},
"policy_summary": {
"queries_allowed": 12450,
"queries_denied": 50,
"columns_masked": 2400,
"rows_filtered": 8200
}
}
List Active Agents
GET /v1/environments/{env_id}/agents
Lists all agents that have queried the environment. Requires Owner, Admin, or Auditor role.
Request:
curl https://api.hatidata.com/v1/environments/env_prod_x1y2/agents \
-H "Authorization: Bearer <jwt>"
Response 200 OK:
{
"data": [
{
"agent_id": "data-analyst-v2",
"framework": "langchain",
"status": "active",
"total_queries": 12500,
"last_active": "2026-02-16T10:30:00Z",
"capability_grants": 1
},
{
"agent_id": "report-generator",
"framework": "crewai",
"status": "active",
"total_queries": 3200,
"last_active": "2026-02-16T09:45:00Z",
"capability_grants": 0
}
],
"pagination": {
"cursor": null,
"has_more": false,
"total": 2
}
}
Federation
List Federation Providers
GET /v1/organizations/{org_id}/federation/providers
Lists configured federation providers. Requires Owner or Admin role.
Request:
curl https://api.hatidata.com/v1/organizations/org_a1b2c3d4/federation/providers \
-H "Authorization: Bearer <jwt>"
Response 200 OK:
{
"data": [
{
"provider_id": "fed_aws_x1y2",
"type": "aws_sts",
"config": {
"role_arn": "arn:aws:iam::123456789012:role/HatiDataAgent",
"external_id": "hatidata-org_a1b2c3d4"
},
"status": "active",
"created_at": "2026-01-20T10:00:00Z"
}
]
}
Configure Federation Provider
POST /v1/organizations/{org_id}/federation/providers
Adds a new federation provider. Requires Owner or Admin role.
Request:
curl -X POST https://api.hatidata.com/v1/organizations/org_a1b2c3d4/federation/providers \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"type": "gcp_workload_identity",
"config": {
"project_id": "my-project-123",
"workload_identity_pool": "hatidata-pool",
"provider": "hatidata-provider"
}
}'
Response 201 Created:
{
"provider_id": "fed_gcp_a3b4",
"type": "gcp_workload_identity",
"config": {
"project_id": "my-project-123",
"workload_identity_pool": "hatidata-pool",
"provider": "hatidata-provider"
},
"status": "active",
"created_at": "2026-02-16T10:00:00Z"
}
Tenants
List Tenants
GET /v1/organizations/{org_id}/tenants
Lists tenants in a multi-tenant organization. Requires Owner or Admin role.
Request:
curl https://api.hatidata.com/v1/organizations/org_a1b2c3d4/tenants \
-H "Authorization: Bearer <jwt>"
Response 200 OK:
{
"data": [
{
"tenant_id": "tnt_us_east",
"name": "Acme US East",
"parent_org_id": "org_a1b2c3d4",
"status": "active",
"user_count": 12,
"query_count_today": 450,
"created_at": "2026-01-15T10:00:00Z"
},
{
"tenant_id": "tnt_eu_west",
"name": "Acme EU West",
"parent_org_id": "org_a1b2c3d4",
"status": "active",
"user_count": 8,
"query_count_today": 220,
"created_at": "2026-01-15T10:00:00Z"
}
]
}
Public Health Endpoints
These endpoints do not require authentication.
Health Check
GET /health
curl https://api.hatidata.com/health
{
"status": "healthy",
"version": "1.0.0",
"uptime_seconds": 86400
}
Readiness Check
GET /ready
Returns 200 when the proxy is ready to accept queries, 503 during startup or shutdown.
curl https://api.hatidata.com/ready
{
"ready": true,
"duckdb": "connected",
"control_plane": "connected"
}
Query Pipeline
Every query (wire protocol or REST) passes through the same 13-step pipeline:
- Semaphore -- Concurrency control (configurable, default 100)
- Table extraction -- Walk AST to find referenced tables
- Policy evaluation -- ABAC context check against extracted tables
- Cost estimation -- Heuristic credit cost calculation
- Quota check -- Per-org credit limit enforcement
- Row filters -- RLS WHERE clause injection
- Transpilation -- Snowflake SQL to DuckDB SQL
- Snapshot pinning -- Iceberg snapshot isolation
- DuckDB execution -- Query execution with timeout
- AI healing -- On failure, attempt automatic SQL correction
- Column masking -- Post-execution redaction by role
- Metering -- Credit consumption and Prometheus metrics
- Audit -- PII-redacted immutable log entry
Error Responses
| Status | Code | Description |
|---|---|---|
400 | QUERY_PARSE_ERROR | SQL syntax error |
401 | UNAUTHORIZED | Missing or invalid authentication |
403 | POLICY_DENIED | Query blocked by ABAC policy or agent capability |
408 | QUERY_TIMEOUT | Query exceeded timeout |
422 | TRANSPILATION_ERROR | Unsupported SQL construct |
429 | QUOTA_EXCEEDED | Monthly credit limit reached |
500 | EXECUTION_ERROR | DuckDB execution failure |