00-andruia-consultant
Usar al iniciar o mejorar un proyecto de IA: diagnostica código y restricciones, propone skills existentes y redacta tareas y un…
Builds reviewable REST API endpoint scaffolds with validation, error handling, authentication, and documentation. Follows best practices for security and scalability.
Claude Code
$ npx -y skills add sickn33/agentic-awesome-skills --skill api-endpoint-builder --agent claude-code
Codex
$ npx skills add sickn33/agentic-awesome-skills --skill api-endpoint-builder -a codex -y
Cursor
$ npx skills add sickn33/agentic-awesome-skills --skill api-endpoint-builder -a cursor -y
Gemini CLI
$ npx skills add sickn33/agentic-awesome-skills --skill api-endpoint-builder -a gemini-cli -y
GitHub Copilot
$ npx skills add sickn33/agentic-awesome-skills --skill api-endpoint-builder -a github-copilot -y
OpenCode
$ npx skills add sickn33/agentic-awesome-skills --skill api-endpoint-builder -a opencode -y
Windsurf
$ npx skills add sickn33/agentic-awesome-skills --skill api-endpoint-builder -a windsurf -y
name: api-endpoint-builder description: "Builds reviewable REST API endpoint scaffolds with validation, error handling, authentication, and documentation. Follows best practices for security and scalability." category: development risk: critical source: community date_added: "2026-03-05"
Build complete, reviewable REST API endpoint scaffolds with proper validation, error handling, authentication, and documentation.
For each endpoint, you create:
// Express example
router.post('/api/users', authenticate, validateUser, createUser);
// Fastify example
fastify.post('/api/users', {
preHandler: [authenticate],
schema: userSchema
}, createUser);Always validate before processing:
const validateUser = (req, res, next) => {
const { email, name, password } = req.body ?? {};
if (typeof email !== 'string' || !email.includes('@')) {
return res.status(400).json({ error: 'Valid email required' });
}
if (typeof name !== 'string' || name.trim().length < 2) {
return res.status(400).json({ error: 'Name must be at least 2 characters' });
}
if (typeof password !== 'string' || password.length < 8) {
return res.status(400).json({ error: 'Password must be at least 8 characters' });
}
next();
};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 userWithoutPassword = { id: user.id, email: user.email, name: user.name };
res.status(201).json({
success: true,
data: userWithoutPassword
});
} catch (error) {
console.error('Create user error:', error);
res.status(500).json({ error: 'Internal server error' });
}
};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
}
}// 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 });
});// 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/:idconst getResources = async (req, res) => {
const page = Number(req.query.page ?? 1);
const limit = Number(req.query.limit ?? 20);
if (!Number.isSafeInteger(page) || page < 1 || !Number.isSafeInteger(limit) || limit < 1 || limit > 100 || (page - 1) * limit > 100000) {
return res.status(400).json({ error: "Invalid pagination" });
}
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)
}
});
};const getResources = async (req, res) => {
const { status, sort = '-createdAt' } = req.query;
const filter = {};
if (status && !["active", "inactive"].includes(status)) return res.status(400).json({ error: "Invalid status" });
if (!["createdAt", "-createdAt", "name", "-name"].includes(sort)) return res.status(400).json({ error: "Invalid sort" });
if (status) filter.status = status;
const resources = await db.resources
.find(filter)
.sort(sort)
.limit(20);
res.json({ success: true, data: resources });
};/**
* @route POST /api/users
* @desc Create a new user
* @access Public
*
* @body {string} email - User email (required)
* @body {string} nFind reusable instructions for your project, inspect their complete files, and keep an exact skill set you can review and reuse.
Usar al iniciar o mejorar un proyecto de IA: diagnostica código y restricciones, propone skills existentes y redacta tareas y un…
Security audit, hardening, threat modeling (STRIDE/PASTA), Red/Blue Team, OWASP checks, code review, incident response, and…
Usar para crear o mejorar una skill de Andru.ia: define entradas y resultados, redacta SKILL.md con ejemplos y límites, valida la…
Usar tras definir el sector de un proyecto: prepara un dossier en español con contexto, normas aplicables, patrones UX y riesgos,…
AI-powered presentation generation via the 2slides API — create slides from text, match a reference image style, summarize…
360 feedback register: reviewer, subject, review cycle, visibility, due date and score, as CSV, SQL, JSON Schema or Notion on…
Use your assigned AgentMail inbox to read email tasks, explicitly send or reply, and check delivery. Provided automatically by…
Create a new Architecture Decision Record with sequential numbering and AgentDB registration