Consume external APIs with type safety, robust error handling, and production-ready patterns. Handles OpenAPI/Swagger specs, GraphQL schemas, REST documentation, and example requests. Produces typed clients with authentication, retry logic, and comprehensive error handling. Primary focus on TypeScript with patterns applicable to other languages. Use this skill when integrating third-party APIs, generating API clients, or implementing authentication flows.
Generates type-safe API clients with authentication, retry logic, and error handling.
/plugin marketplace add srstomp/pokayokay/plugin install srstomp-pokayokay@srstomp/pokayokayThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/authentication.mdreferences/client-architecture.mdreferences/error-handling.mdreferences/openapi-consumption.mdreferences/testing.mdBuild robust, type-safe API clients from specs and documentation.
┌─────────────────────────────────────────────────────────────┐
│ INPUTS │
├──────────────┬──────────────┬──────────────┬────────────────┤
│ OpenAPI/ │ GraphQL │ REST Docs │ Example │
│ Swagger │ Schema │ (informal) │ Requests │
└──────┬───────┴──────┬───────┴──────┬───────┴───────┬────────┘
│ │ │ │
└──────────────┴──────────────┴───────────────┘
│
▼
┌───────────────────────────────┐
│ ANALYSIS & DESIGN │
│ • Extract types/schemas │
│ • Identify auth requirements │
│ • Map error responses │
│ • Plan client architecture │
└───────────────┬───────────────┘
│
▼
┌───────────────────────────────┐
│ IMPLEMENTATION │
│ • Generate/write types │
│ • Build client layer │
│ • Implement auth flow │
│ • Add error handling │
│ • Configure retry logic │
└───────────────┬───────────────┘
│
▼
┌───────────────────────────────┐
│ TESTING │
│ • Mock responses │
│ • Integration tests │
│ • Error scenario tests │
└───────────────────────────────┘
Best case: Full spec with schemas, auth, error responses.
Extract:
Extract:
When no formal spec exists:
From cURL, Postman, or code samples:
How complex is the integration?
│
├── Simple (1-5 endpoints, basic auth)
│ └── Typed fetch wrapper
│
├── Medium (5-20 endpoints, OAuth/multiple resources)
│ └── Service class with methods per endpoint
│
└── Complex (20+ endpoints, multiple auth schemes, heavy usage)
└── Generated client + custom wrapper layer
| Complexity | Pattern | When to Use |
|---|---|---|
| Simple | Typed functions | Few endpoints, one-off integration |
| Medium | Service class | Core integration, team will maintain |
| Complex | Generated + wrapper | Large API, frequent updates, critical path |
// ❌ Untyped
const user = await api.get('/users/1');
// ✅ Typed
const user = await api.get<User>('/users/1');
// ✅ Even better: validated at runtime
const user = await api.get('/users/1', { schema: UserSchema });
// ❌ Silent failure
const data = response.data ?? {};
// ✅ Explicit error
if (!response.ok) {
throw new ApiError(response.status, await response.json());
}
// ❌ Auth scattered everywhere
fetch(url, { headers: { Authorization: `Bearer ${token}` } });
// ✅ Auth handled by client
const client = createApiClient({ auth: tokenProvider });
// ❌ Retry everything
retry(request, { attempts: 3 });
// ✅ Retry only idempotent + transient failures
retry(request, {
attempts: 3,
when: (error) => error.status >= 500 || error.code === 'NETWORK_ERROR',
methods: ['GET', 'PUT', 'DELETE'], // Not POST
});
// ❌ API details leak everywhere
const response = await fetch(`${API_URL}/users/${id}`);
const user = response.data.data.attributes;
// ✅ Transform at boundary
// In api client:
async getUser(id: string): Promise<User> {
const response = await this.get(`/users/${id}`);
return transformUser(response.data);
}
async function api<T>(
path: string,
options?: RequestInit
): Promise<T> {
const response = await fetch(`${BASE_URL}${path}`, {
...options,
headers: {
'Content-Type': 'application/json',
...options?.headers,
},
});
if (!response.ok) {
throw await ApiError.fromResponse(response);
}
return response.json();
}
// Usage
const user = await api<User>('/users/1');
class UserService {
constructor(private client: ApiClient) {}
async getUser(id: string): Promise<User> {
return this.client.get(`/users/${id}`);
}
async createUser(data: CreateUserInput): Promise<User> {
return this.client.post('/users', data);
}
async updateUser(id: string, data: UpdateUserInput): Promise<User> {
return this.client.put(`/users/${id}`, data);
}
async deleteUser(id: string): Promise<void> {
return this.client.delete(`/users/${id}`);
}
}
class ApiError extends Error {
constructor(
public status: number,
public code: string,
public details?: unknown
) {
super(`API Error: ${code}`);
}
get isRetryable(): boolean {
return this.status >= 500 || this.status === 429;
}
get isAuthError(): boolean {
return this.status === 401 || this.status === 403;
}
get isValidationError(): boolean {
return this.status === 400 || this.status === 422;
}
get isNotFound(): boolean {
return this.status === 404;
}
}
// Bad: No type safety
const user = await api.get('/users/' + id);
user.nmae; // Typo not caught
// Bad: Errors disappear
try {
return await api.getUser(id);
} catch {
return null;
}
// Bad: Can't refresh, can't test
const headers = { Authorization: 'Bearer abc123' };
// Bad: Hammers failing server
while (attempts < 3) {
try { return await request(); } catch { attempts++; }
}
// Bad: Can't debug production issues
// No logging at all
// Bad: API response shape leaks into app
function UserProfile({ user }: { user: ApiUserResponse }) {
return <div>{user.data.attributes.name}</div>;
}
References:
Activates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Activates when the user asks about Agent Skills, wants to find reusable AI capabilities, needs to install skills, or mentions skills for Claude. Use for discovering, retrieving, and installing skills.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.