Fetch & Curl
FETCH makes HTTP requests from within OcaltQL. It operates in two modes — synchronous by default, or asynchronous with SET PROMISE. All modifiers are optional and can appear in any order. CURL is a direct alias for FETCH.
Sync vs Async
This is the most important distinction in FETCH.
Synchronous — AFTER blocks until the fetch completes. The script cannot proceed until the response arrives. Simple and sequential, but the script pays the full wait cost at that line.
Asynchronous — SET PROMISE starts the fetch in the background immediately. The script continues running. The variable is WAITING until the response arrives. You only block when you explicitly call WAIT FOR — and only if the fetch has not already resolved by then.
FETCH "https://api.example.com/data" SET ?data
AFTER EMIT ?data
(* AFTER cannot run until FETCH completes *)
FETCH "https://api.example.com/data" SET PROMISE ?data
AFTER EMIT "I ran immediately while fetch is still in progress"
AFTER WAIT FOR ?data SET ?result
AFTER EMIT ?result
(* Script runs freely until WAIT FOR — only blocks there *)
FETCH "https://api1.com/data" SET PROMISE ?a
AND FETCH "https://api2.com/data" SET PROMISE ?b
AND FETCH "https://api3.com/data" SET PROMISE ?c
(* All three start simultaneously in the background *)
AFTER EMIT "Doing other work while fetches run"
AFTER CALCULATE 1 + 1 SET ?result
(* Now collect — if already resolved, no wait at all *)
AFTER WAIT FOR ?a SET ?a
AFTER WAIT FOR ?b SET ?b
AFTER WAIT FOR ?c SET ?c
AFTER EMIT ?a & ?b & ?c
Basic FETCH
Without modifiers, FETCH performs a GET request and captures the response body.
STRING "https://api.example.com/data" SET ?url
AFTER FETCH ?url SET ?data
AFTER EMIT ?data
Modifiers
All modifiers are optional and can appear in any order after the URL.
FETCH ?url METHOD "post" SET ?posted
FETCH ?url METHOD "post" IP "192.168.1.1" SET ?proxied
FETCH ?url METHOD "post" USER AGENT "Mozilla/5.0" SET ?spoofed
FETCH ?url USER AGENT "CustomBot/1.0" TIMEOUT 10 SECONDS SET ?slow
FETCH ?url METHOD "get" HEADER "Authorization: Bearer token" HEADER "X-Custom: value" SET ?headers
Request Body
The BODY modifier passes a request body. Set the appropriate HEADER alongside it for the content type.
FETCH ?url METHOD "post" BODY "name=Alice&age=30" SET ?form
FETCH ?url METHOD "post" BODY '{"name":"Alice"}' HEADER "Content-Type: application/json" SET ?json
Download to File
INTO writes the response body directly to a file path. Side-effect only — no SET.
FETCH ?url INTO "/root/downloaded.html"
Parsing the Response
PARSE JSON converts a raw JSON response string into an OcaltQL object.
FETCH ?url SET ?raw
AFTER PARSE JSON ?raw SET ?parsed
AFTER EMIT ?parsed("status")
AFTER EMIT ?parsed("data")
Split Status and Data Capture
To capture the HTTP status code and response body separately in one request, use WITH STATUS and WITH DATA.
FETCH "https://api.example.com/data" SET ?responsecode WITH STATUS AND SET ?responsedata WITH DATA
AFTER EMIT ?responsecode
AFTER EMIT ?responsedata
CURL
CURL is a direct alias for FETCH. Every modifier and pattern available on FETCH works identically on CURL.
CURL ?url SET ?response
CURL ?url METHOD "get" SET ?simple
METHOD, HEADER, BODY, USER AGENT, IP, and TIMEOUT can appear in any combination and in any sequence after the URL.