Skip to main content
The hitspec server exposes a REST API on http://localhost:8080 (default) when you run hitspec serve. All endpoints are prefixed with /api/v1. Responses are JSON with Content-Type: application/json.
hitspec serve --port 8080

Error Format

All error responses follow a consistent structure:
{
  "error": "Bad Request",
  "message": "file is required"
}
FieldTypeDescription
errorstringHTTP status text (e.g., "Bad Request", "Not Found")
messagestringHuman-readable error detail

Workspace & Files

Get Workspace Overview

Returns the workspace file tree, total request count, active environment, and whether a config file exists.
curl http://localhost:8080/api/v1/workspace
Response 200 OK
{
  "root": "/Users/you/project",
  "files": [
    {
      "path": "tests",
      "name": "tests",
      "dir": "",
      "isDir": true,
      "children": [
        {
          "path": "tests/api.http",
          "name": "api.http",
          "dir": "tests",
          "isDir": false,
          "requestCount": 5
        }
      ]
    },
    {
      "path": "smoke.http",
      "name": "smoke.http",
      "dir": "",
      "isDir": false,
      "requestCount": 3
    }
  ],
  "totalRequests": 8,
  "environment": "dev",
  "hasConfig": true
}

List Files

Returns a flat list of all .http and .hitspec files in the workspace with metadata.
curl http://localhost:8080/api/v1/files
Response 200 OK
[
  {
    "path": "/Users/you/project/tests/api.http",
    "relativePath": "tests/api.http",
    "name": "api.http",
    "size": 1234,
    "modTime": "2026-02-10T12:00:00Z",
    "requestCount": 5
  }
]

Get Parsed File

Returns the fully parsed content of a single .http or .hitspec file, including all requests, variables, assertions, and captures.
curl http://localhost:8080/api/v1/files/tests/api.http
path
string
required
Relative path to the file within the workspace. Uses wildcard path matching ({path...}).
Response 200 OK
{
  "path": "tests/api.http",
  "variables": [
    { "name": "baseUrl", "value": "http://localhost:3000", "line": 1 }
  ],
  "requests": [
    {
      "name": "Get Users",
      "description": "Fetch all users",
      "tags": ["users"],
      "method": "GET",
      "url": "{{baseUrl}}/users",
      "headers": [
        { "key": "Accept", "value": "application/json", "line": 5 }
      ],
      "queryParams": [
        { "key": "limit", "value": "10", "line": 6 }
      ],
      "assertions": [
        { "subject": "status", "operator": "equals", "expected": 200, "line": 8 }
      ],
      "captures": [
        { "name": "userId", "source": "body", "path": "$.data[0].id", "line": 9 }
      ],
      "line": 3,
      "metadata": {
        "timeout": 5000,
        "retry": 2,
        "depends": ["Auth Login"]
      }
    }
  ]
}

Get Raw File Content

Returns the raw text content of a file. Use this for source editing.
curl http://localhost:8080/api/v1/files/raw/tests/api.http
path
string
required
Relative path to the file within the workspace.
Response 200 OK with Content-Type: text/plain
@baseUrl = https://api.example.com

### Get Users
GET {{baseUrl}}/users

Create File

Create a new .http or .hitspec file in the workspace.
curl -X POST http://localhost:8080/api/v1/files \
  -H "Content-Type: application/json" \
  -d '{"path": "tests/new-api.http", "content": "### Health Check\nGET https://api.example.com/health\n"}'
Request Body
{
  path: string;      // Required. Relative path for the new file
  content?: string;  // Optional. Initial file content
}
path
string
required
Relative path for the new file. Must end in .http or .hitspec and be within the workspace.
Response 201 Created
{ "path": "tests/new-api.http" }

Save File

Save raw text content to an existing file. The file watcher suppresses the corresponding change notification to prevent UI reload loops.
curl -X PUT http://localhost:8080/api/v1/files/tests/api.http \
  -H "Content-Type: text/plain" \
  -d '@baseUrl = https://api.example.com

### Get Users
GET {{baseUrl}}/users
'
path
string
required
Relative path to the file within the workspace.
Request Body: Raw file content as text/plain. Response 200 OK
{ "path": "tests/api.http" }

Delete File

Delete a .http or .hitspec file from the workspace.
curl -X DELETE http://localhost:8080/api/v1/files/tests/old-api.http
path
string
required
Relative path to the file within the workspace.
Response 204 No Content

Execution

Execute Request

Execute one or more requests from a specific file. When requestName is provided, only that request runs (filtered by name). When omitted, all requests in the file execute. Real-time progress is broadcast over the WebSocket connection during execution.
curl -X POST http://localhost:8080/api/v1/execute \
  -H "Content-Type: application/json" \
  -d '{"file": "tests/api.http", "requestName": "Get Users", "environment": "dev"}'
Request Body
{
  file: string;          // Required. Relative path to the .http/.hitspec file
  requestName?: string;  // Optional. Filter to a single request by name
  environment?: string;  // Optional. Override the active environment
}
file
string
required
Relative path to the .http or .hitspec file within the workspace.
requestName
string
Name of a specific request to execute. When omitted, all requests in the file are executed.
environment
string
Environment name to use for variable interpolation. Overrides the server’s active environment.
Response 200 OK
{
  "file": "tests/api.http",
  "duration": 245,
  "passed": 1,
  "failed": 0,
  "skipped": 0,
  "results": [
    {
      "name": "Get Users",
      "description": "Fetch all users",
      "passed": true,
      "duration": 245,
      "request": {
        "method": "GET",
        "url": "http://localhost:3000/users",
        "headers": { "Accept": "application/json" }
      },
      "response": {
        "statusCode": 200,
        "status": "200 OK",
        "headers": { "Content-Type": "application/json" },
        "body": "{\"data\":[{\"id\":1,\"name\":\"Alice\"}]}",
        "duration": 243,
        "size": 42
      },
      "assertions": [
        {
          "subject": "status",
          "operator": "equals",
          "expected": 200,
          "actual": 200,
          "passed": true
        }
      ],
      "captures": { "userId": 1 }
    }
  ]
}

Run File

Run all requests in a file. Similar to execute but always runs every request (no name filter).
curl -X POST http://localhost:8080/api/v1/run \
  -H "Content-Type: application/json" \
  -d '{"file": "tests/api.http", "environment": "staging"}'
Request Body
{
  file: string;          // Required. Relative path to the file
  environment?: string;  // Optional. Override the active environment
}
file
string
required
Relative path to the .http or .hitspec file within the workspace.
environment
string
Environment name to use. Overrides the server’s active environment.
Response 200 OK — same RunResultDTO structure as the Execute Request endpoint.

Environments

List Environments

Returns all environments defined in hitspec.yaml, including the currently active environment.
curl http://localhost:8080/api/v1/environments
Response 200 OK
[
  {
    "name": "dev",
    "variables": {
      "baseUrl": "http://localhost:3000",
      "token": "dev-token"
    }
  },
  {
    "name": "staging",
    "variables": {
      "baseUrl": "https://staging.api.example.com",
      "token": "staging-token"
    }
  }
]

Set Active Environment

Switch the server’s active environment. Broadcasts an environment_changed event over WebSocket.
curl -X PUT http://localhost:8080/api/v1/environments/active \
  -H "Content-Type: application/json" \
  -d '{"name": "staging"}'
Request Body
{
  name: string;  // Required. Environment name to activate
}
name
string
required
The name of the environment to set as active.
Response 204 No Content

Get Environment

Get the variables for a specific environment.
curl http://localhost:8080/api/v1/environments/dev
name
string
required
Environment name.
Response 200 OK
{
  "name": "dev",
  "variables": {
    "baseUrl": "http://localhost:3000",
    "token": "dev-token"
  }
}

Update Environment

Create or update the variables for a named environment.
curl -X PUT http://localhost:8080/api/v1/environments/dev \
  -H "Content-Type: application/json" \
  -d '{"variables": {"baseUrl": "http://localhost:4000", "token": "new-token"}}'
name
string
required
Environment name.
Request Body
{
  variables: Record<string, any>;  // Key-value pairs of environment variables
}
variables
object
required
Map of variable names to values for this environment.
Response 200 OK
{
  "name": "dev",
  "variables": {
    "baseUrl": "http://localhost:4000",
    "token": "new-token"
  }
}

Config

Get Configuration

Returns the current hitspec.yaml configuration. Returns an empty object if no config file is present.
curl http://localhost:8080/api/v1/config
Response 200 OK
{
  "defaultEnvironment": "dev",
  "timeout": 30000,
  "retries": 0,
  "followRedirects": true,
  "validateSSL": true,
  "proxy": "",
  "headers": {
    "User-Agent": "hitspec/1.0"
  },
  "parallel": false,
  "concurrency": 5
}

Update Configuration

Partially update the server configuration. Only provided fields are updated; omitted fields remain unchanged. Changes are persisted to the hitspec.yaml config file on disk. If no config file exists, one is created in the workspace root.
curl -X PUT http://localhost:8080/api/v1/config \
  -H "Content-Type: application/json" \
  -d '{"timeout": 60000, "parallel": true, "concurrency": 10}'
Request Body
{
  defaultEnvironment?: string;
  timeout?: number;              // Milliseconds
  retries?: number;
  followRedirects?: boolean;
  validateSSL?: boolean;
  proxy?: string;
  headers?: Record<string, string>;
  parallel?: boolean;
  concurrency?: number;
}
timeout
number
Request timeout in milliseconds. Must be greater than 0.
retries
number
Number of automatic retries on failure. Must be greater than 0.
followRedirects
boolean
Whether to follow HTTP 3xx redirects.
validateSSL
boolean
Whether to validate SSL/TLS certificates.
proxy
string
HTTP proxy URL (e.g., http://proxy:8080).
parallel
boolean
Whether to run independent requests in parallel.
concurrency
number
Maximum number of concurrent requests in parallel mode. Must be greater than 0.
Response 200 OK — returns the updated configuration object.

History

hitspec maintains two layers of history: a lightweight in-memory history for the current session and a persistent SQLite-backed history stored at ~/.hitspec/history.db.

Get In-Memory History

Returns the in-memory execution history for the current server session.
curl http://localhost:8080/api/v1/history
Response 200 OK
[
  {
    "id": "a1b2c3d4",
    "file": "tests/api.http",
    "requestName": "Get Users",
    "method": "GET",
    "url": "http://localhost:3000/users",
    "statusCode": 200,
    "duration": 245,
    "passed": true,
    "timestamp": "2026-02-10T12:00:00Z"
  }
]

Clear In-Memory History

Clear all in-memory history entries.
curl -X DELETE http://localhost:8080/api/v1/history
Response 204 No Content

List Persistent Runs

Returns paginated persistent run history from the SQLite database.
curl "http://localhost:8080/api/v1/history/runs?limit=20&offset=0"
limit
number
default:"20"
Number of runs to return. Maximum 100.
offset
number
default:"0"
Number of runs to skip for pagination.
Response 200 OK
{
  "runs": [
    {
      "id": 42,
      "filePath": "tests/api.http",
      "environment": "dev",
      "startedAt": "2026-02-10T12:00:00Z",
      "finishedAt": "2026-02-10T12:00:01Z",
      "durationMs": 1200,
      "passed": 5,
      "failed": 0,
      "skipped": 1,
      "total": 6
    }
  ],
  "total": 150,
  "limit": 20,
  "offset": 0
}

Get Run Details

Returns a single run with its full results and assertion details.
curl http://localhost:8080/api/v1/history/runs/42
id
number
required
Numeric run ID.
Response 200 OK
{
  "id": 42,
  "filePath": "tests/api.http",
  "environment": "dev",
  "startedAt": "2026-02-10T12:00:00Z",
  "finishedAt": "2026-02-10T12:00:01Z",
  "durationMs": 1200,
  "passed": 5,
  "failed": 0,
  "skipped": 1,
  "total": 6,
  "results": [
    {
      "id": 101,
      "requestName": "Get Users",
      "method": "GET",
      "url": "http://localhost:3000/users",
      "statusCode": 200,
      "durationMs": 243,
      "passed": true,
      "description": "Fetch all users",
      "bodyPreview": "{\"data\":[{\"id\":1,\"name\":\"Alice\"}]}",
      "assertions": [
        {
          "id": 201,
          "operator": "equals",
          "subject": "status",
          "expected": "200",
          "actual": "200",
          "passed": true
        }
      ]
    }
  ]
}

Delete a Run

Delete a specific run and all its associated results and assertions (cascade delete).
curl -X DELETE http://localhost:8080/api/v1/history/runs/42
id
number
required
Numeric run ID.
Response 204 No Content

Delete All Runs

Delete all persistent run history.
curl -X DELETE http://localhost:8080/api/v1/history/runs
Response 204 No Content

List Results by Request Name

Retrieve historical results for a specific request, filtered by file path. Useful for comparing how a single request’s responses have changed over time. Results are ordered by run start time (newest first).
curl "http://localhost:8080/api/v1/history/results?requestName=GetUsers&filePath=api.http&limit=20&offset=0"
requestName
string
required
The name of the request to look up.
filePath
string
required
The file path containing the request.
limit
number
default:"20"
Maximum number of results to return (1–100).
offset
number
default:"0"
Number of results to skip for pagination.
Response 200 OK
{
  "results": [
    {
      "id": 101,
      "runId": 42,
      "requestName": "GetUsers",
      "method": "GET",
      "url": "https://api.example.com/users",
      "statusCode": 200,
      "durationMs": 134,
      "passed": true,
      "skipped": false,
      "error": null,
      "bodyPreview": "{\"users\": [...]}",
      "filePath": "api.http",
      "environment": "staging",
      "runStartedAt": "2026-02-19T15:30:00Z",
      "assertions": []
    }
  ],
  "total": 15,
  "limit": 20,
  "offset": 0
}

Stress Testing

Start Stress Test

Start a load test against the requests defined in one or more files. Metrics are broadcast in real time over the WebSocket connection via stress_update messages.
curl -X POST http://localhost:8080/api/v1/stress/start \
  -H "Content-Type: application/json" \
  -d '{
    "files": ["tests/api.http"],
    "duration": "30s",
    "rate": 50,
    "vus": 10,
    "maxVUs": 20
  }'
Request Body
{
  files: string[];       // Required. List of .http/.hitspec files (relative paths)
  duration: string;      // Required. Go duration string (e.g., "30s", "5m", "1h")
  rate?: number;         // Optional. Target requests per second
  vus?: number;          // Optional. Number of virtual users (switches to VU mode)
  maxVUs?: number;       // Optional. Maximum concurrent virtual users
}
files
string[]
required
List of .http or .hitspec file paths relative to the workspace.
duration
string
required
Duration of the stress test as a Go duration string (e.g., "30s", "5m", "1h").
rate
number
Target requests per second in rate mode.
vus
number
Number of virtual users. Setting this switches from rate mode to VU mode.
maxVUs
number
Maximum number of concurrent virtual users.
Response 200 OK
{ "status": "started" }
Error 409 Conflict if a stress test is already running.

Stop Stress Test

Stop a running stress test. If no test is currently running, the endpoint returns 200 OK with an "already_stopped" status instead of an error.
curl -X POST http://localhost:8080/api/v1/stress/stop
Response 200 OK
{ "status": "stopping" }
When no test is running:
{ "status": "already_stopped" }

Get Stress Test Status

Returns whether a stress test is running and, if so, the current metrics.
curl http://localhost:8080/api/v1/stress/status
Response 200 OK
{
  "running": true,
  "elapsed": 15.3,
  "stats": {
    "total": 750,
    "success": 745,
    "errors": 5,
    "rps": 49.8,
    "p50Ms": 12.5,
    "p95Ms": 45.2,
    "p99Ms": 120.0,
    "maxMs": 350.0,
    "errorRate": 0.0067,
    "activeVUs": 10
  }
}
When no stress test is running:
{ "running": false, "elapsed": 0, "stats": null }

Get Stress Test Result

Returns the result of the last completed stress test, including summary metrics, latency percentiles, and per-request breakdown.
curl http://localhost:8080/api/v1/stress/result
Response 200 OK
{
  "duration": 30.0,
  "totalRequests": 1500,
  "successCount": 1485,
  "errorCount": 15,
  "avgRps": 50.0,
  "latency": {
    "min": 2.1,
    "max": 350.0,
    "mean": 25.3,
    "stddev": 18.7,
    "p50": 12.5,
    "p95": 45.2,
    "p99": 120.0
  },
  "thresholds": [
    { "metric": "p95", "threshold": "200ms", "actual": 45.2, "passed": true },
    { "metric": "errors", "threshold": "1%", "actual": 1.0, "passed": true }
  ],
  "perRequest": [
    {
      "name": "Get Users",
      "count": 750,
      "successCount": 745,
      "errorCount": 5,
      "avgMs": 22.1,
      "minMs": 2.1,
      "maxMs": 200.0,
      "p50Ms": 11.0,
      "p95Ms": 40.0,
      "p99Ms": 100.0
    }
  ]
}
When no result is available:
{ "error": "Not Found", "message": "no stress test result available" }

List Stress Profiles

Returns the stress test profiles defined in hitspec.yaml.
curl http://localhost:8080/api/v1/stress/profiles
Response 200 OK
[
  {
    "name": "smoke",
    "duration": "10s",
    "rate": 5
  },
  {
    "name": "load",
    "duration": "5m",
    "rate": 100,
    "thresholds": {
      "p95": "200ms",
      "errors": "1%"
    }
  },
  {
    "name": "spike",
    "duration": "2m",
    "vus": 200,
    "maxVUs": 500,
    "rampUp": "30s",
    "thinkTime": "500ms"
  }
]

Create Stress Profile

Create a new stress profile. The profile is persisted to hitspec.yaml.
curl -X POST http://localhost:8080/api/v1/stress/profiles \
  -H "Content-Type: application/json" \
  -d '{
    "name": "smoke",
    "duration": "30s",
    "rate": 10,
    "maxVUs": 5
  }'
Request Body
{
  name: string;           // Required. Unique profile name
  duration: string;       // Required. Go duration string (e.g., "30s", "5m")
  rate?: number;          // Optional. Target requests per second
  vus?: number;           // Optional. Number of virtual users
  maxVUs?: number;        // Optional. Maximum concurrent virtual users
  rampUp?: string;        // Optional. Ramp-up duration
  thinkTime?: string;     // Optional. Think time between requests per VU
  thresholds?: {          // Optional. Pass/fail thresholds
    p95?: string;
    p99?: string;
    errors?: string;
  };
}
name
string
required
Unique name for the profile. Must not conflict with an existing profile.
duration
string
required
Duration of the stress test as a Go duration string.
Response 201 Created
{ "name": "smoke" }
Error 409 Conflict if a profile with the same name already exists.

Update Stress Profile

Update an existing stress profile. The changes are persisted to hitspec.yaml.
curl -X PUT http://localhost:8080/api/v1/stress/profiles/smoke \
  -H "Content-Type: application/json" \
  -d '{"duration": "1m", "rate": 20, "maxVUs": 10}'
name
string
required
Name of the profile to update.
Request Body: Same fields as Create Stress Profile (except name). Response 200 OK
{ "name": "smoke" }
Error 404 Not Found if the profile does not exist.

Delete Stress Profile

Delete a stress profile. The deletion is persisted to hitspec.yaml.
curl -X DELETE http://localhost:8080/api/v1/stress/profiles/smoke
name
string
required
Name of the profile to delete.
Response 204 No Content Error 404 Not Found if the profile does not exist.

Mock Server

Start Mock Server

Start a mock server that serves responses based on the request/response pairs defined in your .http files. Incoming requests to the mock server are broadcast over WebSocket as mock_request events.
curl -X POST http://localhost:8080/api/v1/mock/start \
  -H "Content-Type: application/json" \
  -d '{"files": ["mocks/users.http"], "port": 3000, "delay": "100ms"}'
Request Body
{
  files: string[];    // Required. List of .http/.hitspec files with mock definitions
  port?: number;      // Optional. Port for the mock server (default: 3000)
  delay?: string;     // Optional. Artificial response delay (Go duration, e.g., "100ms")
}
files
string[]
required
List of .http or .hitspec file paths containing request/response pairs.
port
number
default:"3000"
Port on which the mock server will listen.
delay
string
Artificial delay before each response, as a Go duration string (e.g., "100ms", "1s").
Response 200 OK
{
  "running": true,
  "port": 3000,
  "routes": [
    {
      "method": "GET",
      "path": "/users",
      "name": "Get Users",
      "statusCode": 200,
      "contentType": "application/json"
    },
    {
      "method": "POST",
      "path": "/users",
      "name": "Create User",
      "statusCode": 201,
      "contentType": "application/json"
    }
  ]
}
Error 409 Conflict if a mock server is already running.

Stop Mock Server

Stop the running mock server.
curl -X POST http://localhost:8080/api/v1/mock/stop
Response 200 OK
{ "status": "stopping" }

Get Mock Routes

Returns the current status and registered routes of the mock server.
curl http://localhost:8080/api/v1/mock/routes
Response 200 OK (when running)
{
  "running": true,
  "port": 3000,
  "routes": [
    {
      "method": "GET",
      "path": "/users",
      "name": "Get Users",
      "statusCode": 200,
      "contentType": "application/json"
    }
  ]
}
Response 200 OK (when not running)
{ "running": false }

Contract Testing

Verify Contracts

Run contract verification against a live provider. Sends each request defined in the contract files to the provider URL and validates the responses match expectations.
curl -X POST http://localhost:8080/api/v1/contract/verify \
  -H "Content-Type: application/json" \
  -d '{
    "providerUrl": "http://localhost:3000",
    "stateHandler": "http://localhost:3000/_state",
    "files": ["contracts/users.http"]
  }'
Request Body
{
  providerUrl: string;      // Required. Base URL of the provider to verify against
  stateHandler?: string;    // Optional. URL for provider state setup endpoint
  files?: string[];         // Optional. Specific contract files (defaults to all workspace files)
}
providerUrl
string
required
The base URL of the provider service to verify contracts against.
stateHandler
string
URL of an endpoint that accepts state setup requests before each interaction.
files
string[]
List of contract file paths. When omitted, all .http/.hitspec files in the workspace are used.
Response 200 OK
[
  {
    "file": "contracts/users.http",
    "passed": 3,
    "failed": 0,
    "skipped": 0,
    "duration": 450,
    "results": [
      {
        "name": "Get Users",
        "provider": "UserService",
        "state": "users exist",
        "passed": true,
        "duration": 150
      },
      {
        "name": "Create User",
        "provider": "UserService",
        "state": "no users",
        "passed": true,
        "duration": 200
      }
    ]
  }
]

List Contract Files

Returns all .http/.hitspec files in the workspace that can be used as contract files.
curl http://localhost:8080/api/v1/contract/files
Response 200 OK
{
  "files": [
    "contracts/users.http",
    "contracts/orders.http",
    "tests/api.http"
  ]
}

Recording Proxy

Start Recording

Start a recording proxy that captures HTTP traffic passing through it. The proxy forwards requests to the target URL and records both request and response.
curl -X POST http://localhost:8080/api/v1/record/start \
  -H "Content-Type: application/json" \
  -d '{
    "targetUrl": "http://localhost:3000",
    "port": 8081,
    "deduplicate": true
  }'
Request Body
{
  targetUrl: string;       // Required. URL to proxy requests to
  port?: number;           // Optional. Proxy listen port (default: 8081)
  deduplicate?: boolean;   // Optional. Remove duplicate request recordings
  exclude?: string[];      // Optional. URL patterns to exclude from recording
  sanitize?: string[];     // Optional. Header names to sanitize in recordings
}
targetUrl
string
required
The upstream URL that the proxy forwards requests to.
port
number
default:"8081"
Port on which the recording proxy will listen.
deduplicate
boolean
default:"false"
When true, duplicate requests with the same method and path are only recorded once.
exclude
string[]
List of URL path patterns to exclude from recording.
sanitize
string[]
List of header names whose values should be sanitized (replaced with placeholders) in the recorded output.
Response 200 OK
{
  "status": "started",
  "port": 8081
}
Error 409 Conflict if a recording proxy is already running.

Stop Recording

Stop the recording proxy.
curl -X POST http://localhost:8080/api/v1/record/stop
Response 200 OK
{ "status": "stopping" }

Get Recording Status

Returns whether the recording proxy is running, how many requests have been captured, and the captured request details.
curl http://localhost:8080/api/v1/record/status
Response 200 OK (when running)
{
  "running": true,
  "targetUrl": "http://localhost:3000",
  "port": 8081,
  "count": 12,
  "recordings": [
    {
      "method": "GET",
      "path": "/users",
      "url": "http://localhost:3000/users",
      "contentType": "application/json",
      "statusCode": 200,
      "duration": 45
    },
    {
      "method": "POST",
      "path": "/users",
      "url": "http://localhost:3000/users",
      "contentType": "application/json",
      "statusCode": 201,
      "duration": 67
    }
  ]
}
Response 200 OK (when not running)
{ "running": false, "count": 0 }

Export Recordings

Export all captured recordings as .http file content. The proxy must be running.
curl -X POST http://localhost:8080/api/v1/record/export
Response 200 OK
{
  "content": "### Get Users\nGET http://localhost:3000/users\nAccept: application/json\n\n### Create User\nPOST http://localhost:3000/users\nContent-Type: application/json\n\n{\"name\": \"Alice\"}\n"
}

Clear Recordings

Clear all captured recordings without stopping the proxy.
curl -X DELETE http://localhost:8080/api/v1/record/clear
Response 200 OK
{ "status": "cleared" }

Import

Import curl

Convert a curl command or a file containing curl commands into .http format.
# From a command string
curl -X POST http://localhost:8080/api/v1/import/curl \
  -H "Content-Type: application/json" \
  -d '{"command": "curl -X GET https://api.example.com/users -H \"Authorization: Bearer token\""}'

# From a file
curl -X POST http://localhost:8080/api/v1/import/curl \
  -H "Content-Type: application/json" \
  -d '{"filePath": "exports/commands.sh"}'
Request Body
{
  command?: string;    // A curl command string to convert
  filePath?: string;   // Path to a file containing curl commands (relative to workspace)
}
One of command or filePath is required.
command
string
A curl command string to convert to .http format.
filePath
string
Path to a file containing curl commands, relative to the workspace.
Response 200 OK
{
  "content": "### Imported Request\nGET https://api.example.com/users\nAuthorization: Bearer token\n",
  "requestCount": 1
}

Import Insomnia

Convert an Insomnia export (JSON) into .http format.
# From inline JSON data
curl -X POST http://localhost:8080/api/v1/import/insomnia \
  -H "Content-Type: application/json" \
  -d '{"data": "{\"_type\":\"export\",\"resources\":[...]}"}'

# From a file
curl -X POST http://localhost:8080/api/v1/import/insomnia \
  -H "Content-Type: application/json" \
  -d '{"filePath": "insomnia-export.json"}'
Request Body
{
  data?: string;       // Insomnia export JSON as a string
  filePath?: string;   // Path to an Insomnia export file (relative to workspace)
}
One of data or filePath is required.
data
string
Insomnia export JSON content as a string.
filePath
string
Path to an Insomnia JSON export file, relative to the workspace.
Response 200 OK
{
  "content": "### Get Users\nGET https://api.example.com/users\n\n### Create User\nPOST https://api.example.com/users\nContent-Type: application/json\n\n{\"name\":\"Alice\"}\n",
  "requestCount": 2
}

Import OpenAPI

Convert an OpenAPI specification (YAML or JSON, v2 or v3) into .http format. The spec can be a local file path or a URL.
# From a local file
curl -X POST http://localhost:8080/api/v1/import/openapi \
  -H "Content-Type: application/json" \
  -d '{"specPath": "openapi.yaml", "baseUrl": "http://localhost:3000"}'

# From a URL
curl -X POST http://localhost:8080/api/v1/import/openapi \
  -H "Content-Type: application/json" \
  -d '{"specPath": "https://petstore.swagger.io/v2/swagger.json"}'
Request Body
{
  specPath: string;    // Required. Path or URL to the OpenAPI spec
  baseUrl?: string;    // Optional. Override the base URL in the spec
}
specPath
string
required
Path to the OpenAPI specification file (relative to workspace) or a URL. Supports YAML and JSON, OpenAPI v2 and v3.
baseUrl
string
Override the base URL from the spec. Useful when the spec references a production URL but you want to target localhost.
Response 200 OK
{
  "content": "### List Pets\nGET http://localhost:3000/pets\n\n### Create Pet\nPOST http://localhost:3000/pets\nContent-Type: application/json\n\n{\"name\":\"Fido\",\"tag\":\"dog\"}\n",
  "requestCount": 2
}

Export

Export as curl

Convert requests from a .http/.hitspec file into curl commands.
# Export all requests in a file
curl -X POST http://localhost:8080/api/v1/export/curl \
  -H "Content-Type: application/json" \
  -d '{"file": "tests/api.http"}'

# Export a specific request
curl -X POST http://localhost:8080/api/v1/export/curl \
  -H "Content-Type: application/json" \
  -d '{"file": "tests/api.http", "requestName": "Create User"}'
Request Body
{
  file: string;            // Required. Relative path to the file
  requestName?: string;    // Optional. Export only this named request
}
file
string
required
Relative path to the .http or .hitspec file in the workspace.
requestName
string
Name of a specific request to export. When omitted, all requests are exported.
Response 200 OK
{
  "commands": [
    "curl -X GET 'http://localhost:3000/users' -H 'Accept: application/json'",
    "curl -X POST 'http://localhost:3000/users' -H 'Content-Type: application/json' -d '{\"name\":\"Alice\"}'"
  ]
}

System

Get System Info

Returns version, build time, Go version, and platform information.
curl http://localhost:8080/api/v1/system/info
Response 200 OK
{
  "version": "2.6.0",
  "buildTime": "2026-02-10T12:00:00Z",
  "goVersion": "go1.25.0",
  "os": "darwin",
  "arch": "arm64"
}

WebSocket

Connect

Establish a WebSocket connection for real-time event streaming. The server pushes events as they occur — no polling required.
ws://localhost:8080/api/v1/ws
The WebSocket endpoint accepts connections from localhost, 127.0.0.1, and [::1] origins only.
Connection Example
const ws = new WebSocket('ws://localhost:8080/api/v1/ws');

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  console.log(msg.type, msg.payload);
};

// Keep alive with ping/pong
setInterval(() => {
  ws.send(JSON.stringify({ type: 'ping' }));
}, 30000);

Message Envelope

All WebSocket messages use this envelope format:
{
  type: string;        // Message type identifier
  payload: any;        // Type-specific payload
  timestamp: string;   // ISO 8601 timestamp (UTC)
}

Message Types

execution_start

Sent when a request execution begins.
{
  "type": "execution_start",
  "payload": {
    "id": "a1b2c3d4",
    "file": "tests/api.http",
    "status": "started",
    "timestamp": "2026-02-10T12:00:00Z"
  },
  "timestamp": "2026-02-10T12:00:00Z"
}

request_progress

Sent for each individual request as it starts and completes during an execution.
{
  "type": "request_progress",
  "payload": {
    "execId": "a1b2c3d4",
    "file": "tests/api.http",
    "requestName": "Get Users",
    "status": "completed",
    "index": 0,
    "total": 3,
    "passed": true,
    "duration": 245,
    "timestamp": "2026-02-10T12:00:00Z"
  },
  "timestamp": "2026-02-10T12:00:00Z"
}
The status field is either "started" or "completed". The passed and duration fields are only present when status is "completed".

execution_complete

Sent when an entire execution finishes. The result payload contains the full RunResultDTO.
{
  "type": "execution_complete",
  "payload": {
    "id": "a1b2c3d4",
    "file": "tests/api.http",
    "status": "completed",
    "result": { "file": "tests/api.http", "duration": 500, "passed": 3, "failed": 0, "skipped": 0, "results": [] },
    "timestamp": "2026-02-10T12:00:00Z"
  },
  "timestamp": "2026-02-10T12:00:00Z"
}

error

Sent when an execution fails with an error.
{
  "type": "error",
  "payload": {
    "id": "a1b2c3d4",
    "file": "tests/api.http",
    "status": "error",
    "error": "parse error: unexpected token at line 5",
    "timestamp": "2026-02-10T12:00:00Z"
  },
  "timestamp": "2026-02-10T12:00:00Z"
}

environment_changed

Sent when the active environment is switched via PUT /api/v1/environments/active.
{
  "type": "environment_changed",
  "payload": {
    "name": "staging",
    "timestamp": "2026-02-10T12:00:00Z"
  },
  "timestamp": "2026-02-10T12:00:00Z"
}

file_changed

Sent when a .http or .hitspec file is created, modified, or deleted in the workspace (via filesystem watcher).
{
  "type": "file_changed",
  "payload": {
    "path": "tests/api.http",
    "operation": "write",
    "timestamp": "2026-02-10T12:00:00Z"
  },
  "timestamp": "2026-02-10T12:00:00Z"
}

stress_update

Sent every 500ms during an active stress test with current metrics. The running and completed booleans indicate the test lifecycle — the UI uses these to detect when a test finishes naturally (without an explicit stop) and transition to the results view.
{
  "type": "stress_update",
  "payload": {
    "running": true,
    "completed": false,
    "stats": {
      "total": 750,
      "success": 745,
      "errors": 5,
      "rps": 49.8,
      "p50Ms": 12.5,
      "p95Ms": 45.2,
      "p99Ms": 120.0,
      "maxMs": 350.0,
      "errorRate": 0.0067,
      "activeVUs": 10
    },
    "elapsed": 15.3,
    "timestamp": "2026-02-10T12:00:00Z"
  },
  "timestamp": "2026-02-10T12:00:00Z"
}

mock_request

Sent when the mock server receives a request, or when it starts/stops.
{
  "type": "mock_request",
  "payload": {
    "event": "request",
    "method": "GET",
    "path": "/users",
    "status": 200,
    "duration": 1.2,
    "timestamp": "2026-02-10T12:00:00Z"
  },
  "timestamp": "2026-02-10T12:00:00Z"
}
The event field can be "started", "stopped", or "request".

ping / pong

Clients can send {"type": "ping"} messages and the server will respond with a pong:
{
  "type": "pong",
  "payload": null,
  "timestamp": "2026-02-10T12:00:00Z"
}