Brandedflow api-endpoint-builder
Build Express.js API endpoints for the BrandedFlow MCP server. Covers route design, validation, Airtable dual-write, error handling, and rate limiting. Use when adding new MCP tools or API routes.
install
source · Clone the upstream repo
git clone https://github.com/JenCW/brandedflow
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/JenCW/brandedflow "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.claude/skills-library/api-endpoint-builder" ~/.claude/skills/jencw-brandedflow-api-endpoint-builder && rm -rf "$T"
manifest:
.claude/skills-library/api-endpoint-builder/SKILL.mdsource content
API Endpoint Builder
When to Use
- Adding a new route to
brandedflow.onrender.com - Building a new MCP tool
- Adding a webhook receiver
- Creating a data transformation endpoint
BrandedFlow MCP Server Context
- Runtime: Node.js / Express
- Deployed: Render (
)brandedflow.onrender.com - Codebase:
4-automate/mcps/ - Pattern: each MCP = one route file + registered in main server
- Airtable master base:
appYXzdeB0MUlwqFN - Auth: bearer token or Airtable API key via
.env
Endpoint Design Process
- Name the tool — kebab-case, verb-noun (e.g.
,qualify-lead
)create-client-folder - Define inputs — What does the caller send? (JSON body schema)
- Define outputs — What does the endpoint return? (success + error shapes)
- Map side effects — What does it write? (Airtable, DB, file, email)
- Write the route — Express router, validation, business logic, response
- Register — Add to main server index
- Test — curl or Postman against staging
Endpoint Template
// routes/[tool-name].js const express = require('express'); const router = express.Router(); router.post('/[tool-name]', async (req, res) => { const { field1, field2 } = req.body; // Validate if (!field1) return res.status(400).json({ error: 'field1 required' }); try { // Business logic const result = await doTheThing(field1, field2); // Dual-write Airtable if needed await writeToAirtable(result); res.json({ success: true, data: result }); } catch (err) { console.error('[tool-name] error:', err.message); res.status(500).json({ error: 'Internal error', details: err.message }); } }); module.exports = router;
Validation Rules
- Always validate required fields → 400 if missing
- Sanitize string inputs (trim, escape)
- Rate-limit public endpoints (express-rate-limit)
- Add honeypot field on public lead endpoints
End of Task
State: "END-OF-TASK: Directive [updated/N/A]. Self-annealing [applied/N/A]."