Skip to content
Hoody.com

Execute outbound HTTP requests from a Hoody container using libcurl, and stream async job lifecycle events over WebSocket or Server-Sent Events. The POST endpoint exposes the full request surface (retry, proxy, cookie sessions, scheduling, response storage), while the GET endpoint is a quick URL-driven form for simple calls. Subscribe to /api/v1/curl/ws or /api/v1/curl/sse to observe jobs started in async mode, or open the persistent /api/v1/curl/channel WebSocket for multiplexed request dispatch.

Execute an HTTP request using libcurl with comprehensive configuration options. Supports both synchronous (immediate response) and asynchronous (background job) execution modes.

Execution modes:

  • sync (default) — blocks until completion and returns the response in the same call.
  • async — returns a job_id immediately and runs the request in the background.

Response modes:

  • transparent (default) — returns the raw upstream response with original headers.
  • json — wraps the response in JSON with timing metrics and metadata.

This endpoint takes no path, query, or header parameters.

The request body follows the curl_CurlRequest schema. The url field is required; every other field is optional. Unknown fields are rejected (deny_unknown_fields).

FieldTypeRequiredDescription
urlstringYesTarget URL.
methodstringNoHTTP method (for example GET, POST).
modestringNoExecution mode: sync or async.
responsestringNoResponse mode: transparent or json.
headersobjectNoCustom headers keyed by header name.
datastringNoRaw request body.
jsonobjectNoJSON request body of any shape. Sent with Content-Type: application/json.
formobjectNoForm fields keyed by field name.
bearer_tokenstringNoBearer token sent as Authorization: Bearer ....
auth_methodstringNoHTTP authentication method.
auth_userstringNoHTTP authentication username.
auth_passwordstringNoHTTP authentication password.
cookiestringNoCookie header value.
user_agentstringNoUser-Agent header.
refererstringNoReferer header.
follow_redirectsbooleanNoFollow HTTP redirects.
max_redirectsintegerNoMaximum number of redirects to follow.
timeoutintegerNoTotal request timeout (seconds).
connect_timeoutintegerNoConnection timeout (seconds).
insecurebooleanNoSkip TLS verification.
compressedbooleanNoRequest a compressed response.
keepalivebooleanNoEnable TCP keepalive.
keepalive_timeintegerNoTCP keepalive idle time (seconds).
tcp_nodelaybooleanNoDisable Nagle’s algorithm.
proxystringNoProxy URL.
proxy_userstringNoProxy username.
proxy_passwordstringNoProxy password.
cacertstringNoCA certificate path or content.
certstringNoClient certificate path or content.
cert_typestringNoClient certificate type (for example PEM).
keystringNoClient private key.
session_idstringNoReuse cookies from this session ID.
savebooleanNoSave the response body to container storage.
save_pathstringNoRelative save path under downloads/by-job/{job_id}. Must not be absolute or contain ...
job_namestringNoFriendly name for the async job.
schedulestringNoCron expression for recurring execution.
rangestringNoByte range, for example 0-1023.
speed_limitintegerNoDownload speed limit (bytes/sec).
speed_timeintegerNoTime window (seconds) for speed_limit.
max_filesizeintegerNoMaximum response size in bytes.
retry_countintegerNoNumber of retries on failure.
retry_delayintegerNoDelay between retries (seconds).
Terminal window
curl -X POST 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-curl-1.node-us.containers.hoody.com/api/v1/curl/request' \
-H 'Authorization: Bearer <HOODY_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{
"url": "https://api.example.com/v1/posts",
"method": "POST",
"headers": {
"Accept": "application/json"
},
"json": {
"title": "Hello world",
"published": true
},
"mode": "sync",
"response": "json",
"retry_count": 2,
"retry_delay": 1,
"bearer_token": "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
}'
{
"success": true,
"status_code": 201,
"headers": {
"content-type": "application/json; charset=utf-8",
"x-request-id": "req_8f7c2b1a"
},
"body": "{\"id\":\"post_01HMV\",\"title\":\"Hello world\",\"published\":true}",
"is_binary": false,
"job_id": null,
"metadata": {
"content_type": "application/json; charset=utf-8",
"effective_url": "https://api.example.com/v1/posts",
"redirect_count": 0,
"size_download": 58,
"size_upload": 41,
"speed_download": 1284.5,
"speed_upload": 902.3
},
"timing": {
"total": 0.184,
"namelookup": 0.012,
"connect": 0.041,
"pretransfer": 0.044,
"starttransfer": 0.176,
"redirect": 0.0
}
}
FieldTypeRequiredDescription
successbooleanYesWhether the upstream request completed without libcurl errors.
status_codeintegerYesHTTP status code returned by the upstream.
headersobjectYesResponse headers keyed by header name.
bodystringYesUTF-8 text for text responses, or base64 when is_binary is true.
is_binarybooleanYestrue when body is base64-encoded; false when it is plain UTF-8.
job_idstringNoJob ID when the request was executed asynchronously.
metadataobjectYesPer-response metadata — see curl_ResponseMetadata.
timingobjectYesPer-response timing — see curl_ResponseTiming.

Execute a simple HTTP request using URL query parameters. Best suited for quick GET requests and one-off tests. For advanced features (retry, schedule, proxy, cookie sessions) use the POST endpoint.

NameInTypeRequiredDescription
urlquerystringYesTarget URL (required)
methodquerystringNoHTTP method (default: GET)
responsequerystringNoResponse mode: transparent or json (default: json)
modequerystringNoExecution mode: sync or async (default: sync)
session_idquerystringNoSession ID for cookie persistence
follow_redirectsquerybooleanNoFollow redirects (default: true)
timeoutqueryintegerNoTimeout in seconds
user_agentquerystringNoUser-Agent header
refererquerystringNoReferer header
bearer_tokenquerystringNoBearer token
savequerybooleanNoSave to storage
save_pathquerystringNoCustom save path, relative to downloads/by-job/{job_id}. No absolute paths or ..
insecurequerybooleanNoAllow insecure SSL
compressedquerybooleanNoRequest compressed
job_namequerystringNoJob name for async
dataquerystringNoRaw request body (curl --data); alias body; presence upgrades default method to POST
jsonquerystringNoJSON request body, sent with Content-Type: application/json (curl --json); upgrades default method to POST
headerqueryarrayNoCustom header as Name: Value. Repeatable — supply once per header
data_base64querystringNoBase64 request body (binary-safe; standard or URL-safe); alias body_base64. Takes precedence over data/json; upgrades default method to POST
Terminal window
curl 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-curl-1.node-us.containers.hoody.com/api/v1/curl/request?url=https%3A%2F%2Fapi.example.com%2Fposts%2F42&method=GET&response=json' \
-H 'Authorization: Bearer <HOODY_TOKEN>'
{
"success": true,
"status_code": 200,
"headers": {
"content-type": "application/json"
},
"body": "{\"id\":42,\"title\":\"Hello world\"}",
"is_binary": false,
"job_id": null,
"metadata": {
"content_type": "application/json",
"effective_url": "https://api.example.com/posts/42",
"redirect_count": 0,
"size_download": 30,
"size_upload": 0,
"speed_download": 950.2,
"speed_upload": 0
},
"timing": {
"total": 0.092,
"namelookup": 0.008,
"connect": 0.034,
"pretransfer": 0.036,
"starttransfer": 0.088,
"redirect": 0.0
}
}

Establish a WebSocket connection that streams async job lifecycle events as JSON messages. Use this for live progress updates of jobs created via the execution endpoints.

Messages:

  • jobstarted{job_id, name}
  • jobprogress{job_id, progress} (progress is a fraction in the range 0 to 1, inclusive)
  • jobcompleted{job_id, status}
  • error{message}

Pass ?job_id= to receive events for a single job only.

NameInTypeRequiredDescription
job_idquerystringNoOptional job ID filter
Terminal window
curl --include --no-buffer \
-H 'Connection: Upgrade' \
-H 'Upgrade: websocket' \
-H 'Sec-WebSocket-Version: 13' \
-H 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==' \
'https://67e89abc123def456789abcd-890abcdef12345678901cdef-curl-1.node-us.containers.hoody.com/api/v1/curl/ws?job_id=01HMZ8X9K2QF3N5P7R8T6V4WYD'
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

Establish a Server-Sent Events connection for job lifecycle events. Each event is delivered as a standard SSE frame with event: set to the message type and data: containing the JSON payload.

Events:

  • jobstarted{job_id, name}
  • jobprogress{job_id, progress}
  • jobcompleted{job_id, status}
  • error{message}
  • lagged{missed} (emitted if the broadcast subscriber falls behind)

Pass ?job_id= to receive events for a single job only. The Last-Event-Id header is accepted for spec compliance but ignored — there is no replay buffer.

The connection counts against the global SSE concurrency cap. When exhausted the server returns 503.

NameInTypeRequiredDescription
job_idquerystringNoOptional job ID filter
Terminal window
curl --no-buffer \
-H 'Accept: text/event-stream' \
-H 'Authorization: Bearer <HOODY_TOKEN>' \
'https://67e89abc123def456789abcd-890abcdef12345678901cdef-curl-1.node-us.containers.hoody.com/api/v1/curl/sse?job_id=01HMZ8X9K2QF3N5P7R8T6V4WYD'
event: jobstarted
data: {"job_id":"01HMZ8X9K2QF3N5P7R8T6V4WYD","name":"nightly-export"}
event: jobprogress
data: {"job_id":"01HMZ8X9K2QF3N5P7R8T6V4WYD","progress":0.42}
event: jobcompleted
data: {"job_id":"01HMZ8X9K2QF3N5P7R8T6V4WYD","status":"success"}

Establish a persistent WebSocket channel for multiplexed, validated CurlRequest execution. The server validates each request before dispatching.

This endpoint is separate from /api/v1/curl/ws, which only streams async job lifecycle events.

NameInTypeRequiredDescription
max_concurrentqueryintegerNoAlias for max concurrent streams on this channel connection
max_concurrent_streamsqueryintegerNoMaximum concurrently executing streams on this channel connection
max_poolqueryintegerNoAlias for max_concurrent; does not configure outbound libcurl connection pooling
max_queuequeryintegerNoMaximum queued streams waiting for a per-connection execution slot
max_frame_bytesqueryintegerNoMaximum inbound WebSocket text frame size in bytes
max_request_bytesqueryintegerNoMaximum assembled request JSON size in bytes
chunk_bytesqueryintegerNoMaximum upstream response bytes encoded into one channel body frame
stream_timeout_secsqueryintegerNoPer-stream execution timeout in seconds
idle_timeout_secsqueryintegerNoIdle channel timeout in seconds
max_outbound_messagesqueryintegerNoMaximum queued outbound channel messages
Terminal window
curl --include --no-buffer \
-H 'Connection: Upgrade' \
-H 'Upgrade: websocket' \
-H 'Sec-WebSocket-Version: 13' \
-H 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==' \
'https://67e89abc123def456789abcd-890abcdef12345678901cdef-curl-1.node-us.containers.hoody.com/api/v1/curl/channel?max_concurrent=4&max_queue=32&max_frame_bytes=65536&idle_timeout_secs=120'
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=