Skip to content

Client HTTP API Reference

Hugo edited this page Oct 16, 2026 · 3 revisions

Client HTTP API Reference

Back to Home

Overview

CoreTrace exposes an HTTP server with --ipc serve.

./ctrace --ipc serve --serve-host 127.0.0.1 --serve-port 8080 \
         --shutdown-token mytoken --shutdown-timeout-ms 5000

Endpoints:

  • POST /api
  • POST /shutdown
  • OPTIONS /api and OPTIONS /shutdown (CORS preflight)

Transport Behavior

  • Binding. The host is resolved once, and only its first address is bound, which the log gives (::1 for localhost on macOS): connect to that address, or use the same name. When that address and port are already in use, the server exits with code 1. On macOS, a server on 0.0.0.0 and another on 127.0.0.1 can still share a port.
  • Body limit. Requests carry a file list, not file contents, so the body is capped at server.max_body_bytes (default 1 MiB). A larger body is rejected by the HTTP layer.
  • CORS is opt-in. No Access-Control-Allow-Origin header is sent unless server.cors_origin is configured, so a page on another origin cannot read the response. When it is set, the server also answers preflight with POST, OPTIONS and Content-Type.
  • Shutting down. While a graceful shutdown is in progress, /api answers 503 with error.code=ServerShuttingDown, and OPTIONS answers 503.
  • Bad body. A body that is not valid JSON, or not a JSON object, answers 400 with error.code=InvalidRequest.
  • Server failures. An unexpected exception, or a resource of the server's side that is not available (an IPC socket nobody listens on), answers 500 with error.code=InternalError; the details are only in the server's log.
  • Encoding. Bytes that are not UTF-8, in the request or in a tool's output, are replaced by U+FFFD in the answer, which is always valid JSON.

server.max_body_bytes and server.cors_origin live in the server section of the config file; there is no CLI flag for them.

Request Contract (POST /api)

The request is a JSON object with these top-level fields:

  • proto (string, required): coretrace-1.0. Any other value, or none, answers 400 with error.code=UnsupportedProtocol.
  • id (any JSON value, optional; echoed back, default 0)
  • type (string, optional): request when given, else 400 InvalidRequest
  • method (string) — only run_analysis is supported
  • params (object)

An unknown method answers 400 with error.code=UnknownMethod.

params for run_analysis

Every parameter is flat in the request and is translated into the sectioned configuration document, then applied through the same loader as the config file and the CLI — one validation path for all three. docs/configuration.md documents the semantics of each target key.

Parameter Config key Type
verbose output.verbose bool
quiet output.quiet bool
demangle output.demangle bool
sarif_format output.sarif_format bool
report_file output.report_file string
output_file output.output_file string
static_analysis analysis.static bool
dynamic_analysis analysis.dynamic bool
invoke analysis.invoke list
fail_on analysis.fail_on string (error|warning|none)
input files.input list
entry_points files.entry_points list
compile_commands files.compile_commands string
include_compdb_deps files.include_compdb_deps bool
jobs runtime.jobs uint (0 one per core, the default; 1 sequential)
async runtime.async bool, deprecated: use jobs
ipc_path runtime.ipc_path string
timing stack_analyzer.timing bool
analysis_profile stack_analyzer.analysis_profile string
smt stack_analyzer.smt string (on|off)
smt_backend stack_analyzer.smt_backend string
smt_secondary_backend stack_analyzer.smt_secondary_backend string
smt_mode stack_analyzer.smt_mode string
smt_timeout_ms stack_analyzer.smt_timeout_ms uint
smt_budget_nodes stack_analyzer.smt_budget_nodes uint
smt_rules stack_analyzer.smt_rules list
stack_limit stack_analyzer.stack_limit uint
resource_model stack_analyzer.resource_model string
escape_model stack_analyzer.escape_model string
buffer_model stack_analyzer.buffer_model string
stack_analyzer_mode stack_analyzer.mode string
stack_analyzer_output_format stack_analyzer.output_format string
stack_analyzer_extra_args stack_analyzer.extra_args list

Two parameters are handled outside the table:

  • config (string): path to a JSON config file, loaded before the request parameters. Precedence is defaults < config file < request parameters. A load failure answers InvalidParams with Failed to load config: ....
  • ipc (string): standardIO, socket or serve, with serv and server accepted as aliases of serve. Inside a request, serve means the analysis runs in-process, so it is normalized to standardIO for tool execution.

List parameters

A list parameter accepts either a JSON array of strings or a comma-separated string; empty items are dropped. input items are themselves split on commas, so "input": "a.c,b.c" and "input": ["a.c", "b.c"] are equivalent.

Validation

As the config file does, a request rejects the parameters it does not know: an unknown parameter, a wrong JSON type or a value out of range answers 400 with error.code=InvalidParams. Loader diagnostics are rewritten to name the flat parameter the client sent rather than the internal section key. Deprecated config-file spellings found in a config file are logged as warnings, not errors.

Success Response Shape

status=ok, with result containing:

Findings

  • diagnostics: every finding in one model, whatever tool produced it — tool, rule_id, file, line, column, severity, message, cwe.
  • diagnostics_summary_total: counts by severity (info, warning, error).
  • sarif: the merged SARIF 2.1.0 log, present when sarif_format is true. It is the same document the CLI prints, and it is also written to report_file.
  • uninterpreted_tools: tools that ran without ever reporting structured findings. Their output is in outputs but is not counted — this is distinct from a tool with zero findings.

Verdict

  • gate: the verdict the CLI would exit with, so a client applies one policy — fail_on, exit_code (see Exit Codes) and failed_tools.

Echo of the effective configuration

files (number of processed files), static_analysis, dynamic_analysis, invoked_tools, sarif_format, report_file, config, include_compdb_deps, resource_model, escape_model, buffer_model, analysis_profile, smt, smt_backend, smt_secondary_backend, smt_mode, smt_timeout_ms, smt_budget_nodes, smt_rules, timing, stack_limit, stack_analyzer_mode, stack_analyzer_output_format, stack_analyzer_extra_args.

Raw tool output

  • outputs: an object keyed by tool name. Each entry has stream (stdout or stderr) and message — a string, or a parsed JSON object/array when the captured text is valid JSON.

Each request gets the same shipped defaults as the CLI: the stack analyzer models and the bundled tools found next to the server's ctrace binary fill whatever the request and its config file leave empty.

Error Codes

Code HTTP Meaning
InvalidRequest 400 Body is not valid JSON or not a JSON object, or type is not request
UnsupportedProtocol 400 proto is missing or is not coretrace-1.0
UnknownMethod 400 method is not run_analysis
InvalidParams 400 Unknown parameter, type/validation failure, bad ipc value, or a config file that failed to load
NoAnalysisSelected 400 None of static_analysis, dynamic_analysis, invoke selected
InvalidInput 400 Input resolution failed (e.g. a .json input that is not a compile database)
MissingInput 400 Resolution produced no source file
DynamicAnalysisDisabled 403 Dynamic analysis, or the runtime analyzer, without --serve-allow-dynamic on the server
InternalError 500 A failure on the server's side; the details are only in its log
ServerShuttingDown 503 Server is closing and rejects new /api work
Unauthorized 403 /shutdown token missing or invalid

The HTTP status tells the kind of error: 400 for an invalid request, 403 for a refused one, 500 for a server failure. The body still carries the error object, with its code and message.

Shutdown Endpoint (POST /shutdown)

Auth headers (either one):

  • Authorization: Bearer <token>
  • X-Admin-Token: <token>

Behavior:

  • Token missing, invalid, or no token configured on the server → 403, error.code=Unauthorized.
  • Accepted → 202 with status=accepted, timeout_ms and message. The server stops accepting new requests and lets in-flight requests finish, up to --shutdown-timeout-ms (indefinitely when 0).
  • Shutdown already in progress → 202 with message: "Shutdown already in progress.".

Example: Analysis Request

curl -X POST http://127.0.0.1:8080/api \
  -H "Content-Type: application/json" \
  -d '{
    "proto": "coretrace-1.0",
    "id": 1,
    "type": "request",
    "method": "run_analysis",
    "params": {
      "input": ["./tests/buffer_overflow.cc"],
      "entry_points": ["main"],
      "static_analysis": true,
      "invoke": ["cppcheck", "ctrace_stack_analyzer"],
      "sarif_format": true,
      "fail_on": "warning",
      "report_file": "ctrace-report.txt",
      "verbose": true
    }
  }'

Reading the answer in a CI client:

# 0/1/2/3, the same verdict the CLI would exit with
jq -r '.result.gate.exit_code' response.json
jq -r '.result.diagnostics_summary_total' response.json

Example: Parallel Scheduling (jobs)

jobs sets how many tool runs go at the same time (0, the default, is one per core; 1 runs them one after another). It does not create a background job API: the response is still returned synchronously. async, its former spelling, is deprecated.

curl -X POST http://127.0.0.1:8080/api \
  -H "Content-Type: application/json" \
  -d '{
    "proto": "coretrace-1.0",
    "id": 2,
    "type": "request",
    "method": "run_analysis",
    "params": {
      "input": "./tests/buffer_overflow.cc,./tests/null_pointer.c",
      "static_analysis": true,
      "invoke": ["flawfinder", "tscancode"],
      "jobs": 4
    }
  }'

Example: Shutdown

curl -i -X POST http://127.0.0.1:8080/shutdown \
  -H "Authorization: Bearer mytoken"

Back to Home