Skip to main content

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

ParameterValue
Hostyour-org.proxy.hatidata.com (cloud) or localhost (local)
Port5439
Databasehatidata
UsernameYour user ID or API key prefix
PasswordYour API key (hd_live_... or hd_test_...)
SSLRequired 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": []
}
FieldTypeRequiredDescription
sqlstringYesSQL query to execute
agent_idstringNoAgent identifier (for agent-specific policies)
agent_frameworkstringNoAgent framework name
timeout_msintegerNoQuery timeout (default: 30000, max: 300000)
formatstringNoResult format: json (default), csv, arrow
Snowflake SQL

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:

  1. Semaphore -- Concurrency control (configurable, default 100)
  2. Table extraction -- Walk AST to find referenced tables
  3. Policy evaluation -- ABAC context check against extracted tables
  4. Cost estimation -- Heuristic credit cost calculation
  5. Quota check -- Per-org credit limit enforcement
  6. Row filters -- RLS WHERE clause injection
  7. Transpilation -- Snowflake SQL to DuckDB SQL
  8. Snapshot pinning -- Iceberg snapshot isolation
  9. DuckDB execution -- Query execution with timeout
  10. AI healing -- On failure, attempt automatic SQL correction
  11. Column masking -- Post-execution redaction by role
  12. Metering -- Credit consumption and Prometheus metrics
  13. Audit -- PII-redacted immutable log entry

Error Responses

StatusCodeDescription
400QUERY_PARSE_ERRORSQL syntax error
401UNAUTHORIZEDMissing or invalid authentication
403POLICY_DENIEDQuery blocked by ABAC policy or agent capability
408QUERY_TIMEOUTQuery exceeded timeout
422TRANSPILATION_ERRORUnsupported SQL construct
429QUOTA_EXCEEDEDMonthly credit limit reached
500EXECUTION_ERRORDuckDB execution failure

Stay in the loop

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