Skip to main content

Audit

HatiData maintains two separate audit trails: Query Audit for all SQL queries executed through the proxy, and IAM Audit for all administrative actions. Both are immutable and tamper-evident.

Query Audit

List Query Audit Entries

GET /v1/environments/{env_id}/audit/queries

Returns paginated query audit entries. Requires Owner, Admin, or Auditor role.

Request:

curl "https://api.hatidata.com/v1/environments/env_prod_x1y2/audit/queries?limit=20&start_date=2026-02-15" \
-H "Authorization: Bearer <jwt>"

Response 200 OK:

{
"data": [
{
"query_id": "qry_a1b2c3d4",
"user_id": "usr_x1y2z3",
"source_ip": "10.0.1.50",
"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,
"cache_hit": false,
"policy_verdicts": [
{
"policy_id": "pol_a1b2c3",
"policy_name": "pii-masking",
"action": "mask",
"columns": ["email"]
}
],
"agent_metadata": {
"agent_id": "data-analyst-v2",
"framework": "langchain"
},
"timestamp": "2026-02-16T10:30:00Z"
},
{
"query_id": "qry_e5f6g7h8",
"user_id": "usr_a4b5c6",
"source_ip": "10.0.1.51",
"sql": "SELECT COUNT(*) FROM orders WHERE status = 'completed'",
"tables_accessed": ["orders"],
"rows_returned": 1,
"columns_masked": [],
"execution_time_ms": 3,
"credits_consumed": 1,
"cache_hit": true,
"policy_verdicts": [],
"agent_metadata": null,
"timestamp": "2026-02-16T10:29:00Z"
}
],
"pagination": {
"cursor": "cur_abc123",
"has_more": true,
"total": 1250
}
}

Query Parameters

ParameterTypeDefaultDescription
start_datestring (ISO 8601)24 hours agoStart of date range
end_datestring (ISO 8601)NowEnd of date range
user_idstring--Filter by user
agent_idstring--Filter by agent
tablestring--Filter by table accessed
cache_hitboolean--Filter by cache status
min_duration_msinteger--Filter slow queries
limitinteger50Results per page (max 200)
cursorstring--Pagination cursor

Get Query Details

GET /v1/environments/{env_id}/audit/queries/{query_id}

Returns full details for a single query, including the complete execution plan and any error information.

Request:

curl https://api.hatidata.com/v1/environments/env_prod_x1y2/audit/queries/qry_a1b2c3d4 \
-H "Authorization: Bearer <jwt>"

Response 200 OK:

{
"query_id": "qry_a1b2c3d4",
"user_id": "usr_x1y2z3",
"source_ip": "10.0.1.50",
"sql_original": "SELECT name, email FROM customers WHERE region = '[EMAIL_REDACTED]'",
"sql_transpiled": "SELECT name, email FROM customers WHERE region = '[EMAIL_REDACTED]'",
"sql_with_rls": "SELECT name, email FROM customers WHERE region = '[EMAIL_REDACTED]' AND org_id = 'org_a1b2c3d4'",
"tables_accessed": ["customers"],
"rows_returned": 42,
"columns_masked": ["email"],
"execution_time_ms": 12,
"transpilation_time_ms": 0.5,
"credits_consumed": 1,
"cache_hit": false,
"cache_key": "sha256:a1b2c3d4...",
"policy_verdicts": [
{
"policy_id": "pol_a1b2c3",
"policy_name": "pii-masking",
"action": "mask",
"columns": ["email"],
"function": "full"
}
],
"abac_evaluation": {
"decision": "allow",
"policies_evaluated": 2,
"evaluation_time_ms": 0.3
},
"agent_metadata": {
"agent_id": "data-analyst-v2",
"framework": "langchain"
},
"timestamp": "2026-02-16T10:30:00Z"
}

IAM Audit

List Admin Actions

GET /v1/environments/{env_id}/audit/admin

Returns hash-chained IAM audit events. Each event includes a SHA-256 hash linking it to the previous event for tamper detection. Requires Owner, Admin, or Auditor role.

Request:

curl "https://api.hatidata.com/v1/environments/env_prod_x1y2/audit/admin?limit=10" \
-H "Authorization: Bearer <jwt>"

Response 200 OK:

{
"data": [
{
"event_id": "iam_a1b2c3",
"event_type": "policy.created",
"actor_id": "usr_x1y2z3",
"actor_email": "alice@acme.com",
"actor_role": "admin",
"source_ip": "10.0.1.50",
"resource_type": "policy",
"resource_id": "pol_g7h8i9",
"changes": {
"after": {
"name": "payment-masking",
"type": "column_masking",
"rules_count": 2
}
},
"hash": "sha256:a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6",
"previous_hash": "sha256:z6y5x4w3v2u1t0s9r8q7p6o5n4m3l2k1j0i9h8g7f6e5d4c3b2a1",
"timestamp": "2026-02-16T10:00:00Z"
},
{
"event_id": "iam_d4e5f6",
"event_type": "user.role_changed",
"actor_id": "usr_x1y2z3",
"actor_email": "alice@acme.com",
"actor_role": "owner",
"source_ip": "10.0.1.50",
"resource_type": "user",
"resource_id": "usr_a4b5c6",
"changes": {
"before": { "role": "developer" },
"after": { "role": "admin" }
},
"hash": "sha256:z6y5x4w3v2u1t0s9r8q7p6o5n4m3l2k1j0i9h8g7f6e5d4c3b2a1",
"previous_hash": "sha256:m3n4o5p6q7r8s9t0u1v2w3x4y5z6a1b2c3d4e5f6g7h8i9j0k1l2",
"timestamp": "2026-02-16T09:45:00Z"
}
],
"pagination": {
"cursor": "cur_def456",
"has_more": true,
"total": 87
}
}

IAM Event Types

CategoryEvent Types
Usersuser.invited, user.removed, user.role_changed, user.suspended, user.reactivated
API Keyskey.created, key.rotated, key.revoked
Policiespolicy.created, policy.updated, policy.deleted, abac_policy.created, abac_policy.updated, abac_policy.deleted
SSOsso.configured, sso.updated, sso.disabled
Webhookswebhook.created, webhook.updated, webhook.deleted
Environmentsenvironment.created, environment.promoted, environment.suspended
JIT Accessjit.requested, jit.approved, jit.denied, jit.revoked
Agentagent_capability.granted, agent_capability.revoked
Organizationorg.settings_updated, org.mfa_enforced

Verify Chain Integrity

GET /v1/environments/{env_id}/audit/admin/verify-chain

Verifies the integrity of the IAM audit hash chain. Each event's hash is computed from the event content plus the previous_hash, forming a tamper-evident chain.

Request:

curl https://api.hatidata.com/v1/environments/env_prod_x1y2/audit/admin/verify-chain \
-H "Authorization: Bearer <jwt>"

Response 200 OK:

{
"chain_valid": true,
"events_verified": 87,
"first_event": {
"event_id": "iam_genesis",
"timestamp": "2026-01-15T10:00:00Z"
},
"last_event": {
"event_id": "iam_a1b2c3",
"timestamp": "2026-02-16T10:00:00Z"
},
"verified_at": "2026-02-16T10:05:00Z"
}

If the chain has been tampered with:

{
"chain_valid": false,
"events_verified": 45,
"break_detected_at": {
"event_id": "iam_x9y8z7",
"expected_hash": "sha256:expected...",
"actual_hash": "sha256:actual...",
"timestamp": "2026-02-10T14:30:00Z"
},
"verified_at": "2026-02-16T10:05:00Z"
}

Export Audit Logs

POST /v1/environments/{env_id}/audit/export

Triggers an export of audit logs for a date range. Logs are written to the configured S3 bucket in JSONL format.

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:

{
"export_id": "exp_p7q8r9",
"type": "query",
"status": "processing",
"date_range": {
"start": "2026-02-01T00:00:00Z",
"end": "2026-02-15T23:59:59Z"
},
"estimated_records": 42000,
"s3_path": "s3://acme-hatidata-audit/exports/exp_p7q8r9/",
"created_at": "2026-02-16T10:00:00Z"
}
FieldTypeRequiredDescription
typestringYesquery or admin
start_datestringYesISO 8601 start date
end_datestringYesISO 8601 end date
formatstringNojsonl (default) or csv

Error Responses

StatusCodeDescription
401UNAUTHORIZEDMissing or invalid authentication
403FORBIDDENInsufficient role (must be Owner, Admin, or Auditor)
404NOT_FOUNDEnvironment or query not found
422INVALID_DATE_RANGEStart date after end date or range exceeds 90 days

Stay in the loop

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