> ## Documentation Index
> Fetch the complete documentation index at: https://docs.goldsky.com/llms.txt
> Use this file to discover all available pages before exploring further.

# HTTP Requests (fetch)

## 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.

```typescript theme={null}
fetch<T = unknown>(
  url: string,
  fetchConfigOrRetryConfig?: FetchConfig | ContextFunctionRetryConfig,
  retryConfig?: ContextFunctionRetryConfig
): Promise<T | undefined>
```

Where `FetchConfig` is:

```typescript theme={null}
export interface FetchConfig {
  method?: string;
  headers?: Record<string, string>;
  body?: Record<string, unknown> | string;
}
```

And `ContextFunctionRetryConfig` is:

```typescript theme={null}
type ContextFunctionRetryConfig = {
  max_attempts: number;
  initial_interval_ms: number;
  backoff_factor: number;
};
```

<Note>
  By default, `ctx.fetch` does **not** retry on failure (`max_attempts` defaults to `1`). If you
  want automatic retries with exponential backoff, pass a `ContextFunctionRetryConfig` explicitly
  — see the "Request with Custom Retry Configuration" example below.
</Note>

### 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

```typescript theme={null}
import { TaskContext } from "compose";

export async function main({ fetch }: TaskContext) {
  const data = await fetch("https://api.example.com/data");
  return data;
}
```

#### 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).

<Tip>
  To call another task in the same app, use [`ctx.callTask`](./call-task) — you don't need to go
  through HTTP unless you're hitting an [HTTP-triggered task](../task-triggers) externally.
</Tip>

```typescript theme={null}
import { TaskContext } from "compose";

export async function main({ fetch }: TaskContext) {
  const result = await fetch("https://api.example.com/submit", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: "Bearer token123",
    },
    body: {
      name: "John Doe",
      email: "john@example.com",
    },
  });

  return result;
}
```

#### Request with Custom Retry Configuration

```typescript theme={null}
import { TaskContext } from "compose";

export async function main({ fetch }: TaskContext) {
  const data = await fetch(
    "https://unreliable-api.com/data",
    {
      method: "GET",
      headers: { "User-Agent": "Compose/1.0" },
    },
    {
      max_attempts: 5,
      initial_interval_ms: 2000,
      backoff_factor: 1.5,
    }
  );

  return data;
}
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Collections" icon="file-code" href="./collections">
    Manage state across tasks and task runs with collections.
  </Card>

  <Card title="EVM" icon="code" href="./evm/overview">
    Interact with EVM blockchains and smart contracts.
  </Card>
</CardGroup>
