# Fetch

The Fetch API is a native browser API requiring no additional dependencies. It also works in server-side frameworks and edge runtimes like Cloudflare Workers, Vercel Edge, and Deno.

## Configuration

Set the `client` option to `fetch`:

```ts
import { defineConfig } from 'orval';

export default defineConfig({
  petstore: {
    output: {
      mode: 'tags-split',
      target: 'app/gen/petstore.ts',
      schemas: 'app/gen/models',
      client: 'fetch',
      baseUrl: 'http://localhost:3000',
      mock: true,
    },
    input: {
      target: './petstore.yaml',
    },
  },
});
```

## Runtime base URL

For a host that is only known at runtime (for example `process.env.API_BASE_URL` in Node or `import.meta.env.VITE_*` in Vite), use `baseUrl.runtime` instead of a fixed string. The built-in fetch client embeds the expression in generated URL template literals, so you can keep using `override.fetch` options such as `runtimeValidation` and `includeHttpResponseReturnType` without a custom mutator.

```ts
baseUrl: {
  runtime: 'process.env.API_BASE_URL',
},
```

See the [output `baseUrl` reference](/docs/reference/configuration/output#runtime) for `imports` and expressions such as `env.API_BASE_URL` from a shared module (for example `import { env } from '../../env'`). MSW mock host filtering uses the separate [`mock.baseUrl`](/docs/reference/configuration/output#mock-options) option.

## Generated Output

Orval generates three things for each endpoint:

### 1. Response Type

```ts
export type listPetsResponse = {
  data: Pets;
  status: number;
};
```

### 2. URL Generator

```ts
export const getListPetsUrl = (params?: ListPetsParams) => {
  const normalizedParams = new URLSearchParams();

  Object.entries(params || {}).forEach(([key, value]) => {
    if (value === null) {
      normalizedParams.append(key, 'null');
    } else if (value !== undefined) {
      normalizedParams.append(key, value.toString());
    }
  });

  return `http://localhost:3000/pets?${normalizedParams.toString()}`;
};
```

### 3. Fetch Function

```ts
export const listPets = async (
  params?: ListPetsParams,
  options?: RequestInit,
): Promise<listPetsResponse> => {
  const res = await fetch(getListPetsUrl(params), {
    ...options,
    method: 'GET',
  });
  const data = await res.json();

  return { status: res.status, data };
};
```

## Custom Fetch Function

Add a custom fetch implementation via mutator:

```ts
import { defineConfig } from 'orval';

export default defineConfig({
  petstore: {
    output: {
      // ...
      override: {
        mutator: {
          path: './custom-fetch.ts',
          name: 'customFetch',
        },
      },
    },
    // ...
  },
});
```

The generated functions will use your custom implementation:

```ts
export const listPets = async (
  params?: ListPetsParams,
  options?: RequestInit,
): Promise<listPetsResponse> => {
  return customFetch<Promise<listPetsResponse>>(getListPetsUrl(params), {
    ...options,
    method: 'GET',
  });
};
```

## Full Example

See the [Next.js with Fetch example](https://github.com/orval-labs/orval/tree/master/samples/next-app-with-fetch) on GitHub.
