Skip to main content
← Back to Docs

API Reference

3 min read

Overview

The ThreatHarvest API provides programmatic access to findings, requirements, and attributes for your organization.

Base URL

https://api.threatharvest.com/v1

Versioning

The API is versioned via the URL path (/v1/). When breaking changes are introduced, a new version will be released (for example /v2/). Advance notice is provided before any API version is deprecated.

Authentication

All API requests (except /v1/health) require a Bearer token in the Authorization header. Manage keys in your ThreatHarvest account — see API keys.

Format:

Authorization: Bearer YOUR_API_KEY

Example:

curl -H "Authorization: Bearer hvst_live_abc123xyz789" https://api.threatharvest.com/v1/findings

Rate limiting

The API enforces rate limits for fair usage and stability. Limits are subject to change.

  • Limit: 100 requests per hour
  • Method: Sliding window
  • Scope: All endpoints share the same rate limit

Response headers

Every API response includes rate-limit information:

  • X-RateLimit-Limit — maximum requests allowed per hour
  • X-RateLimit-Remaining — requests remaining in the current window
  • X-RateLimit-Reset — ISO 8601 timestamp when the rate limit resets

When you exceed the limit, the API returns 429 Too Many Requests with a Retry-After header (seconds to wait).

Burst limit

In addition, more than 10 requests in 10 seconds from one IP address is blocked with 403 Forbidden for 10 seconds. If this happens, back off and retry after about 10 seconds.

Endpoints

Health

GET /v1/health

Check API status. No authentication required.

Response

{
  "status": "ok",
  "version": "v1"
}

List findings

GET /v1/findings

List findings for your organization.

Query parameters

ParameterDescription
limitOptional. Max results. Default: 50, Max: 100
offsetOptional. Pagination offset. Default: 0
statusOptional. Filter by status. Values: pending, review, resolved
requirement_idOptional. Filter by requirement ID
relevantOptional. Filter by relevance. Values: true, false

Response example

{
  "data": [
    {
      "id": "finding-uuid",
      "requirement": { "id": "req-uuid", "name": "Data Breach Monitoring" },
      "source": { "description": "Example Breaches" },
      "attribute": "user@example.com",
      "summary": "Email found in breach",
      "added": "2024-01-15",
      "status": "pending",
      "relevant": true,
      "thp_score": 7.5
    }
  ],
  "meta": {
    "total": 150,
    "limit": 50,
    "offset": 0,
    "returned": 50
  }
}

Get finding

GET /v1/findings/{finding_id}

Return detailed information for a specific finding.

Path parameters

ParameterDescription
finding_idUnique identifier of the finding

Field notes

  • thp_score — only present (non-null) for relevant findings
  • discovery.status and last_change — null if discovery is not applicable

Response example

{
  "data": {
    "id": "finding-uuid",
    "requirement": { "id": "req-uuid", "name": "Data Breach Monitoring", "short_name": "Breach" },
    "source": { "description": "Example Breaches", "notice": "Sample Data Source" },
    "attribute": "user@example.com",
    "added": "2024-01-15 10:30:45",
    "content": [
      {"name": "Breach Name", "value": "Example Breach"},
      {"name": "Breach Date", "value": "2023-12-01"},
      {"name": "Data Classes", "value": "Emails, Passwords"}
    ],
    "discovery": {
      "enabled": true,
      "status": "Current (Active)",
      "last_change": "2024-01-15 10:30:45"
    },
    "status": "pending",
    "thp_score": 7.5
  }
}

List requirements

GET /v1/requirements

List available requirements.

Response example

{
  "data": [
    {
      "id": "req-uuid",
      "name": "Data Breach Monitoring"
    }
  ],
  "meta": { "total": 10 }
}

List attributes

GET /v1/attributes

List active attributes for your organization.

Response example

{
  "data": [
    {
      "id": "attr-uuid",
      "requirement_id": "req-uuid",
      "attribute_type": "Email Address",
      "attribute_value": "user@example.com",
      "created": "2024-01-01 10:30:45"
    }
  ],
  "meta": { "total": 25 }
}

Error responses

The API uses standard HTTP status codes.

Status codes

CodeDescription
200OK — request successful
400Bad Request — invalid input parameters
401Unauthorized — missing or invalid API key
404Not Found — resource not found or access denied
429Too Many Requests — rate limit exceeded
500Internal Server Error

Format

{
  "error": "Error message description",
  "message": "Optional detailed message"
}

Pagination

List endpoints (for example /v1/findings) support limit and offset.

Example request:

curl -H "Authorization: Bearer KEY" "https://api.threatharvest.com/v1/findings?limit=100&offset=100"

Response metadata:

{
  "meta": {
    "total": 250,
    "limit": 100,
    "offset": 100,
    "returned": 100
  }
}

Examples

Python

import requests

API_KEY = "your-api-key-here"
BASE_URL = "https://api.threatharvest.com/v1"

headers = { "Authorization": f"Bearer {API_KEY}" }

# Get all pending findings
response = requests.get(
    f"{BASE_URL}/findings",
    headers=headers,
    params={"status": "pending", "limit": 100}
)

if response.status_code == 200:
    data = response.json()
    print(f"Found {len(data['data'])} pending findings")
else:
    print(f"Error: {response.json()['error']}")

cURL

#!/bin/bash
API_KEY="your-api-key-here"
BASE_URL="https://api.threatharvest.com/v1"

curl -H "Authorization: Bearer $API_KEY" \
  "$BASE_URL/findings?status=pending&limit=100"

Guidance

  • Keep API keys out of client-side code and public repositories.
  • Use HTTPS for all requests.
  • Watch X-RateLimit-Remaining and back off on 429 responses.
  • Paginate large result sets with limit and offset.

Need help?

Can't find what you need?

Contact us with your question, or start a free trial to try ThreatHarvest yourself.