{"id":"895c82ca-0373-4b46-b62a-a0e90c22acf3","shortId":"gq8Baw","kind":"skill","title":"api-endpoint-builder","tagline":"Builds production-ready REST API endpoints with validation, error handling, authentication, and documentation. Follows best practices for security and scalability.","description":"# API Endpoint Builder\n\nBuild complete, production-ready REST API endpoints with proper validation, error handling, authentication, and documentation.\n\n## When to Use This Skill\n\n- User asks to \"create an API endpoint\" or \"build a REST API\"\n- Building new backend features\n- Adding endpoints to existing APIs\n- User mentions \"API\", \"endpoint\", \"route\", or \"REST\"\n- Creating CRUD operations\n\n## What You'll Build\n\nFor each endpoint, you create:\n- Route handler with proper HTTP method\n- Input validation (request body, params, query)\n- Authentication/authorization checks\n- Business logic\n- Error handling\n- Response formatting\n- API documentation\n- Tests (if requested)\n\n## Endpoint Structure\n\n### 1. Route Definition\n\n```javascript\n// Express example\nrouter.post('/api/users', authenticate, validateUser, createUser);\n\n// Fastify example\nfastify.post('/api/users', {\n  preHandler: [authenticate],\n  schema: userSchema\n}, createUser);\n```\n\n### 2. Input Validation\n\nAlways validate before processing:\n\n```javascript\nconst validateUser = (req, res, next) => {\n  const { email, name, password } = req.body;\n  \n  if (!email || !email.includes('@')) {\n    return res.status(400).json({ error: 'Valid email required' });\n  }\n  \n  if (!name || name.length < 2) {\n    return res.status(400).json({ error: 'Name must be at least 2 characters' });\n  }\n  \n  if (!password || password.length < 8) {\n    return res.status(400).json({ error: 'Password must be at least 8 characters' });\n  }\n  \n  next();\n};\n```\n\n### 3. Handler Implementation\n\n```javascript\nconst createUser = async (req, res) => {\n  try {\n    const { email, name, password } = req.body;\n    \n    // Check if user exists\n    const existing = await db.users.findOne({ email });\n    if (existing) {\n      return res.status(409).json({ error: 'User already exists' });\n    }\n    \n    // Hash password\n    const hashedPassword = await bcrypt.hash(password, 10);\n    \n    // Create user\n    const user = await db.users.create({\n      email,\n      name,\n      password: hashedPassword,\n      createdAt: new Date()\n    });\n    \n    // Don't return password\n    const { password: _, ...userWithoutPassword } = user;\n    \n    res.status(201).json({\n      success: true,\n      data: userWithoutPassword\n    });\n    \n  } catch (error) {\n    console.error('Create user error:', error);\n    res.status(500).json({ error: 'Internal server error' });\n  }\n};\n```\n\n## Best Practices\n\n### HTTP Status Codes\n- `200` - Success (GET, PUT, PATCH)\n- `201` - Created (POST)\n- `204` - No Content (DELETE)\n- `400` - Bad Request (validation failed)\n- `401` - Unauthorized (not authenticated)\n- `403` - Forbidden (not authorized)\n- `404` - Not Found\n- `409` - Conflict (duplicate)\n- `500` - Internal Server Error\n\n### Response Format\n\nConsistent structure:\n\n```javascript\n// Success\n{\n  \"success\": true,\n  \"data\": { ... }\n}\n\n// Error\n{\n  \"error\": \"Error message\",\n  \"details\": { ... } // optional\n}\n\n// List with pagination\n{\n  \"success\": true,\n  \"data\": [...],\n  \"pagination\": {\n    \"page\": 1,\n    \"limit\": 20,\n    \"total\": 100\n  }\n}\n```\n\n### Security Checklist\n\n- [ ] Authentication required for protected routes\n- [ ] Authorization checks (user owns resource)\n- [ ] Input validation on all fields\n- [ ] SQL injection prevention (use parameterized queries)\n- [ ] Rate limiting on public endpoints\n- [ ] No sensitive data in responses (passwords, tokens)\n- [ ] CORS configured properly\n- [ ] Request size limits set\n\n### Error Handling\n\n```javascript\n// Centralized error handler\napp.use((err, req, res, next) => {\n  console.error(err.stack);\n  \n  // Don't leak error details in production\n  const message = process.env.NODE_ENV === 'production' \n    ? 'Internal server error' \n    : err.message;\n  \n  res.status(err.status || 500).json({ error: message });\n});\n```\n\n## Common Patterns\n\n### CRUD Operations\n\n```javascript\n// Create\nPOST /api/resources\nBody: { name, description }\n\n// Read (list)\nGET /api/resources?page=1&limit=20\n\n// Read (single)\nGET /api/resources/:id\n\n// Update\nPUT /api/resources/:id\nBody: { name, description }\n\n// Delete\nDELETE /api/resources/:id\n```\n\n### Pagination\n\n```javascript\nconst getResources = async (req, res) => {\n  const page = parseInt(req.query.page) || 1;\n  const limit = parseInt(req.query.limit) || 20;\n  const skip = (page - 1) * limit;\n  \n  const [resources, total] = await Promise.all([\n    db.resources.find().skip(skip).limit(limit),\n    db.resources.countDocuments()\n  ]);\n  \n  res.json({\n    success: true,\n    data: resources,\n    pagination: {\n      page,\n      limit,\n      total,\n      pages: Math.ceil(total / limit)\n    }\n  });\n};\n```\n\n### Filtering & Sorting\n\n```javascript\nconst getResources = async (req, res) => {\n  const { status, sort = '-createdAt' } = req.query;\n  \n  const filter = {};\n  if (status) filter.status = status;\n  \n  const resources = await db.resources\n    .find(filter)\n    .sort(sort)\n    .limit(20);\n  \n  res.json({ success: true, data: resources });\n};\n```\n\n## Documentation Template\n\n```javascript\n/**\n * @route POST /api/users\n * @desc Create a new user\n * @access Public\n * \n * @body {string} email - User email (required)\n * @body {string} name - User name (required)\n * @body {string} password - Password, min 8 chars (required)\n * \n * @returns {201} User created successfully\n * @returns {400} Validation error\n * @returns {409} User already exists\n * @returns {500} Server error\n * \n * @example\n * POST /api/users\n * {\n *   \"email\": \"user@example.com\",\n *   \"name\": \"John Doe\",\n *   \"password\": \"securepass123\"\n * }\n */\n```\n\n## Testing Example\n\n```javascript\ndescribe('POST /api/users', () => {\n  it('should create a new user', async () => {\n    const response = await request(app)\n      .post('/api/users')\n      .send({\n        email: 'test@example.com',\n        name: 'Test User',\n        password: 'password123'\n      });\n    \n    expect(response.status).toBe(201);\n    expect(response.body.success).toBe(true);\n    expect(response.body.data.email).toBe('test@example.com');\n    expect(response.body.data.password).toBeUndefined();\n  });\n  \n  it('should reject invalid email', async () => {\n    const response = await request(app)\n      .post('/api/users')\n      .send({\n        email: 'invalid',\n        name: 'Test User',\n        password: 'password123'\n      });\n    \n    expect(response.status).toBe(400);\n    expect(response.body.error).toContain('email');\n  });\n});\n```\n\n## Key Principles\n\n- Validate all inputs before processing\n- Use proper HTTP status codes\n- Handle errors gracefully\n- Never expose sensitive data\n- Keep responses consistent\n- Add authentication where needed\n- Document your endpoints\n- Write tests for critical paths\n\n## Related Skills\n\n- `@security-auditor` - Security review\n- `@test-driven-development` - Testing\n- `@database-design` - Data modeling\n\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.","tags":["api","endpoint","builder","antigravity","awesome","skills","sickn33","agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding"],"capabilities":["skill","source-sickn33","skill-api-endpoint-builder","topic-agent-skills","topic-agentic-skills","topic-ai-agent-skills","topic-ai-agents","topic-ai-coding","topic-ai-workflows","topic-antigravity","topic-antigravity-skills","topic-claude-code","topic-claude-code-skills","topic-codex-cli","topic-codex-skills"],"categories":["antigravity-awesome-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/sickn33/antigravity-awesome-skills/api-endpoint-builder","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add sickn33/antigravity-awesome-skills","source_repo":"https://github.com/sickn33/antigravity-awesome-skills","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 34964 github stars · SKILL.md body (7,115 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-25T00:50:26.819Z","embedding":null,"createdAt":"2026-04-18T21:31:07.944Z","updatedAt":"2026-04-25T00:50:26.819Z","lastSeenAt":"2026-04-25T00:50:26.819Z","tsv":"'/api/resources':435,442,450,454,461 '/api/users':124,131,548,596,609,623,659 '1':117,346,444,474,483 '10':240 '100':350 '2':137,169,180 '20':348,446,479,537 '200':288 '201':263,293,577,635 '204':296 '3':199 '400':160,172,188,300,582,671 '401':305 '403':309 '404':313 '409':227,316,586 '500':277,319,424,591 '8':185,196,573 'access':554 'ad':66 'add':698 'alreadi':231,588 'alway':140 'api':2,10,26,35,55,61,70,73,110 'api-endpoint-build':1 'app':621,657 'app.use':399 'ask':51,760 'async':205,467,514,616,652 'auditor':714 'authent':16,42,125,133,308,353,699 'authentication/authorization':102 'author':312,358 'await':220,237,245,488,530,619,655 'backend':64 'bad':301 'bcrypt.hash':238 'best':20,283 'bodi':99,436,456,556,562,568 'boundari':768 'build':5,29,58,62,84 'builder':4,28 'busi':104 'catch':269 'central':396 'char':574 'charact':181,197 'check':103,214,359 'checklist':352 'clarif':762 'clear':735 'code':287,687 'common':428 'complet':30 'configur':387 'conflict':317 'consist':325,697 'console.error':271,404 'const':145,150,203,209,218,235,243,258,413,465,470,475,480,485,512,517,522,528,617,653 'content':298 'cor':386 'creat':53,78,89,241,272,294,433,550,579,612 'createdat':251,520 'createus':127,136,204 'criteria':771 'critic':708 'crud':79,430 'data':267,331,343,381,499,541,694,725 'databas':723 'database-design':722 'date':253 'db.resources':531 'db.resources.countdocuments':495 'db.resources.find':490 'db.users.create':246 'db.users.findone':221 'definit':119 'delet':299,459,460 'desc':549 'describ':607,739 'descript':438,458 'design':724 'detail':336,410 'develop':720 'document':18,44,111,543,702 'doe':601 'driven':719 'duplic':318 'email':151,156,164,210,222,247,558,560,597,625,651,661,675 'email.includes':157 'endpoint':3,11,27,36,56,67,74,87,115,378,704 'env':416 'environ':751 'environment-specif':750 'err':400 'err.message':421 'err.stack':405 'err.status':423 'error':14,40,106,162,174,190,229,270,274,275,279,282,322,332,333,334,393,397,409,420,426,584,593,689 'exampl':122,129,594,605 'exist':69,217,219,224,232,589 'expect':632,636,640,644,668,672 'expert':756 'expos':692 'express':121 'fail':304 'fastifi':128 'fastify.post':130 'featur':65 'field':367 'filter':509,523,533 'filter.status':526 'find':532 'follow':19 'forbidden':310 'format':109,324 'found':315 'get':290,441,449 'getresourc':466,513 'grace':690 'handl':15,41,107,394,688 'handler':91,200,398 'hash':233 'hashedpassword':236,250 'http':94,285,685 'id':451,455,462 'implement':201 'inject':369 'input':96,138,363,680,765 'intern':280,320,418 'invalid':650,662 'javascript':120,144,202,327,395,432,464,511,545,606 'john':600 'json':161,173,189,228,264,278,425 'keep':695 'key':676 'leak':408 'least':179,195 'limit':347,375,391,445,476,484,493,494,503,508,536,727 'list':338,440 'll':83 'logic':105 'match':736 'math.ceil':506 'mention':72 'messag':335,414,427 'method':95 'min':572 'miss':773 'model':726 'must':176,192 'name':152,167,175,211,248,437,457,564,566,599,627,663 'name.length':168 'need':701 'never':691 'new':63,252,552,614 'next':149,198,403 'oper':80,431 'option':337 'output':745 'own':361 'page':345,443,471,482,502,505 'pagin':340,344,463,501 'param':100 'parameter':372 'parseint':472,477 'password':153,183,191,212,234,239,249,257,259,384,570,571,602,630,666 'password.length':184 'password123':631,667 'patch':292 'path':709 'pattern':429 'permiss':766 'post':295,434,547,595,608,622,658 'practic':21,284 'prehandl':132 'prevent':370 'principl':677 'process':143,682 'process.env.node':415 'product':7,32,412,417 'production-readi':6,31 'promise.all':489 'proper':38,93,388,684 'protect':356 'public':377,555 'put':291,453 'queri':101,373 'rate':374 'read':439,447 'readi':8,33 'reject':649 'relat':710 'req':147,206,401,468,515 'req.body':154,213 'req.query':521 'req.query.limit':478 'req.query.page':473 'request':98,114,302,389,620,656 'requir':165,354,561,567,575,764 'res':148,207,402,469,516 'res.json':496,538 'res.status':159,171,187,226,262,276,422 'resourc':362,486,500,529,542 'respons':108,323,383,618,654,696 'response.body.data.email':641 'response.body.data.password':645 'response.body.error':673 'response.body.success':637 'response.status':633,669 'rest':9,34,60,77 'return':158,170,186,225,256,576,581,585,590 'review':716,757 'rout':75,90,118,357,546 'router.post':123 'safeti':767 'scalabl':25 'schema':134 'scope':738 'secur':23,351,713,715 'securepass123':603 'security-auditor':712 'send':624,660 'sensit':380,693 'server':281,321,419,592 'set':392 'singl':448 'size':390 'skill':49,711,730 'skill-api-endpoint-builder' 'skip':481,491,492 'sort':510,519,534,535 'source-sickn33' 'specif':752 'sql':368 'status':286,518,525,527,686 'stop':758 'string':557,563,569 'structur':116,326 'substitut':748 'success':265,289,328,329,341,497,539,580,770 'task':734 'templat':544 'test':112,604,628,664,706,718,721,754 'test-driven-develop':717 'test@example.com':626,643 'tobe':634,638,642,670 'tobeundefin':646 'tocontain':674 'token':385 'topic-agent-skills' 'topic-agentic-skills' 'topic-ai-agent-skills' 'topic-ai-agents' 'topic-ai-coding' 'topic-ai-workflows' 'topic-antigravity' 'topic-antigravity-skills' 'topic-claude-code' 'topic-claude-code-skills' 'topic-codex-cli' 'topic-codex-skills' 'total':349,487,504,507 'treat':743 'tri':208 'true':266,330,342,498,540,639 'unauthor':306 'updat':452 'use':47,371,683,728 'user':50,71,216,230,242,244,261,273,360,553,559,565,578,587,615,629,665 'user@example.com':598 'userschema':135 'userwithoutpassword':260,268 'valid':13,39,97,139,141,163,303,364,583,678,753 'validateus':126,146 'write':705","prices":[{"id":"2a23cce1-97e3-437a-83bc-e42deece3173","listingId":"895c82ca-0373-4b46-b62a-a0e90c22acf3","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"sickn33","category":"antigravity-awesome-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T21:31:07.944Z"}],"sources":[{"listingId":"895c82ca-0373-4b46-b62a-a0e90c22acf3","source":"github","sourceId":"sickn33/antigravity-awesome-skills/api-endpoint-builder","sourceUrl":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/api-endpoint-builder","isPrimary":false,"firstSeenAt":"2026-04-18T21:31:07.944Z","lastSeenAt":"2026-04-25T00:50:26.819Z"}],"details":{"listingId":"895c82ca-0373-4b46-b62a-a0e90c22acf3","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"sickn33","slug":"api-endpoint-builder","github":{"repo":"sickn33/antigravity-awesome-skills","stars":34964,"topics":["agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding","ai-workflows","antigravity","antigravity-skills","claude-code","claude-code-skills","codex-cli","codex-skills","cursor","cursor-skills","developer-tools","gemini-cli","gemini-skills","kiro","mcp","skill-library"],"license":"mit","html_url":"https://github.com/sickn33/antigravity-awesome-skills","pushed_at":"2026-04-24T06:41:17Z","description":"Installable GitHub library of 1,400+ agentic skills for Claude Code, Cursor, Codex CLI, Gemini CLI, Antigravity, and more. Includes installer CLI, bundles, workflows, and official/community skill collections.","skill_md_sha":"a745f09568cd5f1ed8a8850aef9e3a50765e895e","skill_md_path":"skills/api-endpoint-builder/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/api-endpoint-builder"},"layout":"multi","source":"github","category":"antigravity-awesome-skills","frontmatter":{"name":"api-endpoint-builder","description":"Builds production-ready REST API endpoints with validation, error handling, authentication, and documentation. Follows best practices for security and scalability."},"skills_sh_url":"https://skills.sh/sickn33/antigravity-awesome-skills/api-endpoint-builder"},"updatedAt":"2026-04-25T00:50:26.819Z"}}