---
title: "One HTTP request to a (private) container port"
method: POST
path: "/preview/nodes/{name}/http"
tags: ["nodes"]
---

# One HTTP request to a (private) container port

`POST /preview/nodes/{name}/http`

## Request

- Base URL: `https://autoresearch.sfcompute.com`
- URL: `https://autoresearch.sfcompute.com/preview/nodes/{name}/http`
- Auth: HTTP bearer

Make ONE HTTP request to a port inside a RUNNING node and get the response back structured, with timing - THE way to test a server you just started (a vLLM /v1/chat/completions, a health check) without shell-quoting a curl payload through run_command: the JSON body rides the `body` parameter verbatim, and the request goes over the platform's own pipe to the port (no expose_port needed; the port stays private). Returns {status, headers, body, body_bytes, truncated, timing_ms: {dial, ttfb, total}}: dial is connection establishment to the port, ttfb is request-sent to response-status, total includes reading the whole body. The body is read to the end (SSE streams included) and capped at 64 KiB (truncated: true past the cap); a non-UTF-8 body arrives base64 as `body_base64`. Budgeted by `timeout` (default 60s, ceiling 300 - a long generation wants more). This tool never wakes a stopped node. A run_command wakes it, and the wake bills. This tests the PORT, not a public URL - it bypasses the ingress edge (no capability check, no bearer), so a 200 here does not prove an exposed endpoint's URL works; curl the minted URL for that. Bulk traffic and load tests belong on an expose_port URL.

## Path parameters

- `name` string, required: Node name (from `list_nodes`).

## Query parameters

- `workspace` string

## Request body

- object
  - `body` string, nullable: Request body, sent verbatim (JSON rides here as a string).
  - `headers` object: Extra request headers (name → value). When a body is present and no Content-Type is given, application/json is assumed.
  - `method` string, nullable: HTTP method (default GET): GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS.
  - `path` string, nullable: Request path, query string included (default "/").
  - `port` integer, required: The container port to send the request to. No expose_port needed: the request rides the platform's own pipe to the port, which stays private.
  - `timeout` integer, nullable: Whole-call budget in seconds: dial + request + reading the response (default 60, ceiling 300). A model still loading or a long generation wants a bigger budget.

## Response `200`

The capability's JSON result.

- Result: The capability's result: the same object the MCP tool returns as structuredContent. Resources carry an `object` type discriminator and an immutable id; money is integer micro-dollars in `*_usd_micros` fields.
  - `object` string: The resource type, when the result is one resource.

## Other responses

- `400`: Malformed request: bad JSON, a parameter that does not parse, or a value outside its range. Code `invalid`.
- `401`: No bearer token, or one this API cannot verify. Code `unauthenticated`.
- `403`: Authenticated, but the token's scopes or the account's role do not reach this operation. The message names the scope word to request. Code `forbidden`.
- `404`: No such route. Code `not_found`; the body names the OpenAPI document.
- `422`: A well-formed request the platform declined: no such node, a cap reached, a state that forbids the move. The message says which, and what to do instead. Code `refused`.
- `429`: Over this door's per-customer budget. Wait `Retry-After` seconds. Code `rate_limited`.
- `500`: Our fault. Retry; if it persists, quote the request-id. Code `internal`.

---

[API](https://skmtc.dev/givemeanode/apis/autoresearch-customer-api.md) · [All operations](https://skmtc.dev/givemeanode/apis/autoresearch-customer-api/llms.txt) · [OpenAPI document](https://skmtc.dev/givemeanode/apis/autoresearch-customer-api/revisions/f88dcb70ac6c?raw)
