{"id":"4911974a-a63c-4a2e-8bf3-e3511c8294b6","shortId":"XN7UvR","kind":"skill","title":"REST API Endpoint Designer","tagline":"Designs RESTful API endpoints following OpenAPI spec and industry best practices.","description":"# REST API Endpoint Designer\n\n## What this skill does\n\nThis skill directs the agent to design RESTful API endpoints for a given resource or feature — including URL structure, HTTP methods, request/response schemas, status codes, and error formats. It outputs a complete OpenAPI 3.1 YAML snippet that can be dropped directly into your API spec, along with implementation notes.\n\nUse this when starting a new API resource, reviewing an existing endpoint design, or when you want a second opinion on naming conventions and status code choices.\n\n## How to use\n\n### Claude Code / Cursor / Codex\n\nCopy this file to `.agents/skills/api-endpoint-designer/SKILL.md` in your project root (for Claude Code), or add the instructions to your `.cursorrules` (for Cursor).\n\nThen ask:\n- *\"Design the REST endpoints for a blog post resource using the REST API Endpoint Designer skill.\"*\n- *\"I need CRUD endpoints for a `team-members` resource. Use the REST API Endpoint Designer skill.\"*\n\nProvide the resource name, any existing conventions in your API (e.g., base path, auth method), and any fields the resource should have.\n\n## The Prompt / Instructions for the Agent\n\nWhen asked to design REST API endpoints, follow these rules:\n\n### 1. URL naming conventions\n\n- Use **plural nouns** for resource collections: `/users`, `/orders`, `/blog-posts`\n- Use **kebab-case** for multi-word resources: `/blog-posts`, not `/blogPosts`\n- Use path parameters for specific resources: `/users/{userId}`\n- Use **nested resources** only when the relationship is truly hierarchical: `/users/{userId}/orders`\n- Avoid verbs in URLs — the HTTP method is the verb: `POST /sessions` not `POST /login`\n- Use query parameters for filtering, sorting, and pagination: `GET /users?role=admin&sort=created_at&order=desc&page=2&limit=20`\n\n### 2. HTTP method selection\n\n| Action | Method | Notes |\n|---|---|---|\n| List resources | GET | Paginated, filterable |\n| Get one resource | GET | By ID in path |\n| Create | POST | Body contains new resource |\n| Full replace | PUT | Idempotent — replaces entire resource |\n| Partial update | PATCH | Only fields provided are updated |\n| Delete | DELETE | Returns 204 No Content on success |\n\n### 3. Status codes\n\nAlways return the most specific correct code:\n- `200` — success with body\n- `201` — resource created (include `Location` header)\n- `204` — success with no body (DELETE, some PATCH)\n- `400` — bad request / validation error (include which field failed)\n- `401` — not authenticated\n- `403` — authenticated but not authorized\n- `404` — resource not found\n- `409` — conflict (e.g., duplicate email)\n- `422` — unprocessable entity (semantic validation failed)\n- `500` — internal server error (never leak stack traces)\n\n### 4. Error response format\n\nAll error responses must follow this consistent shape:\n```json\n{\n  \"error\": {\n    \"code\": \"VALIDATION_ERROR\",\n    \"message\": \"Human-readable description\",\n    \"details\": [\n      { \"field\": \"email\", \"message\": \"must be a valid email address\" }\n    ]\n  }\n}\n```\n\n### 5. Output format\n\nProduce:\n1. A table listing each endpoint with method, path, description, and auth requirement\n2. An OpenAPI 3.1 YAML snippet for each endpoint\n3. Implementation notes (e.g., pagination defaults, required indexes, rate limiting recommendations)\n\n## Example\n\n**Input to Agent:**\n> \"Design CRUD endpoints for a `posts` resource. Fields: title (string, required), body (string, required), authorId (string, required), status (draft | published, default: draft). Auth is required for create/update/delete. Use the REST API Endpoint Designer skill.\"\n\n**Output from Agent:**\n\n**Endpoints**\n\n| Method | Path | Description | Auth Required |\n|---|---|---|---|\n| GET | /posts | List posts (paginated, filterable by status) | No |\n| GET | /posts/{postId} | Get a single post | No |\n| POST | /posts | Create a new post | Yes |\n| PATCH | /posts/{postId} | Update post fields | Yes (author only) |\n| DELETE | /posts/{postId} | Delete a post | Yes (author only) |\n\n**OpenAPI YAML**\n\n```yaml\npaths:\n  /posts:\n    get:\n      summary: List posts\n      operationId: listPosts\n      tags: [Posts]\n      parameters:\n        - name: status\n          in: query\n          schema:\n            type: string\n            enum: [draft, published]\n        - name: page\n          in: query\n          schema:\n            type: integer\n            default: 1\n        - name: limit\n          in: query\n          schema:\n            type: integer\n            default: 20\n            maximum: 100\n      responses:\n        '200':\n          description: Paginated list of posts\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  data:\n                    type: array\n                    items:\n                      $ref: '#/components/schemas/Post'\n                  meta:\n                    $ref: '#/components/schemas/PaginationMeta'\n\n    post:\n      summary: Create a post\n      operationId: createPost\n      tags: [Posts]\n      security:\n        - bearerAuth: []\n      requestBody:\n        required: true\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/CreatePostInput'\n      responses:\n        '201':\n          description: Post created\n          headers:\n            Location:\n              schema:\n                type: string\n                example: /posts/abc123\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Post'\n        '400':\n          $ref: '#/components/responses/ValidationError'\n        '401':\n          $ref: '#/components/responses/Unauthorized'\n\n  /posts/{postId}:\n    get:\n      summary: Get a post\n      operationId: getPost\n      tags: [Posts]\n      parameters:\n        - $ref: '#/components/parameters/PostId'\n      responses:\n        '200':\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Post'\n        '404':\n          $ref: '#/components/responses/NotFound'\n\n    patch:\n      summary: Update a post\n      operationId: updatePost\n      tags: [Posts]\n      security:\n        - bearerAuth: []\n      parameters:\n        - $ref: '#/components/parameters/PostId'\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/UpdatePostInput'\n      responses:\n        '200':\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Post'\n        '403':\n          $ref: '#/components/responses/Forbidden'\n        '404':\n          $ref: '#/components/responses/NotFound'\n\n    delete:\n      summary: Delete a post\n      operationId: deletePost\n      tags: [Posts]\n      security:\n        - bearerAuth: []\n      parameters:\n        - $ref: '#/components/parameters/PostId'\n      responses:\n        '204':\n          description: Post deleted\n        '403':\n          $ref: '#/components/responses/Forbidden'\n        '404':\n          $ref: '#/components/responses/NotFound'\n```\n\n**Implementation Notes**\n- Index `posts.status` and `posts.authorId` for the list endpoint filters\n- Enforce `limit <= 100` server-side, not just in the spec\n- `PATCH /posts/{postId}` should check `authorId === currentUser.id` before applying changes — return `403` if not\n- Consider a `GET /posts?authorId={userId}` filter for profile pages\n\n## Notes\n\n- By default this skill outputs OpenAPI 3.1 YAML. Ask for JSON or an earlier version (3.0, 2.0/Swagger) if needed.\n- The skill does not generate implementation code — only the API contract. Use the Unit Test Writer or another skill for implementation.\n- For GraphQL or gRPC APIs, this skill is not the right tool — it is designed for REST only.","tags":["api","endpoint","designer","openagentskills","notysoty","agent-skills","claude","claude-code","claude-skills","cline","cursor","llm"],"capabilities":["skill","source-notysoty","skill-api-endpoint-designer","topic-agent-skills","topic-claude","topic-claude-code","topic-claude-skills","topic-cline","topic-cursor","topic-llm","topic-llm-skills","topic-skills"],"categories":["openagentskills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/Notysoty/openagentskills/api-endpoint-designer","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add Notysoty/openagentskills","source_repo":"https://github.com/Notysoty/openagentskills","install_from":"skills.sh"}},"qualityScore":"0.454","qualityRationale":"deterministic score 0.45 from registry signals: · indexed on github topic:agent-skills · 8 github stars · SKILL.md body (7,801 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-05-18T19:13:20.196Z","embedding":null,"createdAt":"2026-05-18T13:20:40.575Z","updatedAt":"2026-05-18T19:13:20.196Z","lastSeenAt":"2026-05-18T19:13:20.196Z","tsv":"'/blog-posts':213,223 '/blogposts':225 '/components/parameters/postid':679,703,736 '/components/responses/forbidden':719,744 '/components/responses/notfound':689,722,747 '/components/responses/unauthorized':665 '/components/responses/validationerror':662 '/components/schemas/createpostinput':642 '/components/schemas/paginationmeta':623 '/components/schemas/post':620,659,686,716 '/components/schemas/updatepostinput':709 '/login':261 '/orders':212,246 '/posts':517,526,534,541,550,562,666,771,787 '/posts/abc123':654 '/sessions':258 '/swagger':812 '/users':211,232,244,271 '1':201,436,590 '100':601,761 '2':280,283,449 '2.0':811 '20':282,599 '200':342,603,681,711 '201':346,644 '204':327,352,738 '3':332,458 '3.0':810 '3.1':57,452,801 '4':400 '400':360,660 '401':369,663 '403':372,717,742,781 '404':377,687,720,745 '409':381 '422':386 '5':432 '500':392 'action':287 'add':120 'address':431 'admin':273 'agent':28,190,472,509 'agents/skills/api-endpoint-designer/skill.md':111 'along':69 'alway':335 'anoth':832 'api':2,7,17,32,67,79,142,159,172,196,503,824,840 'appli':778 'application/json':610,639,656,683,706,713 'array':617 'ask':129,192,803 'auth':176,447,495,514 'authent':371,373 'author':376,547,556 'authorid':487,775,788 'avoid':247 'bad':361 'base':174 'bearerauth':634,700,733 'best':14 'blog':136 'bodi':305,345,356,484 'case':217 'chang':779 'check':774 'choic':99 'claud':103,117 'code':48,98,104,118,334,341,414,821 'codex':106 'collect':210 'complet':55 'conflict':382 'consid':784 'consist':410 'contain':306 'content':329,609,638,655,682,705,712 'contract':825 'convent':95,169,204 'copi':107 'correct':340 'creat':275,303,348,535,626,647 'create/update/delete':499 'createpost':630 'crud':148,474 'currentuser.id':776 'cursor':105,127 'cursorrul':125 'data':615 'default':463,493,589,598,796 'delet':324,325,357,549,552,723,725,741 'deletepost':729 'desc':278 'descript':421,445,513,604,645,739 'design':4,5,19,30,85,130,144,161,194,473,505,850 'detail':422 'direct':26,64 'draft':491,494,580 'drop':63 'duplic':384 'e.g':173,383,461 'earlier':808 'email':385,424,430 'endpoint':3,8,18,33,84,133,143,149,160,197,441,457,475,504,510,757 'enforc':759 'entir':314 'entiti':388 'enum':579 'error':50,364,395,401,405,413,416 'exampl':469,653 'exist':83,168 'fail':368,391 'featur':39 'field':180,320,367,423,480,545 'file':109 'filter':266,294,521,758,790 'follow':9,198,408 'format':51,403,434 'found':380 'full':309 'generat':819 'get':270,292,295,298,516,525,528,563,668,670,786 'getpost':674 'given':36 'graphql':837 'grpc':839 'header':351,648 'hierarch':243 'http':43,252,284 'human':419 'human-read':418 'id':300 'idempot':312 'implement':71,459,748,820,835 'includ':40,349,365 'index':465,750 'industri':13 'input':470 'instruct':122,187 'integ':588,597 'intern':393 'item':618 'json':412,805 'kebab':216 'kebab-cas':215 'leak':397 'limit':281,467,592,760 'list':290,439,518,565,606,756 'listpost':568 'locat':350,649 'maximum':600 'member':154 'messag':417,425 'meta':621 'method':44,177,253,285,288,443,511 'multi':220 'multi-word':219 'must':407,426 'name':94,166,203,572,582,591 'need':147,814 'nest':235 'never':396 'new':78,307,537 'note':72,289,460,749,794 'noun':207 'object':613 'one':296 'openapi':10,56,451,558,800 'operationid':567,629,673,695,728 'opinion':92 'order':277 'output':53,433,507,799 'page':279,583,793 'pagin':269,293,462,520,605 'paramet':228,264,571,677,701,734 'partial':316 'patch':318,359,540,690,770 'path':175,227,302,444,512,561 'plural':206 'post':137,257,260,304,478,519,531,533,538,544,554,566,570,608,624,628,632,646,672,676,694,698,727,731,740 'postid':527,542,551,667,772 'posts.authorid':753 'posts.status':751 'practic':15 'produc':435 'profil':792 'project':114 'prompt':186 'properti':614 'provid':163,321 'publish':492,581 'put':311 'queri':263,575,585,594 'rate':466 'readabl':420 'recommend':468 'ref':619,622,641,658,661,664,678,685,688,702,708,715,718,721,735,743,746 'relationship':240 'replac':310,313 'request':362 'request/response':45 'requestbodi':635,704 'requir':448,464,483,486,489,497,515,636 'resourc':37,80,138,155,165,182,209,222,231,236,291,297,308,315,347,378,479 'respons':402,406,602,643,680,710,737 'rest':1,6,16,31,132,141,158,195,502,852 'return':326,336,780 'review':81 'right':846 'role':272 'root':115 'rule':200 'schema':46,576,586,595,611,640,650,657,684,707,714 'second':91 'secur':633,699,732 'select':286 'semant':389 'server':394,763 'server-sid':762 'shape':411 'side':764 'singl':530 'skill':22,25,145,162,506,798,816,833,842 'skill-api-endpoint-designer' 'snippet':59,454 'sort':267,274 'source-notysoty' 'spec':11,68,769 'specif':230,339 'stack':398 'start':76 'status':47,97,333,490,523,573 'string':482,485,488,578,652 'structur':42 'success':331,343,353 'summari':564,625,669,691,724 'tabl':438 'tag':569,631,675,697,730 'team':153 'team-memb':152 'test':829 'titl':481 'tool':847 'topic-agent-skills' 'topic-claude' 'topic-claude-code' 'topic-claude-skills' 'topic-cline' 'topic-cursor' 'topic-llm' 'topic-llm-skills' 'topic-skills' 'trace':399 'true':637 'truli':242 'type':577,587,596,612,616,651 'unit':828 'unprocess':387 'updat':317,323,543,692 'updatepost':696 'url':41,202,250 'use':73,102,139,156,205,214,226,234,262,500,826 'userid':233,245,789 'valid':363,390,415,429 'verb':248,256 'version':809 'want':89 'word':221 'writer':830 'yaml':58,453,559,560,802 'yes':539,546,555","prices":[{"id":"e9112462-2d3f-4f95-82cb-c3f9891d0f29","listingId":"4911974a-a63c-4a2e-8bf3-e3511c8294b6","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"Notysoty","category":"openagentskills","install_from":"skills.sh"},"createdAt":"2026-05-18T13:20:40.575Z"}],"sources":[{"listingId":"4911974a-a63c-4a2e-8bf3-e3511c8294b6","source":"github","sourceId":"Notysoty/openagentskills/api-endpoint-designer","sourceUrl":"https://github.com/Notysoty/openagentskills/tree/main/skills/api-endpoint-designer","isPrimary":false,"firstSeenAt":"2026-05-18T13:20:40.575Z","lastSeenAt":"2026-05-18T19:13:20.196Z"}],"details":{"listingId":"4911974a-a63c-4a2e-8bf3-e3511c8294b6","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"Notysoty","slug":"api-endpoint-designer","github":{"repo":"Notysoty/openagentskills","stars":8,"topics":["agent-skills","claude","claude-code","claude-skills","cline","cursor","llm","llm-skills","skills"],"license":"mit","html_url":"https://github.com/Notysoty/openagentskills","pushed_at":"2026-03-28T06:50:19Z","description":"A  community-driven library of reusable AI agent skills for Claude Code, Cursor, Codex, Cline, and more.","skill_md_sha":"8c2de9fa83dcb6a9b33fe7f1d81864db59cb99c8","skill_md_path":"skills/api-endpoint-designer/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/Notysoty/openagentskills/tree/main/skills/api-endpoint-designer"},"layout":"multi","source":"github","category":"openagentskills","frontmatter":{"name":"REST API Endpoint Designer","description":"Designs RESTful API endpoints following OpenAPI spec and industry best practices."},"skills_sh_url":"https://skills.sh/Notysoty/openagentskills/api-endpoint-designer"},"updatedAt":"2026-05-18T19:13:20.196Z"}}