Antigravity-awesome-skills api-endpoint-builder
Builds production-ready REST API endpoints with validation, error handling, authentication, and documentation. Follows best practices for security and scalability.
install
source · Clone the upstream repo
git clone https://github.com/sickn33/antigravity-awesome-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/sickn33/antigravity-awesome-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/antigravity-awesome-skills-claude/skills/api-endpoint-builder" ~/.claude/skills/sickn33-antigravity-awesome-skills-api-endpoint-builder && rm -rf "$T"
manifest:
plugins/antigravity-awesome-skills-claude/skills/api-endpoint-builder/SKILL.mdsafety · automated scan (low risk)
This is a pattern-based risk scan, not a security review. Our crawler flagged:
- references .env files
Always read a skill's source content before installing. Patterns alone don't mean the skill is malicious — but they warrant attention.
source content
API Endpoint Builder
Build complete, production-ready REST API endpoints with proper validation, error handling, authentication, and documentation.
When to Use This Skill
- User asks to "create an API endpoint" or "build a REST API"
- Building new backend features
- Adding endpoints to existing APIs
- User mentions "API", "endpoint", "route", or "REST"
- Creating CRUD operations
What You'll Build
For each endpoint, you create:
- Route handler with proper HTTP method
- Input validation (request body, params, query)
- Authentication/authorization checks
- Business logic
- Error handling
- Response formatting
- API documentation
- Tests (if requested)
Endpoint Structure
1. Route Definition
// Express example router.post('/api/users', authenticate, validateUser, createUser); // Fastify example fastify.post('/api/users', { preHandler: [authenticate], schema: userSchema }, createUser);
2. Input Validation
Always validate before processing:
const validateUser = (req, res, next) => { const { email, name, password } = req.body; if (!email || !email.includes('@')) { return res.status(400).json({ error: 'Valid email required' }); } if (!name || name.length < 2) { return res.status(400).json({ error: 'Name must be at least 2 characters' }); } if (!password || password.length < 8) { return res.status(400).json({ error: 'Password must be at least 8 characters' }); } next(); };
3. Handler Implementation
const createUser = async (req, res) => { try { const { email, name, password } = req.body; // Check if user exists const existing = await db.users.findOne({ email }); if (existing) { return res.status(409).json({ error: 'User already exists' }); } // Hash password const hashedPassword = await bcrypt.hash(password, 10); // Create user const user = await db.users.create({ email, name, password: hashedPassword, createdAt: new Date() }); // Don't return password const { password: _, ...userWithoutPassword } = user; res.status(201).json({ success: true, data: userWithoutPassword }); } catch (error) { console.error('Create user error:', error); res.status(500).json({ error: 'Internal server error' }); } };
Best Practices
HTTP Status Codes
- Success (GET, PUT, PATCH)200
- Created (POST)201
- No Content (DELETE)204
- Bad Request (validation failed)400
- Unauthorized (not authenticated)401
- Forbidden (not authorized)403
- Not Found404
- Conflict (duplicate)409
- Internal Server Error500
Response Format
Consistent structure:
// Success { "success": true, "data": { ... } } // Error { "error": "Error message", "details": { ... } // optional } // List with pagination { "success": true, "data": [...], "pagination": { "page": 1, "limit": 20, "total": 100 } }
Security Checklist
- Authentication required for protected routes
- Authorization checks (user owns resource)
- Input validation on all fields
- SQL injection prevention (use parameterized queries)
- Rate limiting on public endpoints
- No sensitive data in responses (passwords, tokens)
- CORS configured properly
- Request size limits set
Error Handling
// Centralized error handler app.use((err, req, res, next) => { console.error(err.stack); // Don't leak error details in production const message = process.env.NODE_ENV === 'production' ? 'Internal server error' : err.message; res.status(err.status || 500).json({ error: message }); });
Common Patterns
CRUD Operations
// Create POST /api/resources Body: { name, description } // Read (list) GET /api/resources?page=1&limit=20 // Read (single) GET /api/resources/:id // Update PUT /api/resources/:id Body: { name, description } // Delete DELETE /api/resources/:id
Pagination
const getResources = async (req, res) => { const page = parseInt(req.query.page) || 1; const limit = parseInt(req.query.limit) || 20; const skip = (page - 1) * limit; const [resources, total] = await Promise.all([ db.resources.find().skip(skip).limit(limit), db.resources.countDocuments() ]); res.json({ success: true, data: resources, pagination: { page, limit, total, pages: Math.ceil(total / limit) } }); };
Filtering & Sorting
const getResources = async (req, res) => { const { status, sort = '-createdAt' } = req.query; const filter = {}; if (status) filter.status = status; const resources = await db.resources .find(filter) .sort(sort) .limit(20); res.json({ success: true, data: resources }); };
Documentation Template
/** * @route POST /api/users * @desc Create a new user * @access Public * * @body {string} email - User email (required) * @body {string} name - User name (required) * @body {string} password - Password, min 8 chars (required) * * @returns {201} User created successfully * @returns {400} Validation error * @returns {409} User already exists * @returns {500} Server error * * @example * POST /api/users * { * "email": "user@example.com", * "name": "John Doe", * "password": "securepass123" * } */
Testing Example
describe('POST /api/users', () => { it('should create a new user', async () => { const response = await request(app) .post('/api/users') .send({ email: 'test@example.com', name: 'Test User', password: 'password123' }); expect(response.status).toBe(201); expect(response.body.success).toBe(true); expect(response.body.data.email).toBe('test@example.com'); expect(response.body.data.password).toBeUndefined(); }); it('should reject invalid email', async () => { const response = await request(app) .post('/api/users') .send({ email: 'invalid', name: 'Test User', password: 'password123' }); expect(response.status).toBe(400); expect(response.body.error).toContain('email'); }); });
Key Principles
- Validate all inputs before processing
- Use proper HTTP status codes
- Handle errors gracefully
- Never expose sensitive data
- Keep responses consistent
- Add authentication where needed
- Document your endpoints
- Write tests for critical paths
Related Skills
- Security review@security-auditor
- Testing@test-driven-development
- Data modeling@database-design
Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.