# HTTP calls with Fetch

> Send API calls over HTTP and handle them with Fetch APIs.

## Useful when

- Your runtime or framework already exposes a Fetch-compatible request handler.
- A browser or remote service should call the contract over HTTP.

Use `fetchTransport()` to send client calls over HTTP. On the server, `fetchAdapter().mount()` accepts those requests and runs your implementation.

The examples use the contract and implementation from [Build a task API](https://hulla.dev/guides/api/quick-start.md).

## Mount a Fetch handler

```ts filename="src/api/handler.ts"
import { fetchAdapter } from '@hulla/api/fetch'
import { implementation } from './implementation'

export const handler = fetchAdapter().mount(implementation)
```

Pass `handler` to a Web-standard server route. The adapter owns catch-all route matching, request representation reads, response writing, cancellation, and protocol errors.

Set `maxBodyBytes` when the adapter should impose a byte budget. The default is `Infinity`; a host may still apply its own limit. Set `preserveRequestBody: true` only when native context needs to read the original body after contract decoding.

## Create a Fetch client

For a local verification, use the mounted handler as the transport's custom `fetch` function. The absolute test origin gives Node.js a valid `Request` URL; no server needs to listen on it.

```ts filename="src/api/client.ts"
import { createClient } from '@hulla/api/client'
import { fetchTransport } from '@hulla/api/fetch'
import { contract } from './contract'
import { handler } from './handler'

const api = createClient(contract, {
  transport: fetchTransport({
    baseUrl: 'https://api.test',
    fetch: handler,
  }),
})
```

The generated client is unchanged by the custom `fetch`. Call it exactly as the application will:

```ts filename="src/api/client.ts"
const result = await api.createTask({
  body: { title: 'Write the quick start' },
})

console.log(result.body.title) // Write the quick start
```

An omitted or relative `baseUrl` resolves against the document URL when the runtime supports relative `Request` objects. Node.js and most SSR modules should pass an absolute origin. Supply a custom `fetch` when the framework provides request-local dispatch or caching behavior. In a deployed application, replace the handler-backed `fetch` with the runtime's normal `fetch`; the client call and contract stay the same.

Fetch is one adapter, not the universal internal representation. Use a native adapter when the host framework should own routing, parsed bodies, hooks, streaming, or native context without translating through a second Fetch request.
