v2Updated 2026-05-02

Customer API

Reference documentation for accessing PentaTrail CTEM data via REST API and MCP. This read-only public surface requires ctem:read and is generated from the same OpenAPI source as the landing page.

Authentication

Include your API key as a Bearer token in all requests. Generate API keys from the PentaTrail Dashboard under Settings > API Keys.

Example request
curl -H "Authorization: Bearer ptk_your_api_key_here" \
  "https://api.pentatrail.co/v1/ctem/domains"

Scopes

API keys must include ctem:read scope.

ctem:read

OpenAPI

The OpenAPI JSON is generated from the same source-of-truth data used by the landing page. The published docs and the machine-readable spec stay in sync.

OpenAPI JSON
curl -s "https://pentatrail.co/api/openapi/customer-api-v2" | jq .

This spec is generated from the same source-of-truth data as the landing page.

MCP Setup

Model Context Protocol (MCP) Access read-only PentaTrail CTEM data from Model Context Protocol (MCP) clients such as Claude Code and Claude Desktop.

Run
npx @pentatrail/mcp-server
Claude Code / Claude Desktop configuration
{
  "mcpServers": {
    "pentatrail": {
      "command": "npx",
      "args": ["@pentatrail/mcp-server"],
      "env": {
        "PENTATRAIL_API_KEY": "ptk_your_api_key_here",
        "PENTATRAIL_API_URL": "https://api.pentatrail.co"
      }
    }
  }
}

PENTATRAIL_API_URL set PENTATRAIL_API_URL to https://api.pentatrail.co.

Read Endpoints

Read CTEM data. All require ctem:read scope. 9 routes are published today.

GET/v1/ctem/domainsctem:read

List all monitored domains.

GET/v1/ctem/hostsctem:read

List hosts for a domain with enrichment (port count, tech count, open finding count).

domain_idrequiredOrigin domain ID (UUID)
pagePage number (default: 1)
limitItems per page (default: 50, max: 100)
host_statusFilter: active, discovered, dns_only, inactive, third_party
searchSearch by FQDN
order_bySort: fqdn, first_seen_at, last_seen_at, host_status
ascendingtrue/false (default: true)
GET/v1/ctem/findingsctem:read

List vulnerabilities/findings for a domain. Default sort: Threat Discovery Level (TDL5=most critical). Only findings on active hosts are returned.

domain_idrequiredOrigin domain ID (UUID)
pagePage number
limitItems per page (max: 100)
statusFilter: open, in_progress, closed, accepted
severityFilter: critical, high, medium, low, info
priority_keyTDL filter: tdl5, tdl4, tdl3, tdl2, tdl1, info
target_fqdnFilter by affected FQDN
source_filterall, passive_only, deep_only
vuln_idExact match by vulnerability ID
searchSearch by title, vuln_id, or target
order_bySort: effective_priority_rank, cvss, severity_order, first_seen_at, last_seen_at
ascendingtrue/false (default: true)
GET/v1/ctem/assets/countsctem:read

Get counts per asset type (hosts, IPs, ports, tech, buckets, URLs, findings).

domain_idrequiredOrigin domain ID (UUID)
GET/v1/ctem/findings/severityctem:read

Get open finding counts grouped by Threat Discovery Level (TDL). Only findings on active hosts.

domain_idrequiredOrigin domain ID (UUID)
GET/v1/ctem/scoresctem:read

Get live domain scores: asset counts and findings breakdown by severity and status.

domain_idrequiredOrigin domain ID (UUID)
GET/v1/ctem/scores/trendctem:read

Get score trend over time (snapshot-based).

domain_idrequiredOrigin domain ID (UUID)
daysLookback period in days (7-365, default: 56)
GET/v1/ctem/portsctem:read

List discovered open ports.

domain_idrequiredOrigin domain ID (UUID)
pagePage number
limitItems per page (max: 100)
searchSearch by hostname or service
source_typeFilter by scan source type
portFilter by port number
protocoltcp / udp
order_bySort: target, port, service, first_seen_at, last_seen_at
GET/v1/ctem/techctem:read

List discovered technology stack.

domain_idrequiredOrigin domain ID (UUID)
pagePage number
limitItems per page (max: 100)
searchSearch by tech name or hostname
source_typeFilter by scan source type
tech_categoryFilter by category
tech_nameFilter by technology name
order_bySort: tech_name, tech_category, target, first_seen_at, last_seen_at

Error Codes

CodeHTTPDescription
PT_API_AUTH_INVALID401Invalid or expired API key
PT_API_AUTH_IP_DENIED403Request from unauthorized IP
PT_API_SCOPE_DENIED403Insufficient API key scope
PT_API_FORBIDDEN403No access to the requested resource
PT_API_NOT_FOUND404Resource not found
PT_API_ALREADY_EXISTS409Resource already exists
PT_API_RATE_LIMITED429Rate limit exceeded (retriable)
PT_API_INVALID_PARAM400Invalid parameter
PT_API_INVALID_STATUS400Invalid status value
PT_API_INVALID_CATEGORY400Invalid exclusion category
PT_API_INTERNAL500Internal server error (retriable)

Rate Limiting

Each API key is limited to 100 requests per minute. Exceeding the limit returns a 429 response.

Response Headers

X-RateLimit-LimitMaximum requests per window (100)
X-RateLimit-RemainingRemaining requests in current window
X-RateLimit-ResetSeconds until window resets

Correlation ID

Every response includes a correlation_id (format: pt_<uuid>). Use this when contacting support for troubleshooting.