From forge-skills
Use when designing REST endpoints, defining error envelopes, setting a versioning or deprecation policy, choosing pagination shape, adding idempotency to mutations, reviewing API contracts, or when two services need a stable interface between them.
How this skill is triggered — by the user, by Claude, or both
Slash command
/forge-skills:api-designThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Define the project's API conventions *before* endpoints proliferate. Output is `.forge/api-design.md` — verbs and status codes, the error envelope schema, versioning + deprecation policy, pagination/filter contract, rate-limiting envelope, auth/authz envelope, idempotency rules for mutations, and the public-vs-internal API boundary. Consumed by `architecture-and-contracts` (per-module contracts...
Define the project's API conventions before endpoints proliferate. Output is .forge/api-design.md — verbs and status codes, the error envelope schema, versioning + deprecation policy, pagination/filter contract, rate-limiting envelope, auth/authz envelope, idempotency rules for mutations, and the public-vs-internal API boundary. Consumed by architecture-and-contracts (per-module contracts inherit these), incremental-implementation (endpoints must conform), and code-review-and-quality (PR review checklist).
architecture-and-contracts)| Thought | Reality |
|---|---|
| "We'll version when we break something" | By then clients are coupled to the unversioned shape. Versioning costs nothing on day one, costs a migration on day 200. |
| "Every endpoint is different, no need to standardize" | Inconsistency is a bug, not flexibility. Every divergent error shape costs clients a special case. |
| "Just return 200 with an error field" | Clients can't distinguish success from failure without parsing the body. Proxies and CDNs cache 200s aggressively. |
| "Internal APIs don't need contracts" | Internal APIs become external APIs the moment a second team touches them. Two consumers = production interface. |
| "PATCH replaces the resource" | RFC 7396 says PATCH merges. Clients that depend on merge semantics will break silently if you replace. |
| "Idempotency keys are only for payments" | Network retries happen on every endpoint. Without idempotency, retries create duplicates everywhere. |
{ error: "..." } here, { message: "..." } there, raw string elsewhere)200 OK with { "success": false } in the bodyPATCH that replaces the resource entirelyPOST /payments with no idempotency key supportOFFSET/LIMIT pagination on a feed that will exceed 10k rows.forge/contracts/<module>.md is the authoritative source for module boundaries, operations, types, and error cases. api-design.md is the subordinate that defines how those operations map to HTTP (verbs, paths, envelope shape, error codes, versioning).
Rule: If .forge/contracts/ exists, read every contract first. Your API design must be consistent with the operations and error types they define. If a contract specifies RefundError with cases TransactionNotFound | RefundWindowExpired | AlreadyRefunded, the matching HTTP design must surface those exact codes — no inventing new ones, no collapsing them into a generic 400.
If a contract is missing an operation you need to expose (e.g., the PRD calls for refunds but PaymentService contract has no refund), do NOT add it to api-design.md alone — file /feedback targeting the contract so it gets updated upstream. Otherwise the two artifacts will diverge and forge-sync will flag a CONFLICT.
If no contracts exist yet, api-design.md may define the envelope policy in isolation, but the module boundaries it references will be back-filled when architecture-and-contracts runs.
Glob .forge/contracts/*.md. For each contract found:
ProvidesHold these as the source of truth. Every endpoint you design must trace back to a contract operation (or be flagged as new and worth a feedback entry).
GET (read), POST (create or non-idempotent action), PUT (replace), PATCH (merge per RFC 7396), DELETE (remove).2xx success only. 4xx for client errors. 5xx for server errors. Never 200 OK with error: true./users/{id}, /orders).Every error response uses the same shape. Write it in .forge/api-design.md:
{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "User not found.",
"field": "user_id",
"request_id": "01HABC...",
"details": {}
}
}
code — stable, machine-readable, screaming-snake-case. Clients pattern-match on this, never on message.message — human-readable, non-technical when surfaced to end users.field — populated for validation errors only.request_id — always populated; matches the correlation ID from observability.details — optional, structured per error code.Cross-reference the error-handling-and-resilience taxonomy (transient / permanent / user-correctable maps to retryable HTTP codes).
Choose one mechanism (URI /v1/, header Accept: application/vnd.api+json;version=1, or query ?version=1) and apply it everywhere. Document:
v1, never v0).Deprecation: <date> header + warnings in details.{ items: [], next_cursor: string|null, prev_cursor: string|null }. OFFSET/LIMIT only allowed for small admin endpoints.?status=active for exact match, ?status=active,pending for OR, ?created_after=... for ranges. No nested-query DSL unless the product justifies one.?sort=field ascending, ?sort=-field descending. Multi-sort: ?sort=-created_at,id.Idempotency-Key: <client-generated>. Server stores result keyed by (endpoint, key) for at least 24h. Replays return the original response.RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset. 429 on exceedance with Retry-After.Authorization: Bearer <token>. Errors use stable codes (AUTH_MISSING, AUTH_EXPIRED, AUTH_INVALID, FORBIDDEN). Never leak existence — 403 and 404 for "exists but you can't see it" both return 404 at the public boundary.In .forge/api-design.md: list every endpoint as public (versioned, deprecation-aware, hardened) or internal (faster iteration, still auth-gated, never reachable from internet). Internal endpoints get their own subdomain or VPC routing. Mixing the two on the same hostname guarantees future leaks.
Prepend a forge:meta header (generated_by: api-design, generated_at: <ISO 8601 UTC with Z>, depends_on: [.forge/architecture.md] — paths only, never hashes, generated_from: {.forge/architecture.md: <upstream content_hash AT generation time>}, content_hash: <sha256 first 8 of THIS file's body>). See forge-dependency-graph.
.forge/contracts/*.md read (or noted as absent); every endpoint traces back to a contract operation/feedback entry was filed targeting the contract — not silently added here.forge/api-design.md writtenIdempotency-Key header (or has a documented reason it doesn't need one)200 OK with { "success": false } anywhereRateLimit-* headers and a request_idnpx claudepluginhub aneja5/forge-skills --plugin forge-skillsSearches MemPalace before answering questions about past work, people, projects, or prior decisions. Returns verbatim stored content instead of guessing from model memory.
Guides Payload CMS config (payload.config.ts), collections, fields, hooks, access control, APIs. Debugs validation errors, security, relationships, queries, transactions, hook behavior.
Implements vector databases with Pinecone, Weaviate, Qdrant, Milvus, pgvector for semantic search, RAG, recommendations, and similarity systems. Optimizes embeddings, indexing, and hybrid search.