API Integration Skill
Quick reference for integrating backend REST APIs into React frontend applications.
When to Use
- •Starting fresh API integration for a new feature
- •Adding new endpoints to existing services
- •Connecting frontend pages to backend APIs
- •Creating TypeScript service wrappers for httpService
Quick Start (3 Steps)
1. Read Documentation
- •
.claude-project/docs/PROJECT_API.md- Available backend endpoints - •
.claude-project/docs/PROJECT_KNOWLEDGE.md- Product features and pages
2. Create Service File
typescript
// frontend/app/services/featureService.ts
import { httpService } from './httpService';
export const featureService = {
getAll: () => httpService.get('/features'),
getById: (id: string) => httpService.get(`/features/${id}`),
create: (data: CreateDto) => httpService.post('/features', data),
update: (id: string, data: UpdateDto) => httpService.put(`/features/${id}`, data),
delete: (id: string) => httpService.delete(`/features/${id}`)
};
3. Integrate in Component
typescript
// frontend/app/pages/feature/list.tsx
import { featureService } from '~/services/featureService';
export default function FeatureList() {
const [features, setFeatures] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
featureService.getAll()
.then(data => setFeatures(data))
.catch(err => console.error(err))
.finally(() => setLoading(false));
}, []);
if (loading) return <div>Loading...</div>;
return <div>{/* Render features */}</div>;
}
Common Patterns
GET Request (Fetch Data)
typescript
const ideaService = {
browse: (filters?: BrowseFilters) =>
httpService.get<Idea[]>('/ideas', { params: filters }),
getById: (id: string) =>
httpService.get<Idea>(`/ideas/${id}`)
};
POST Request (Create)
typescript
const ideaService = {
create: (data: CreateIdeaDto) =>
httpService.post<Idea>('/ideas', data)
};
PUT/PATCH Request (Update)
typescript
const ideaService = {
update: (id: string, data: UpdateIdeaDto) =>
httpService.put<Idea>(`/ideas/${id}`, data)
};
DELETE Request
typescript
const ideaService = {
delete: (id: string) =>
httpService.delete(`/ideas/${id}`)
};
File Upload (FormData)
typescript
const mediaService = {
uploadImage: (ideaId: string, file: File) => {
const formData = new FormData();
formData.append('file', file);
return httpService.post(`/ideas/${ideaId}/media/image`, formData);
}
};
Examples
Example 1: Authentication Service
typescript
// frontend/app/services/authService.ts
import { httpService } from './httpService';
import type { LoginDto, AuthResponse } from '~/types/auth.types';
export const authService = {
login: (data: LoginDto) =>
httpService.post<AuthResponse>('/auth/login', data),
logout: () =>
httpService.get('/auth/logout'),
forgotPassword: (email: string) =>
httpService.post('/auth/forgot-password', { email }),
resetPassword: (data: ResetPasswordDto) =>
httpService.post('/auth/reset-password', data)
};
Example 2: CRUD Service with Filters
typescript
// frontend/app/services/ideaService.ts
export const ideaService = {
// Browse with filters
browse: (filters?: {
category?: string;
status?: string;
search?: string;
page?: number;
limit?: number;
}) => httpService.get<Idea[]>('/ideas', { params: filters }),
// My ideas only
getMyIdeas: () =>
httpService.get<Idea[]>('/ideas/my/ideas'),
// Admin endpoints
admin: {
getPending: () =>
httpService.get<Idea[]>('/ideas/admin/pending'),
approve: (id: string) =>
httpService.patch(`/ideas/admin/${id}/approve`)
}
};
TypeScript Types
Create corresponding type files in frontend/app/types/:
typescript
// frontend/app/types/idea.types.ts
export interface Idea {
id: string;
projectName: string;
tagline: string;
category: CategoryEnum;
tags: string[];
story: string;
voteCount: number;
commentCount: number;
status: IdeaStatusEnum;
createdAt: string;
updatedAt: string;
}
export enum IdeaStatusEnum {
DRAFT = 'DRAFT',
APPROVED = 'APPROVED',
IN_DEVELOPMENT = 'IN_DEVELOPMENT'
}
export interface CreateIdeaDto {
projectName: string;
tagline: string;
category: CategoryEnum;
tags: string[];
story: string;
}
Error Handling
The httpService already includes error handling, but you can add custom handling:
typescript
try {
const data = await ideaService.create(formData);
toast.success('Idea created successfully');
navigate(`/ideas/${data.id}`);
} catch (error) {
// Error is already processed by errorHandler
toast.error(error.message || 'Failed to create idea');
}
Testing
After creating services, test them:
typescript
// Manual test in browser console
import { ideaService } from '~/services/ideaService';
// Test GET
const ideas = await ideaService.browse({ limit: 5 });
console.log(ideas);
// Test POST (if authenticated)
const newIdea = await ideaService.create({
projectName: 'Test',
tagline: 'Test tagline',
// ... other fields
});
Verification Checklist
- • Service file created in
frontend/app/services/ - • TypeScript types defined in
frontend/app/types/ - • Service methods match backend API endpoints
- • Endpoint URLs are correct (check PROJECT_API.md)
- • Authentication required? Bearer token handled by httpService
- • Error handling in place
- • Loading states in components
- • Success/error messages shown to user
- • PROJECT_API_INTEGRATION.md updated with status
Full Workflow
For comprehensive step-by-step workflow including:
- •Documentation analysis
- •API mapping to pages
- •E2E test creation
- •Updating integration docs
See: .claude/react/agents/frontend-developer.md
Related Resources
- •frontend-developer agent - Complete workflow
- •PROJECT_API_INTEGRATION.md - Integration tracking
- •httpService.ts - Base HTTP client
- •e2e-testing skill - Playwright testing patterns