Skip to main content

Auditable HTTP Requests with “fetch”

Make HTTP requests that are recorded as spans on the task run. This is how Compose apps interact with off-chain systems — every ctx.fetch call, its URL, and its response are captured in the run’s event log, so the behavior of your app is auditable after the fact. For example, if you have an oracle that is advertised as being driven by an aggregate of several well-known price feeds, users of dApps built with it can audit the calls made to determine their prices, ensuring the price logic is fair and works as advertised. ctx.fetch wraps the native fetch and adds a few Compose-specific behaviors: the response is parsed as JSON (with a text fallback), each call is recorded as an OpenTelemetry span, successful results are cached by a deterministic idempotency key so replays after a crash don’t re-hit the remote server, and the request runs on a dedicated HTTP client pool isolated from Compose’s internal traffic.
Where FetchConfig is:
And ContextFunctionRetryConfig is:
ctx.fetch retries GET, HEAD, and OPTIONS requests by default (max_attempts defaults to 3, initial_interval_ms to 500, and backoff_factor to 2). POST, PUT, PATCH, and DELETE default to a single attempt because they are not assumed idempotent. To override either, pass a ContextFunctionRetryConfig explicitly, as in the “Request with Custom Retry Configuration” example below.

Response handling

ctx.fetch reads the response body as JSON and returns the parsed object. If the body is not valid JSON, it falls back to returning the raw text. Non-2xx responses throw an error that includes the status code, status text, and response body — so you do not need to check response.ok yourself. Because of this, the return type is the decoded body, not a Response object.

Examples

Basic GET Request

POST Request with JSON Body

If body is an object, ctx.fetch JSON-encodes it for you. Pass a string if you want to send a raw body (e.g. form-encoded or pre-serialized JSON).
To call another task in the same app, use ctx.callTask — you don’t need to go through HTTP unless you’re hitting an HTTP-triggered task externally.

Request with Custom Retry Configuration

Next Steps

Collections

Manage state across tasks and task runs with collections.

EVM

Interact with EVM blockchains and smart contracts.