API Reference

The Tenurex API provides programmatic access to your compliance evidence, control gap data, and integration status. The API is available on Scale plan. All requests use HTTPS and return JSON.

Base URL: https://api.tenureq.com/v1

Authentication

All API requests require a bearer token. Generate API keys from your account settings under Settings → API Keys.

curl https://api.tenureq.com/v1/evidence \
  -H "Authorization: Bearer tnx_sk_live_..." \
  -H "Content-Type: application/json"

API keys are scoped to your organization. All keys log access with timestamps and endpoint. Keys can be rotated or revoked from the dashboard at any time.

Evidence endpoints

List evidence runs

Returns a paginated list of evidence collection runs, sorted by most recent first.

GET /v1/evidence/runs

Query parameters:
  framework   string   Filter by framework: soc2, iso27001, hipaa
  status      string   Filter by status: pass, gap, collecting
  from        string   ISO 8601 date — start of range
  to          string   ISO 8601 date — end of range
  limit       integer  Default 50, max 200
  cursor      string   Pagination cursor from previous response

Example response:

{
  "runs": [
    {
      "id": "run_01hx2kv...",
      "collected_at": "2026-06-15T12:00:00Z",
      "integration": "aws",
      "framework": "soc2",
      "control_id": "CC6.1",
      "status": "pass",
      "evidence_hash": "sha256:a3f9...",
      "source": "IAM policy export"
    }
  ],
  "next_cursor": "cur_01hx2...",
  "has_more": true
}

Get evidence run by ID

GET /v1/evidence/runs/{run_id}

Export evidence package

Triggers an async export of evidence for a specified framework and time range. Returns a job ID — poll for completion.

POST /v1/evidence/export

{
  "framework": "soc2",
  "from": "2025-07-01",
  "to": "2026-06-30",
  "format": "pdf"
}

Gap endpoints

List active gaps

Returns all currently active control gaps — controls where evidence is missing, failing, or drift has been detected.

GET /v1/gaps

Query parameters:
  framework   string   Filter by framework
  severity    string   critical, high, warning, informational
  status      string   open, acknowledged, resolved
  limit       integer  Default 50, max 200

Example response:

{
  "gaps": [
    {
      "id": "gap_01hx3...",
      "control_id": "CC7.2",
      "framework": "soc2",
      "severity": "critical",
      "description": "CloudTrail logging disabled in us-west-2",
      "detected_at": "2026-06-15T14:12:00Z",
      "status": "open",
      "integration": "aws"
    }
  ]
}

Acknowledge a gap

POST /v1/gaps/{gap_id}/acknowledge

{
  "note": "Investigating — CloudTrail config change in progress",
  "acknowledged_by": "[email protected]"
}

Webhooks

Configure webhooks to receive real-time notifications when gaps are detected, evidence runs complete, or integration health changes.

Register a webhook endpoint

POST /v1/webhooks

{
  "url": "https://your-system.example.com/tenurex-events",
  "events": ["gap.created", "gap.resolved", "run.completed"],
  "secret": "your_webhook_secret"
}

Webhook event payload

All webhook payloads include a X-Tenurex-Signature header for verification. The signature is an HMAC-SHA256 hash of the request body using your webhook secret.

{
  "event": "gap.created",
  "timestamp": "2026-06-15T14:12:00Z",
  "data": {
    "gap_id": "gap_01hx3...",
    "control_id": "CC7.2",
    "severity": "critical",
    "description": "CloudTrail logging disabled in us-west-2",
    "framework": "soc2"
  }
}

Verify webhook signatures

import hmac
import hashlib

def verify_webhook(payload_body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload_body,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature)

Rate limits

API rate limits are enforced per API key:

  • Read endpoints: 1,000 requests per minute
  • Write endpoints: 100 requests per minute
  • Export jobs: 10 concurrent exports

Rate limit headers are included in every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. A 429 Too Many Requests response is returned when limits are exceeded.

Error responses

All error responses use standard HTTP status codes and return a JSON body:

{
  "error": {
    "code": "integration_not_found",
    "message": "Integration aws_prod does not exist in your account",
    "request_id": "req_01hx4..."
  }
}