TirraMind API

API Reference

Complete reference for TirraMind's HTTP API. Every tier provides deterministic signal intelligence — no predictions, no LLM hallucinations, just the math.

Quickstart

Get your first API call working in under a minute:

  1. Subscribe to a tier at /pricing
  2. Retrieve your API key at /welcome after payment
  3. Use the key with any endpoint below

Your first request (Brief tier):

curl -H "X-Brief-Key: tirra_..." https://api.tirramind.com/brief.json

Production base URL:

https://api.tirramind.com

Authentication

Sending your key

Use the X-Brief-Key header (recommended):

curl -H "X-Brief-Key: tirra_..." https://api.tirramind.com/brief.json

Passing the key in the query string is rejected:

curl 'https://api.tirramind.com/brief.json?key=tirra_...' → 400 {"ok": false, "error": "query-string API keys are disabled — pass the key via the X-Brief-Key header"}

Query strings are written to access logs and leak via Referer headers, so a key passed that way is a key you have to rotate. Use the header.

Key format and safety

Your key is a long random string starting with tirra_. Treat it like a password:

  • Do not commit it to version control
  • Do not pass it in URLs (use the header instead)
  • Store it in an environment variable or secrets manager
  • If compromised, rotate it immediately via POST /api/v1/rotate-key

Tiers and gates

The API is tiered by price. Higher tiers unlock everything below them — the ladder is monotonic:

Brief ($29/month)

Entry rung. Unlocks:

  • /brief, /brief.json, /brief.md
  • /api/v1/usage
  • POST /api/v1/rotate-key
Scheduler ($50/month)

Adds pipeline visibility. Unlocks everything above plus:

  • /api/v1/dag/runs
Entity Graph ($300/month)

Adds deterministic entity and relationship extraction. Unlocks everything above plus:

  • /api/v1/entity-graph/entities
  • /api/v1/entity-graph/entity
  • /api/v1/entity-graph/links
  • /evidence/graph, /evidence/stats, /evidence/analytics, /evidence/graph/export, /evidence/graph/centrality
Data Platform ($500/month)

Full infrastructure access. Unlocks everything above plus:

  • /api/v1/sources
  • /api/v1/data

Endpoints

GET /api/v1/claim
Claim your API key after completing a purchase. Exchange a Paddle transaction ID for your key.

No tier required (unauthenticated — no key needed yet)

Example

curl 'https://api.tirramind.com/api/v1/claim?txn=txn_0a1b2c3d4e5f'

Parameters

Name Type Notes
txn string required Transaction ID from Paddle confirmation email

Response (200 - claimed)

{ "ok": true, "status": "claimed", "api_key": "tirra_...", "tier": "brief", "subscription_id": "sub_..." }

Response (202 - pending)

Provisioning is still in progress. Retry after the specified delay.

{ "ok": true, "status": "pending", "retry_after_s": 3, "message": "payment received — provisioning your key" }

Errors

400 — Missing or malformed transaction ID.
404 — No transaction found for this ID.
422 — Transaction exists but payment did not complete.
429 — Rate limited (8 requests per 10 minutes per transaction).
GET /status
System delivery status. Useful for monitoring and health checks.

No tier required (unauthenticated)

Example

curl https://api.tirramind.com/status

Response (200)

{ "out_dir": ".tirra_delivery", "total_deliveries": 8, "latest": { "delivered_at": 1787834185.3, "json_path": ".tirra_delivery/intelligence_brief.json", "md_path": ".tirra_delivery/intelligence_brief.md", "n_contracts": 5, "n_anomalies": 8, "duration_ms": 0.69 } }

latest is null when no brief has been delivered yet. total_deliveries is the cumulative count.

GET /brief · /brief.json
Latest delivered intelligence brief as JSON. Both paths return identical JSON content.

Brief

Example

curl -H "X-Brief-Key: tirra_..." https://api.tirramind.com/brief.json
curl -H "X-Brief-Key: tirra_..." https://api.tirramind.com/brief

Response (200)

{ "brief_type": "weekly", "contract_opportunities": [ { "award_id": "...", "recipient": "...", "agency": "...", "description": "...", "amount_usd": 1000000, "p_win": 0.65, "expected_value_usd": 650000 } ], "live_anomalies": [ { "source": "cftc", "observation_type": "positioning_extreme", "entity_id": "...", "field": "net_long", "zscore": 3.2, "flagged_ts": 1787834185.0, "latest_value": 42000 } ] }

Errors

403 — No valid key provided or key does not have Brief tier. See /pricing.
404 — No brief has been delivered yet.
GET /brief.md
Latest brief as Markdown. Same content as JSON, rendered for readability.

Brief

Example

curl -H "X-Brief-Key: tirra_..." https://api.tirramind.com/brief.md

Response (200)

Markdown-rendered brief. Same structure as JSON.

GET /api/v1/usage
Your API usage summary for this key. Includes request counts by endpoint.

Brief+

Example

curl -H "X-Brief-Key: tirra_..." https://api.tirramind.com/api/v1/usage

Parameters

Name Type Notes
since float (optional) Unix epoch seconds. Only count requests after this time.

Response (200)

{ "ok": true, "total": 42, "by_endpoint": { "/brief.json": 30, "/api/v1/data": 12 } }
GET /api/v1/sources
List all queryable external data sources. Use this to discover valid source names for /api/v1/data.

Data Platform

Example

curl -H "X-Brief-Key: tirra_..." https://api.tirramind.com/api/v1/sources

Response (200)

{ "ok": true, "sources": [ { "source": "cftc", "rows": 8192, "last_fetched_at": 1787834185.7 }, { "source": "gdelt", "rows": 342000, "last_fetched_at": 1787834100.0 } ] }
GET /api/v1/data
Query rows from a specific external data source. Use /api/v1/sources first to discover available sources.

Data Platform

Example

curl -H "X-Brief-Key: tirra_..." \ 'https://api.tirramind.com/api/v1/data?source=cftc&limit=50'

Parameters

Name Type Default Notes
source string required Must be in the allowlist from /api/v1/sources
limit int 100 Clamped to 1–1000
since float none Unix epoch seconds. Only rows fetched after this time.
until float none Unix epoch seconds. Only rows fetched before this time.

Response (200)

{ "ok": true, "source": "cftc", "rows": [ { "id": 1, "source": "cftc", "fetched_at": 1787834185.7, "params": {...}, "data": {...} } ] }

Errors

400 — Missing or unknown source. See /api/v1/sources for valid names.
GET /api/v1/dag/runs
Pipeline execution history. View DAG run status, timing, and node-level results.

Scheduler+

Example

curl -H "X-Brief-Key: tirra_..." \ 'https://api.tirramind.com/api/v1/dag/runs?dag_name=daily_collection&limit=10'

Parameters

Name Type Default Notes
dag_name string none Filter by DAG name (exact match). Omit to see all.
limit int 20 Clamped to 1–1000

Response (200)

{ "ok": true, "runs": [ { "run_id": "69f521c3b194", "dag_name": "daily_collection", "started_at": 1787834100.0, "finished_at": 1787834185.7, "status": "completed", "trigger": "manual", "node_results": { "fetch_cftc": {"status": "completed"}, "fetch_gdelt": {"status": "completed"} } } ] }
GET /api/v1/entity-graph/entities
List entities from the production graph. Paginated with type filtering.

Entity Graph+

Example

curl -H "X-Brief-Key: tirra_..." \ 'https://api.tirramind.com/api/v1/entity-graph/entities?type=company&limit=50'

Parameters

Name Type Default Notes
type string none Filter by entity_type (optional)
limit int 100 Clamped to 1–1000
offset int 0 Pagination: skip this many results

Response (200)

{ "ok": true, "entities": [ { "entity_id": "01146d...", "entity_type": "company", "canonical_name": "TirraMind Inc", "created_at": 1787000000.0 } ], "count": 50, "total": 6172, "limit": 100, "offset": 0 }
GET /api/v1/entity-graph/entity
Get a single entity by ID plus all its linked relationships in both directions.

Entity Graph+

Example

curl -H "X-Brief-Key: tirra_..." \ 'https://api.tirramind.com/api/v1/entity-graph/entity?id=01146d...&limit=100'

Parameters

Name Type Notes
id string required
limit int Max links to return. Default 100, clamped to 1–1000.

Response (200)

{ "ok": true, "entity": { "entity_id": "01146d...", "entity_type": "company", "canonical_name": "TirraMind Inc", "created_at": 1787000000.0 }, "links": [ { "link_id": 1, "entity_id_a": "01146d...", "entity_id_b": "02abc4...", "link_type": "competitor", "confidence": 0.92, "source": "gdelt", "created_at": 1787000100.0 } ] }

Errors

400 — Missing id parameter.
404 — Entity not found.
GET /api/v1/entity-graph/links
List relationships in the entity graph. Filter by type and confidence.

Entity Graph+

Example

curl -H "X-Brief-Key: tirra_..." \ 'https://api.tirramind.com/api/v1/entity-graph/links?link_type=competitor&min_confidence=0.9'

Parameters

Name Type Default Notes
link_type string none Filter by link type (optional)
min_confidence float 0.0 Only links with confidence ≥ this value
limit int 100 Clamped to 1–1000
offset int 0 Pagination: skip this many results

Response (200)

{ "ok": true, "links": [ { "link_id": 1, "entity_id_a": "01146d...", "entity_id_b": "02abc4...", "link_type": "competitor", "confidence": 0.92, "source": "gdelt", "created_at": 1787000100.0 } ], "count": 100, "total": 17581, "limit": 100, "offset": 0 }
GET /evidence/graph
Search document evidence store for mentions of an entity.

Entity Graph+

Example

curl -H "X-Brief-Key: tirra_..." \ 'https://api.tirramind.com/evidence/graph?q=nvidia'

Parameters

Name Type Notes
q string required Entity string to search for

Response (200)

{ "ok": true, "entity": "nvidia", "mentions": 42, "related": [ {"entity": "cuda", "co_occurrences": 38}, {"entity": "gpu", "co_occurrences": 35} ] }
GET /evidence/stats
Overview of the document evidence store: document count, mentions, and links.

Entity Graph+

Example

curl -H "X-Brief-Key: tirra_..." https://api.tirramind.com/evidence/stats

Response (200)

{ "ok": true, "stats": { "documents": 13, "mentions": 1565, "links": 5346 } }
GET /evidence/analytics
Cross-document co-occurrence analysis. Find entities that appear together across multiple documents.

Entity Graph+

Example

curl -H "X-Brief-Key: tirra_..." \ 'https://api.tirramind.com/evidence/analytics?q=nvidia&min_docs=2'

Parameters

Name Type Default Notes
q string none Entity string. If omitted, returns overall co-occurrences.
min_docs int 2 Only pairs appearing in this many documents

Response (200)

{ "ok": true, "co_occurrences": [ { "entity_a": "nvidia", "entity_b": "cuda", "documents": 8, "confidence": 0.95 } ], "cross_doc_pairs": 142 }
GET /evidence/graph/export
Export the entire document evidence graph as JSON.

Entity Graph+

Example

curl -H "X-Brief-Key: tirra_..." https://api.tirramind.com/evidence/graph/export

Response (200)

Complete graph structure with all entities, mentions, and relationships.

GET /evidence/graph/centrality
Degree centrality analysis. Find the most connected entities in the graph.

Entity Graph+

Example

curl -H "X-Brief-Key: tirra_..." \ 'https://api.tirramind.com/evidence/graph/centrality?q=nvidia&top=20'

Parameters

Name Type Default Notes
q string none Entity to analyze. If omitted, returns global top entities.
top int 10 Number of top entities to return (not clamped)

Response (200)

{ "ok": true, "top_by_degree": [ {"entity": "gpu", "degree": 156}, {"entity": "cuda", "degree": 142} ], "neighbors": [ {"entity": "tensor", "degree": 89}, {"entity": "compute", "degree": 76} ] }
POST /api/v1/rotate-key
Rotate your API key. The old key becomes invalid immediately. No request body required.

Brief+

Example

curl -X POST -H "X-Brief-Key: tirra_OLD_KEY" \ https://api.tirramind.com/api/v1/rotate-key

Response (200)

{ "ok": true, "message": "key rotated", "new_key": "tirra_..." }

Important: Save the new key immediately. You will not be shown it again. The old key is revoked instantly.

Errors

403 — Invalid or missing key.
POST /api/v1/contact
Submit a contact form. Messages are stored and reviewed by our team.

No tier required (public endpoint)

Example

curl -X POST -H "Content-Type: application/json" \ -d '{ "name": "Alice Smith", "email": "[email protected]", "subject": "API questions", "message": "How do I filter entities by confidence?" }' \ https://api.tirramind.com/api/v1/contact

Request body

Field Type Notes
name string required Max 300 chars
email string required Max 300 chars
subject string required Max 300 chars
message string required Max 8000 chars

Response (200)

{"ok": true, "message": "received"}

Errors

400 — Missing required fields or JSON parse error.
413 — Request body exceeds 8 KB.
429 — Rate limited. Max 5 messages per IP per hour.

Error codes

400 Bad Request

Malformed request. Check your parameters:

  • Invalid or missing required parameters
  • Unparseable JSON in request body
  • Query string key disabled (set TIRRA_REJECT_QUERY_KEYS=1 in production)

403 Forbidden

Authentication or authorization failed:

  • No API key provided
  • API key is invalid or inactive
  • Tier gate: your subscription doesn't include this endpoint

Response is always text/plain. Subscribe at /pricing or upgrade your tier.

404 Not Found

Resource or endpoint not found:

  • Entity doesn't exist
  • No brief has been delivered yet
  • Route doesn't exist

429 Too Many Requests

Rate limit exceeded. Response includes a Retry-After header:

HTTP/1.1 429 Too Many Requests Retry-After: 60 {"ok": false, "error": "rate limited", "retry_after_s": 60}

Wait the specified number of seconds before retrying.

500 Internal Server Error

Unexpected server error. These should be rare. If you see this consistently, contact us.

502 Bad Gateway

Upstream service unavailable. This usually indicates a temporary issue with Paddle (payment verification).

Rate limits and quotas

Global limits

These limits apply to all endpoints unless noted otherwise:

  • Per-request timeout: No hard timeout, but requests must complete within reasonable time.
  • Concurrent connections: Server supports up to 20 concurrent requests by default.
  • Response size: No hard limit on response size. Large queries may take longer.

Endpoint-specific limits

GET /api/v1/claim (transaction verification)

Per transaction: 8 requests / 10 minutes

Per source IP: 20 requests / 1 hour

POST /api/v1/contact (contact form)

Per source IP: 5 requests / 1 hour

Metering and usage tracking

The following endpoints are metered — your usage counts toward any future quota system:

  • /brief, /brief.json, /brief.md
  • /api/v1/sources
  • /api/v1/data
  • /api/v1/dag/runs
  • /api/v1/usage (metering is skipped for this endpoint itself)
  • /evidence/* (all evidence endpoints)
  • /api/v1/entity-graph/* (all entity graph endpoints)

Query your usage at any time with GET /api/v1/usage.