api-endpoint-builder — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited api-endpoint-builder (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
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' });
}
};200 - Success (GET, PUT, PATCH)201 - Created (POST)204 - No Content (DELETE)400 - Bad Request (validation failed)401 - Unauthorized (not authenticated)403 - Forbidden (not authorized)404 - Not Found409 - Conflict (duplicate)500 - Internal Server ErrorConsistent 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,~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.