# Introduction

> Learn about what-the-fetch – a type-safe API client with schema validation using Standard Schema

**what-the-fetch** is a type-safe API client library that integrates schema validation with fetch requests, leveraging the [Standard Schema](https://standardschema.dev) specification for maximum flexibility and type safety. The cost of that validation, with the network stubbed, is on the [benchmarks](/what-the-fetch/benchmarks) page.

<Note>
**Why what-the-fetch?**

Building API clients manually is error-prone and lacks type safety. what-the-fetch
  handles type-safe URL construction, automatic request/response validation,
  and full TypeScript inference automatically.
</Note>

## Why what-the-fetch?

Building API clients manually is tedious and error-prone. what-the-fetch solves common problems developers face when working with APIs:

### Problems with Manual API Clients

- **🔴 No type safety**: Response types are unknown, leading to runtime errors
- **🔴 Manual validation**: You need to write validation code for every endpoint
- **🔴 Schema duplication**: Types and validation logic are often duplicated
- **🔴 URL building errors**: String concatenation leads to malformed URLs
- **🔴 Poor developer experience**: No autocomplete, no compile-time checks

### How what-the-fetch Solves These Issues

**what-the-fetch** provides a complete solution for type-safe API clients:

1. **End-to-end type safety**:

   - Full TypeScript inference from schema to response
   - Compile-time validation of requests
   - Autocomplete for all API endpoints and parameters
   - Type-safe path and query parameters

2. **Schema validation**:

   - Built-in support for [Standard Schema](https://standardschema.dev) specification
   - Works with Zod, Valibot, ArkType, and more
   - Automatic request/response validation
   - Single source of truth for types and validation

3. **Clean API**:

   - Simple, intuitive interface
   - Integrated with fast-url library for clean URL construction
   - Minimal boilerplate code
   - Focus on developer experience

4. **Production-ready**:
   - Comprehensive test coverage
   - Small bundle size
   - Battle-tested in real-world applications
   - Regular updates and maintenance

## Key Features

  <Card title="Type-Safe">
    Full TypeScript support with end-to-end type inference from schema
    definition to response data
  </Card>
  <Card title="Schema Validation">
    Built-in support for [Standard Schema](https://standardschema.dev) - compatible with Zod, Valibot,
    ArkType, and more
  </Card>
  <Card title="Flexible">
    Works with any schema library that implements [Standard Schema](https://standardschema.dev) for maximum
    flexibility
  </Card>
  <Card title="Minimal">
    Small bundle size with minimal dependencies - only fast-url library and
    [Standard Schema](https://standardschema.dev) spec
  </Card>
  <Card title="URL Building">
    Integrated with fast-url library for clean, safe URL construction with
    path and query parameters
  </Card>
  <Card title="Developer Experience">
    Excellent developer experience with full autocomplete and compile-time error
    checking
  </Card>

## The Problem

Building API clients manually lacks type safety and validation:

```typescript
// ❌ No type safety, manual validation
const response = await fetch(`${baseUrl}/users/${id}?fields=${fields}`);
const data = await response.json();
// What type is data? Who knows! Runtime errors waiting to happen
```

**Issues with manual API clients:**

- 🔴 No type safety for request parameters
- 🔴 Unknown response types
- 🔴 Manual validation required
- 🔴 Schema and types are duplicated
- 🔴 Difficult to maintain and refactor

## The Solution

what-the-fetch provides a type-safe API client with automatic validation:

```typescript
// ✅ Type-safe with validation
import { createFetch } from 'what-the-fetch';
import { z } from 'zod';

const api = {
  '/users/:id': {
    params: z.object({ id: z.number() }),
    query: z.object({ fields: z.string().optional() }),
    response: z.object({ id: z.number(), name: z.string(), email: z.string() })
  }
};

const apiFetch = createFetch(api, baseUrl);
const user = await apiFetch('/users/:id', {
  params: { id },
  query: { fields }
});
// user is fully typed as { id: number; name: string; email: string }
```

**Benefits:**

- ✅ Full end-to-end type safety
- ✅ Automatic request/response validation
- ✅ Single source of truth for types and validation
- ✅ Clean separation of concerns
- ✅ Easy to read and maintain

<Check>
**Type Safety & Validation**

what-the-fetch handles type-safe URL construction, automatic validation, and full
  TypeScript inference - catching errors at compile time instead of runtime.
</Check>

## When to Use what-the-fetch

what-the-fetch is ideal for:

- 🌐 **REST API clients**: Building type-safe wrappers around REST APIs
- 🔗 **Microservices**: Creating typed clients for service-to-service communication
- 📱 **Frontend applications**: Type-safe data fetching with validation
- 🛠️ **Backend services**: Calling external APIs with full type safety
- 📊 **SDK development**: Building SDKs with excellent developer experience

## Quick Example

Here's a real-world example showing how what-the-fetch simplifies API client development:

<Tabs>
  <Tab title="With what-the-fetch">
    ```typescript
    import { createFetch } from 'what-the-fetch';
    import { z } from 'zod';
    
    // Define API schema once (methods inferred automatically)
    const api = {
      '/users/:id': {  // GET (no body)
        params: z.object({ id: z.number() }),
        query: z.object({ fields: z.string().optional() }),
        response: z.object({
          id: z.number(),
          name: z.string(),
          email: z.string()
        })
      },
      '/users': {  // POST (has body)
        body: z.object({ name: z.string(), email: z.string() }),
        response: z.object({ id: z.number(), name: z.string() })
      }
    };
    
    const apiFetch = createFetch(api, 'https://api.example.com');
    
    // Type-safe GET request with validation
    const user = await apiFetch('/users/:id', {
      params: { id: 123 },
      query: { fields: 'name,email' }
    });
    // user is typed as { id: number; name: string; email: string }
    
    // Type-safe POST request (method inferred from body)
    const newUser = await apiFetch('/users', {
      body: { name: 'John', email: 'john@example.com' }
    });
    ```
  </Tab>
  <Tab title="Without what-the-fetch">
    ```typescript
    // Define types manually
    interface User {
      id: number;
      name: string;
      email: string;
    }
    
    // Build URL manually
    const url = `https://api.example.com/users/${id}?fields=${fields}`;
    
    const response = await fetch(url);
    
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    
    const data = await response.json();
    
    // Manual validation required
    if (typeof data.id !== 'number' || 
        typeof data.name !== 'string' || 
        typeof data.email !== 'string') {
      throw new Error('Invalid response');
    }
    
    const user: User = data;
    // No compile-time guarantees that data matches User type
    ```
  </Tab>
</Tabs>
