HTTP API
Enable the REST + SSE API with relay-core-cli run --api-port 8082. Default base URL: http://127.0.0.1:8082/api/v1/. Add --api-token <T> to require Authorization: Bearer <T> on every request, and --api-cors <origins> to allow browser clients. CORS is only emitted when --api-cors is set; the server is otherwise strict.
Version & Status
GET /api/v1/version
Engine version, API version, and a list of registered capability names.
{
"engine_version": "0.6.0",
"api_version": "1",
"capabilities": ["flows", "rules", "intercepts", "mock", "metrics", "status", "events", "scripts"]
} GET /api/v1/status
Runtime lifecycle snapshot — uptime, current rules count, intercepts pending, etc.
Flows
GET /api/v1/flows
Search and paginate captured flows. All parameters are optional.
Query Parameters:
host,path,path_contains,method— substring matchesstatus_min,status_max— status code rangehas_error— only flows with errorsis_websocket— only WebSocket flowslimit— page size, default 50, clamped to 1–200offset— pagination offset
{
"items": [{ "id": "fld_...", "method": "GET", "path": "/users", "status": 200 }],
"returned": 10,
"limit": 50,
"offset": 0
} Redaction is applied to URLs (sensitive query keys) and headers before the response leaves the server, so secrets never appear in the result even if they were observed in traffic.
GET /api/v1/flows/:id
Full Flow JSON including headers and bodies. The same redaction rules apply.
POST /api/v1/flows/:id/replay
Replay a captured flow against the live network. Send a JSON body with optional modifications. ?accept_invalid_certs=true skips TLS verification for the replay (debug only).
GET /api/v1/flows/:id/har
Export a single flow as a HAR 1.2 entry.
GET /api/v1/flows/export/har
Batch HAR export. Accepts the same query parameters as GET /api/v1/flows.
Rules
GET /api/v1/rules
List all interception rules. Each entry contains the full Rule object (id, name, priority, stage, filter, actions, enabled).
PUT /api/v1/rules
Create or replace a rule by id.
{
"id": "rul_01HX5K9P3Q8Y2Z7",
"name": "Log API requests",
"priority": 100,
"filter": {
"method": "GET",
"host": "*.example.com",
"path": "/api/*"
},
"action": {
"type": "log"
},
"enabled": true
} DELETE /api/v1/rules/:id
Delete a rule.
POST /api/v1/mock
Quickly create a MockResponse rule. Body fields: url_pattern, status, body, content_type.
Intercepts
POST /api/v1/intercepts
Create a one-shot intercept breakpoint.
{
"url_pattern": "api.example.com",
"phase": "request"
} The response includes the generated rule_id used to refer to the intercept.
GET /api/v1/intercepts
List pending intercepts (both HTTP and WebSocket).
POST /api/v1/intercepts/:key/resume
Resume an intercepted flow. Body accepts action (continue or drop) and any FlowModification fields to apply before forwarding: method, url, request_headers, request_body, status_code, response_headers, response_body, message_content.
Policy & Redaction
GET /api/v1/policy
Return the current ProxyPolicy, including the redaction block and (if configured) the upstream block. The password field of an upstream auth is masked as ***.
PATCH /api/v1/policy
Apply a partial update. Both top-level keys are optional:
{
"redaction": {
"enabled": true,
"redact_bodies": true,
"sensitive_header_names": ["authorization", "x-api-key", "cookie"],
"sensitive_query_keys": ["token", "api_key", "password"]
},
"upstream": {
"proxy_url": "http://corp-proxy.internal:8080",
"bypass_hosts": ["*.internal", "127.0.0.1"],
"fail_open": false
}
} Default sensitive header names: authorization, proxy-authorization, cookie, set-cookie, x-api-key, x-auth-token.
Default sensitive query keys: token, access_token, refresh_token, api_key, apikey, password, secret.
Redaction is applied to the HTTP request/response, the WebSocket handshake, every WebSocket message, flow summaries, search results, and the SSE event stream. Changing upstream.proxy_url at runtime returns 409 Conflict — restart the proxy to apply it.
Scripting
POST /api/v1/script
Hot-load a script into the running engine.
{ "script": "// deno-fmt-ignore\nexport default { onRequest(ctx) { /* ... */ } }" } Events
GET /api/v1/events
Server-Sent Events stream of live updates.
Event types:
flow— new or updated flow (full Flow JSON in the data field)ws-message— new WebSocket messagehttp-body— body chunk available; the data field is{ "flow_id": "..." }, fetch the body viaGET /api/v1/flows/:idbody-budget-exceeded— body cap reached, no further body will be sentaudit— control-plane mutation (rule change, intercept resolved, script reloaded, policy updated)audit-lagged— audit channel dropped events, server resyncslagged— flow / events channel dropped events, TUI resyncslifecycle— proxy start / stop / reload
Metrics
GET /api/v1/metrics
JSON metrics snapshot. Same fields as relay-core-cli metrics (see CLI reference).
GET /api/v1/metrics/prometheus
Prometheus text format metrics.
# HELP relay_core_flows_total Total number of flows captured
# TYPE relay_core_flows_total counter
relay_core_flows_total 12847
# HELP relay_core_request_duration_ms Request duration in milliseconds
# TYPE relay_core_request_duration_ms histogram
relay_core_request_duration_ms_bucket{le="1"} 10023
relay_core_request_duration_ms_bucket{le="5"} 12500
relay_core_request_duration_ms_bucket{le="10"} 12800
relay_core_request_duration_ms_bucket{le="+Inf"} 12847 Script-engine metrics are emitted per hook: relay_core_script_hook_duration_us{hook}, relay_core_script_hook_invocations_total{hook}, relay_core_script_hook_errors_total{hook}, plus relay_core_script_env_access_total, relay_core_script_fetch_total, and relay_core_script_fetch_rejected_total.
Audit
GET /api/v1/audit
Query the control-plane mutation audit log.
Query Parameters:
since_ms,until_ms— epoch milliseconds; either may be omittedactor—runtime,http,tauri,probe, orclikind—rule_changed,intercept_resolved,script_reloaded,policy_updatedoutcome—successorfailure
The response is a JSON array of AuditEvent entries. Each event records who made the change, when, and the relevant before/after diff for mutations.