# Http Clients

> |

- **Type:** Skill
- **Install:** `agentstack add skill-claude-dev-suite-claude-dev-suite-http-clients`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [claude-dev-suite](https://agentstack.voostack.com/s/claude-dev-suite)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [claude-dev-suite](https://github.com/claude-dev-suite)
- **Source:** https://github.com/claude-dev-suite/claude-dev-suite/tree/main/skills/api-integration/http-clients

## Install

```sh
agentstack add skill-claude-dev-suite-claude-dev-suite-http-clients
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# HTTP Clients Core Knowledge

> **Full Reference**: See [advanced.md](advanced.md) for token refresh flow, retry with exponential backoff, request cancellation, and type-safe API client patterns.

> **Deep Knowledge**: Use `mcp__documentation__fetch_docs` with technology: `http-clients` for comprehensive documentation.

## Axios Setup

```typescript
import axios, { AxiosError, InternalAxiosRequestConfig } from 'axios';

const api = axios.create({
  baseURL: process.env.NEXT_PUBLIC_API_URL,
  timeout: 10000,
  headers: { 'Content-Type': 'application/json' },
});

// Request interceptor - add auth token
api.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    const token = localStorage.getItem('accessToken');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

// Response interceptor - handle errors
api.interceptors.response.use(
  (response) => response,
  (error: AxiosError) => {
    if (error.response?.status === 401) {
      window.location.href = '/login';
    }
    return Promise.reject(error);
  }
);
```

## Fetch API Wrapper

```typescript
class ApiError extends Error {
  constructor(public status: number, public statusText: string, public data?: unknown) {
    super(`${status}: ${statusText}`);
  }
}

async function fetchWithTimeout(url: string, options: RequestInit & { timeout?: number } = {}): Promise {
  const { timeout = 10000, ...fetchOptions } = options;
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), timeout);

  try {
    return await fetch(url, { ...fetchOptions, signal: controller.signal });
  } finally {
    clearTimeout(timeoutId);
  }
}

export async function apiFetch(endpoint: string, options: RequestInit = {}): Promise {
  const token = localStorage.getItem('accessToken');
  const headers: HeadersInit = {
    'Content-Type': 'application/json',
    ...(token && { Authorization: `Bearer ${token}` }),
  };

  const response = await fetchWithTimeout(`${API_URL}${endpoint}`, { ...options, headers });

  if (!response.ok) {
    throw new ApiError(response.status, response.statusText);
  }

  return response.json();
}
```

## ky (Modern Fetch Wrapper)

```typescript
import ky from 'ky';

const api = ky.create({
  prefixUrl: process.env.NEXT_PUBLIC_API_URL,
  timeout: 10000,
  retry: {
    limit: 2,
    methods: ['get', 'put', 'delete'],
    statusCodes: [408, 429, 500, 502, 503, 504],
  },
  hooks: {
    beforeRequest: [
      (request) => {
        const token = localStorage.getItem('accessToken');
        if (token) {
          request.headers.set('Authorization', `Bearer ${token}`);
        }
      },
    ],
  },
});

// Usage
const users = await api.get('users').json();
const user = await api.post('users', { json: newUser }).json();
```

## ofetch (Universal Fetch)

```typescript
import { ofetch } from 'ofetch';

const api = ofetch.create({
  baseURL: process.env.NUXT_PUBLIC_API_URL,
  retry: 2,
  retryDelay: 500,
  timeout: 10000,

  async onRequest({ options }) {
    const token = localStorage.getItem('accessToken');
    if (token) {
      options.headers = { ...options.headers, Authorization: `Bearer ${token}` };
    }
  },
});

// Works in Node.js and browser
const users = await api('/users');
```

## When NOT to Use This Skill

- Axios-specific configuration (use `axios` skill)
- GraphQL client setup (use `graphql-codegen` skill)
- tRPC client configuration (use `trpc` skill)
- WebSocket or Server-Sent Events

## Anti-Patterns

| Anti-Pattern | Why It's Bad | Solution |
|--------------|--------------|----------|
| No timeout configured | Hanging requests | Set timeout on all clients |
| Hardcoded API URLs | Environment coupling | Use environment variables |
| No retry logic | Poor UX on transient failures | Implement exponential backoff |
| Ignoring token expiration | 401 errors | Implement token refresh flow |
| Not canceling on unmount | Memory leaks | Use AbortController cleanup |
| Not typing responses | Runtime errors | Use TypeScript generics |

## Quick Troubleshooting

| Issue | Possible Cause | Solution |
|-------|----------------|----------|
| CORS errors | Server misconfiguration | Configure CORS on backend |
| 401 after some time | Token expired | Implement token refresh |
| Memory leaks | Not aborting on unmount | Add cleanup in useEffect |
| Network timeout | Server slow | Increase timeout, add retry |
| Infinite refresh loop | Refresh returns 401 | Exclude refresh from interceptor |

## Production Checklist

- [ ] Base URL via environment
- [ ] Request timeout configured
- [ ] Auth token interceptor
- [ ] Token refresh logic
- [ ] Error response handling
- [ ] Retry with exponential backoff
- [ ] Request cancellation on unmount
- [ ] Type-safe API methods

## Reference Documentation
- [Axios Configuration](quick-ref/axios.md)
- [Fetch Patterns](quick-ref/fetch.md)
- [ky and ofetch](quick-ref/ky-ofetch.md)

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [claude-dev-suite](https://github.com/claude-dev-suite)
- **Source:** [claude-dev-suite/claude-dev-suite](https://github.com/claude-dev-suite/claude-dev-suite)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-claude-dev-suite-claude-dev-suite-http-clients
- Seller: https://agentstack.voostack.com/s/claude-dev-suite
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
