Logs API
Programmatic access to Trinitite's governance audit trail — every interaction, every decision, every correction and block. Use it for SIEM integration, compliance audits, forensic investigation, and custom analytics.
Authentication: Authorization: Bearer <session_token | api_key> with logs:read.
Endpoints
| Method | Path | Purpose |
|---|---|---|
GET | /v1/logs | Query governance logs |
GET | /v1/logs/{log_id} | Get the full forensic record for a single log |
GET /v1/logs
Query parameters
All parameters are optional. Without filters, all logs are returned paginated.
| Param | Type | Description |
|---|---|---|
guardian_name | string | Filter by Guardian name |
guardian_id | string | Filter by Guardian ID |
status | string | passed, corrected, blocked, or error |
start_timestamp | RFC 3339 | Logs at or after this time |
end_timestamp | RFC 3339 | Logs strictly before this time |
user_query | string | Free-text search in user queries |
limit | integer | Page size — default 50, max 500 |
cursor | string | Pagination cursor from previous response |
violation_severity | string | low, medium, high, critical |
mode | string | guardian or direct |
environment | string | live, test, or dev |
has_corrections | boolean | Only logs where corrections were applied |
has_violations | boolean | Only logs where violations were detected |
Response — 200 OK
{
"logs": [
{
"log_id": "log_01JF8RLGA1B2C3D4E5F6G7H8I9",
"timestamp": "2026-05-01T10:00:00Z",
"guardian_name": "PII-Redactor",
"guardian_id": "gov_01JF8R3M3X4N5Q6T7V8W9Y0Z1A",
"guardian_version": "3",
"status": "corrected",
"mode": "guardian",
"user_query": "What is John Doe's account balance?",
"correction_applied": "Redacted account balance (PII policy).",
"correction_count": 1,
"violation_severity": "high",
"processing_time_ms": 85,
"request_id": "req_01JF8RRQ1Z2Y3X4W5V6U7T8S9R",
"environment": "live",
"error_code": null,
"conversation": {
"message_count": 3,
"roles": "user, assistant",
"first_message_preview": "What is John Doe's account balance?"
}
},
{
"log_id": "log_01JF8RLGB2C3D4E5F6G7H8I9J0",
"timestamp": "2026-05-01T10:05:00Z",
"guardian_name": "Ticket-Formatter",
"guardian_id": "gov_01JF8R3M5Z6N7Q8T9V0W1Y2Z3C",
"guardian_version": "1",
"status": "passed",
"mode": "guardian",
"user_query": "Create a ticket with ID TKT-12345",
"correction_applied": null,
"correction_count": 0,
"violation_severity": null,
"processing_time_ms": 45,
"request_id": "req_01JF8RRR2A3B4C5D6E7F8G9H0I",
"environment": "live",
"error_code": null,
"conversation": {
"message_count": 2,
"roles": "user, assistant",
"first_message_preview": "Create a ticket with ID TKT-12345"
}
}
],
"pagination": {
"total": 1542,
"limit": 50,
"next_cursor": "eyJsYXN0X2lkIjoibG9nXzAxSkY4UkxHQjJDM0Q0RTVGNkc3SDhJOUowIn0"
}
}
Response fields
| Field | Type | Description |
|---|---|---|
log_id | string | Unique log identifier (log_*) |
timestamp | RFC 3339 | When the interaction occurred |
guardian_name | string | Guardian that handled the call |
guardian_id | string | Guardian's unique ID (gov_*) |
guardian_version | string | null | Guardian version that processed the request |
status | string | passed, corrected, blocked, or error |
mode | string | guardian or direct |
user_query | string | The input from the user |
correction_applied | string | null | Description of the correction, if any |
correction_count | integer | Number of discrete corrections applied |
violation_severity | string | null | Highest severity violation: low, medium, high, critical |
processing_time_ms | integer | Governance latency in milliseconds |
request_id | string | Correlation ID, matches X-Request-Id |
environment | string | live, test, or dev |
error_code | string | null | Machine-readable error code if status is error |
conversation | object | Summary of the conversation (see below) |
conversation object
| Field | Type | Description |
|---|---|---|
message_count | integer | Total messages in the conversation |
roles | string | Comma-separated list of roles present |
first_message_preview | string | Truncated preview of the first user message |
GET /v1/logs/{log_id}
Retrieve the full forensic record for a single governance interaction — including the complete conversation history, the governance decision chain, every correction applied, token usage, and timing breakdown.
Response — 200 OK
{
"log_id": "log_01JF8RLGA1B2C3D4E5F6G7H8I9",
"timestamp": "2026-05-01T10:00:00Z",
"guardian_name": "PII-Redactor",
"guardian_id": "gov_01JF8R3M3X4N5Q6T7V8W9Y0Z1A",
"guardian_version": "3",
"status": "corrected",
"mode": "guardian",
"user_query": "What is John Doe's account balance?",
"correction_applied": "Redacted account balance (PII policy).",
"correction_count": 1,
"processing_time_ms": 85,
"governance_time_ms": 62,
"llm_time_ms": 18,
"queue_time_ms": 5,
"request_id": "req_01JF8RRQ1Z2Y3X4W5V6U7T8S9R",
"environment": "live",
"region": "us-east-1",
"model_name": "qwen3-4b-instruct",
"instructions": "Redact all PII including account balances and SSNs.",
"action": "Response corrected and returned",
"violation_severity": "high",
"block_reason": null,
"error_code": null,
"error_message": null,
"temperature": 0.0,
"top_p": 1.0,
"max_tokens": 1024,
"prompt_tokens": 145,
"completion_tokens": 38,
"total_tokens": 183,
"user_agent": "trinitite-python-sdk/1.2.0",
"request_size_bytes": 1240,
"response_size_bytes": 890,
"retry_count": 0,
"is_retry": false,
"input_hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"policy_hash": "sha256:c0d3df8a7c0d3df8a7c0d3df8a7c0d3df8a7c0d3df8a7c0d3df8a7c0d3df8a7",
"governance_hash": "sha256:def9876543210fedcba9876543210fedcba9876543210fedcba9876543210fed",
"prev_chain_hash": "sha256:abc1234567890fedcba1234567890fedcba1234567890fedcba1234567890abc",
"conversation_history": [
{ "role": "user", "content": "What is John Doe's account balance?", "timestamp": "2026-05-01T10:00:00.120Z" },
{ "role": "guardian_thinking", "content": "Response contains account balance data. Checking PII policy.", "timestamp": "2026-05-01T10:00:00.245Z" },
{ "role": "correction", "content": "Redacted account balance ($50,000 → [REDACTED])", "timestamp": "2026-05-01T10:00:00.340Z" },
{ "role": "guardian_response", "content": "John Doe's account balance is [REDACTED].", "timestamp": "2026-05-01T10:00:00.670Z" }
],
"corrections": [
{ "op": "replace", "path": "/account_balance", "value": "[REDACTED]" }
],
"violations": [
{ "type": "pii_exposure", "severity": "high", "details": "Account balance detected in response. Redacted per PII policy." }
],
"original_response": { "content": "John Doe's account balance is $50,000." },
"final_response": { "content": "John Doe's account balance is [REDACTED]." }
}
The conversation_history provides the complete chain of reasoning — sufficient for legal discovery, compliance review, and forensic investigation. The four hash fields (input_hash, policy_hash, governance_hash, prev_chain_hash) are the State-Tuple anchors that allow third-party verification via the Public Verification surface.
SIEM envelope (camelCase)
When the platform forwards logs to an SIEM (Splunk, Datadog, CloudWatch) via the configured LOGGING_ADAPTER, fields are emitted as camelCase on top of the same payload — logId, guardianName, guardianId, governanceStatus, correctionCount, processingTimeMs, etc. The REST API list/detail responses retain snake_case for back-compat with API integrations.
Pagination
Iterate using next_cursor:
- Python
- JavaScript
import os, requests
def fetch_all_logs(start_timestamp, end_timestamp):
out, cursor = [], None
while True:
params = {
"start_timestamp": start_timestamp,
"end_timestamp": end_timestamp,
"limit": 500,
}
if cursor:
params["cursor"] = cursor
response = requests.get(
"https://api.trinitite.ai/v1/logs",
headers={"Authorization": f"Bearer {os.environ['TRINITITE_API_KEY']}"},
params=params,
)
data = response.json()
out.extend(data["logs"])
cursor = data["pagination"].get("next_cursor")
if not cursor:
break
return out
async function fetchAllLogs(startTimestamp, endTimestamp) {
const all = [];
let cursor = null;
while (true) {
const url = new URL('https://api.trinitite.ai/v1/logs');
url.searchParams.set('start_timestamp', startTimestamp);
url.searchParams.set('end_timestamp', endTimestamp);
url.searchParams.set('limit', '500');
if (cursor) url.searchParams.set('cursor', cursor);
const response = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.TRINITITE_API_KEY}` },
});
const data = await response.json();
all.push(...data.logs);
if (!data.pagination.next_cursor) break;
cursor = data.pagination.next_cursor;
}
return all;
}
Use cases
SIEM forwarding
import os, requests
from datetime import datetime, timedelta, timezone
last_fetch = (datetime.now(timezone.utc) - timedelta(minutes=5)).isoformat()
response = requests.get(
"https://api.trinitite.ai/v1/logs",
headers={"Authorization": f"Bearer {os.environ['TRINITITE_API_KEY']}"},
params={"start_timestamp": last_fetch},
)
for log in response.json()["logs"]:
requests.post(
"https://splunk.example.com:8088/services/collector",
headers={"Authorization": f"Splunk {os.environ['SPLUNK_TOKEN']}"},
json={"event": log},
)
Compliance audit export
curl -G "https://api.trinitite.ai/v1/logs" \
-H "Authorization: Bearer $TRINITITE_API_KEY" \
--data-urlencode "status=blocked" \
--data-urlencode "start_timestamp=2026-01-01T00:00:00Z" \
--data-urlencode "end_timestamp=2026-03-31T23:59:59Z" \
--data-urlencode "limit=500"
Latency by Guardian
from collections import defaultdict
by_guardian = defaultdict(lambda: [0, 0])
for log in all_logs:
by_guardian[log["guardian_name"]][0] += log["processing_time_ms"]
by_guardian[log["guardian_name"]][1] += 1
for name, (total, count) in by_guardian.items():
print(f"{name}: avg {total // count}ms")
Alert on blocked spikes
blocked_last_hour = fetch_all_logs(
start_timestamp=(datetime.now(timezone.utc) - timedelta(hours=1)).isoformat(),
end_timestamp=datetime.now(timezone.utc).isoformat(),
)
blocked = [log for log in blocked_last_hour if log["status"] == "blocked"]
if len(blocked) > 100:
send_security_alert(f"{len(blocked)} blocks in the last hour")
Errors
| HTTP | error.code | Cause |
|---|---|---|
400 | validation_error | Malformed timestamp, unknown filter value, limit out of range |
401 | unauthenticated | Missing or invalid credential |
403 | forbidden | Caller lacks logs:read |
404 | not_found | Log ID not found in your organization |
429 | rate_limited | Per-organization rate limit exceeded |
{
"error": {
"code": "validation_error",
"message": "Invalid timestamp format. Use RFC 3339 (e.g. 2026-05-01T00:00:00Z).",
"details": { "field": "start_timestamp" },
"request_id": "req_01J..."
}
}
Data retention
Logs are retained for 7 years by default (configurable per enterprise contract). Logs are immutable — they cannot be deleted for compliance reasons. GDPR redaction of PII within log content is available via the Compliance DSR API.
Best practices
- Always filter by timestamp. Fetching all logs without a time range is slow and expensive.
- Paginate. Never assume all results fit in one response — always check
next_cursor. - Cache locally. For analytics, pull logs into your warehouse on a schedule rather than querying the API in real time.
- Verify hashes externally. The
*_hashfields can be re-validated via the Public Verification endpoint without holding API credentials.
Next steps
- Govern AI output → Chat endpoint
- Verify a hash externally → Public Verification
- Monitor governance metrics → Analytics API
- Authentication and rate limits → Authentication