Awesome-omni-skill api-integration
Work with REST and GraphQL APIs, authentication, API configuration, and data fetching. Use when implementing API calls, debugging network requests, setting up Apollo Client, or handling authentication.
install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/api-integration-doitsu2014" ~/.claude/skills/diegosouzapw-awesome-omni-skill-api-integration-a22c72 && rm -rf "$T"
manifest:
skills/development/api-integration-doitsu2014/SKILL.mdsource content
API Integration
Overview
This skill helps you work with API integrations in the admin_side application. The project uses both REST API and GraphQL with Apollo Client, secured by Keycloak authentication.
Key Files
API Configuration
- REST API configuration and authenticated fetchsrc/config/api.config.ts
- Apollo Client setupsrc/infrastructure/graphQL/graphql-client.ts
- Authentication utilitiessrc/infrastructure/utilities.auth.ts
- General utility functionssrc/infrastructure/utilities.ts
Authentication
- Auth context providersrc/auth/AuthContext.tsx
- Route protectionsrc/auth/ProtectedRoute.tsx
- Keycloak configurationsrc/auth/keycloak.ts
Data Access
- Category data access servicesrc/infrastructure/das/categories.das.ts
- GraphQL queriessrc/infrastructure/graphQL/queries/categories/
REST API Setup
Configuration
// src/config/api.config.ts export const getApiUrl = (path: string) => { const baseUrl = import.meta.env.PUBLIC_REST_API_URL; return `${baseUrl}${path}`; };
Authenticated Requests
export const authenticatedFetch = async ( url: string, token: string | null, options: RequestInit = {} ): Promise<Response> => { const headers = { 'Content-Type': 'application/json', ...(token && { Authorization: `Bearer ${token}` }), ...options.headers, }; return fetch(url, { ...options, headers, }); };
Environment Variables
REST API URL is configured via environment variable:
PUBLIC_REST_API_URL=http://localhost:4000/api
GraphQL Integration
Apollo Client Setup
// src/infrastructure/graphQL/graphql-client.ts import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client'; import { setContext } from '@apollo/client/link/context'; const httpLink = createHttpLink({ uri: import.meta.env.PUBLIC_GRAPHQL_API_URL, }); const authLink = setContext((_, { headers }) => { const token = getAuthToken(); // Get from storage return { headers: { ...headers, authorization: token ? `Bearer ${token}` : '', }, }; }); export const graphqlClient = new ApolloClient({ link: authLink.concat(httpLink), cache: new InMemoryCache(), });
Writing GraphQL Queries
// src/infrastructure/graphQL/queries/categories/get-categories.ts import { gql } from '@apollo/client'; export const GET_CATEGORIES = gql` query GetCategories { categories { id name slug description posts { id title } } } `;
Using GraphQL Queries
import { graphqlClient } from '@/infrastructure/graphQL/graphql-client'; import { GET_CATEGORIES } from '@/infrastructure/graphQL/queries/categories/get-categories'; const { data, loading, error } = await graphqlClient.query({ query: GET_CATEGORIES, fetchPolicy: 'network-only', // or 'cache-first', 'cache-only' });
Authentication
Keycloak Integration
The app uses Keycloak for authentication:
// src/auth/keycloak.ts import Keycloak from 'keycloak-js'; const keycloak = new Keycloak({ url: import.meta.env.PUBLIC_KEYCLOAK_URL, realm: import.meta.env.PUBLIC_KEYCLOAK_REALM, clientId: import.meta.env.PUBLIC_KEYCLOAK_CLIENT_ID, }); export default keycloak;
Auth Context
// Usage in components import { useAuth } from '@/auth/AuthContext'; function MyComponent() { const { token, isAuthenticated, login, logout } = useAuth(); // Use token for API calls const response = await authenticatedFetch(url, token); }
Protected Routes
import ProtectedRoute from '@/auth/ProtectedRoute'; <ProtectedRoute> <AdminDashboard /> </ProtectedRoute>
API Endpoints Reference
Blog Posts
- List all postsGET /posts
- Get single postGET /posts/:id
- Create new postPOST /posts
- Update postPUT /posts/:id
- Delete postDELETE /posts/:id
Categories
- List all categoriesGET /categories
- Get single categoryGET /categories/:id
- Create new categoryPOST /categories
- Update categoryPUT /categories/:id
- Delete categoryDELETE /categories/:id
Common Patterns
Fetching Data
const [data, setData] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const { token } = useAuth(); useEffect(() => { const fetchData = async () => { setLoading(true); try { const response = await authenticatedFetch( getApiUrl('/posts'), token ); if (response.ok) { const result = await response.json(); setData(result.data); } else { throw new Error('Failed to fetch'); } } catch (err) { setError(err.message); } finally { setLoading(false); } }; fetchData(); }, [token]);
Creating Data
const handleCreate = async (formData) => { try { const response = await authenticatedFetch( getApiUrl('/posts'), token, { method: 'POST', body: JSON.stringify(formData), } ); if (response.ok) { const result = await response.json(); navigate('/admin/posts'); } else { const error = await response.json(); console.error('Create failed:', error); } } catch (err) { console.error('Network error:', err); } };
Updating Data
const handleUpdate = async (id, formData) => { try { const response = await authenticatedFetch( getApiUrl(`/posts/${id}`), token, { method: 'PUT', body: JSON.stringify({ ...formData, rowVersion, // Include for optimistic locking }), } ); if (response.ok) { navigate('/admin/posts'); } } catch (err) { console.error('Update error:', err); } };
Error Handling
REST API Errors
const response = await authenticatedFetch(url, token); if (!response.ok) { if (response.status === 401) { // Unauthorized - redirect to login logout(); } else if (response.status === 404) { // Not found console.error('Resource not found'); } else { // Other errors const error = await response.json(); console.error('API error:', error); } }
GraphQL Errors
const { data, error } = await graphqlClient.query({ query: GET_CATEGORIES, }); if (error) { console.error('GraphQL error:', error.message); // Handle network errors, GraphQL errors, etc. }
Best Practices
- Always use authenticatedFetch for REST API calls
- Include Bearer token in all authenticated requests
- Handle loading states appropriately
- Catch and display errors to users
- Use environment variables for API URLs
- Implement retry logic for failed requests when appropriate
- Cache GraphQL queries strategically
- Validate responses before using data
- Handle 401 errors by redirecting to login
- Include rowVersion in update operations
Debugging API Issues
- Check Network Tab: Verify request/response in browser DevTools
- Validate Token: Ensure auth token is valid and not expired
- Check CORS: Verify server allows requests from your origin
- Review Headers: Confirm Authorization header is set correctly
- Test Endpoints: Use Postman/curl to test API directly
- Check Environment Variables: Verify API URLs are correct
- Review Apollo Cache: Clear cache if seeing stale data
- Monitor Console: Check for error messages and warnings
Environment Variables
Required environment variables:
# REST API PUBLIC_REST_API_URL=http://localhost:4000/api # GraphQL API PUBLIC_GRAPHQL_API_URL=http://localhost:4000/graphql # Keycloak PUBLIC_KEYCLOAK_URL=http://localhost:8080 PUBLIC_KEYCLOAK_REALM=your-realm PUBLIC_KEYCLOAK_CLIENT_ID=your-client-id
Example Workflow
When implementing a new API integration:
- Review existing API configuration
- Check authentication setup
- Define TypeScript types for request/response
- Implement API call with error handling
- Add loading states to UI
- Test with valid and invalid data
- Handle edge cases (network errors, timeouts)
- Add appropriate user feedback