# API First

> API contract design workflow. Consumer-first resource modeling, error format standardization, and OpenAPI specification. Use when this capability is needed.

- Skill: `tomevault-io/api-first` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/api-first`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/api-first/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/api-first

---


When this skill is active, follow this 7-step discipline when designing an API:

## 1. Start from the Consumer

Design the API from the caller's perspective before writing any server code:
- **List every consumer**: screens, workflows, integrations, and third-party clients that will call this API
- **Write the ideal request and response** for each consumer — what would make integration trivial?
- **Identify shared resources** across consumers — these become your API entities
- **Document call sequences** for each workflow — which endpoints, in what order?

## 2. Model Resources

Map domain concepts to REST resources:
- **Nouns for resources** (`/users`, `/orders`), **verbs for actions** that don't fit CRUD (`/orders/{id}/cancel`)
- **Plural nouns consistently**: `/users/{id}`, not `/user/{id}`
- **Nest only for strong parent-child** relationships: `/users/{id}/addresses` — flatten everything else
- **Keep URLs shallow** — max 2 levels of nesting

## 3. Define Request and Response Shapes

Design the data contract for each endpoint:
- Use consistent field naming: `camelCase` for JSON, `snake_case` for query parameters
- Include only fields the consumer needs — no internal IDs, timestamps, or metadata unless requested
- Use envelope responses for collections: `{ "data": [...], "meta": { "total": 100, "page": 1 } }`
- Support partial responses with `?fields=name,email` for bandwidth-sensitive clients

## 4. Standardize Error Responses

Every error follows the same structure:
```json
{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "Human-readable description",
    "details": [{ "field": "email", "issue": "must be a valid email" }]
  }
}
```
- Use machine-readable `code` for client logic, `message` for display
- Map codes to HTTP status: 400 for validation, 401 for auth, 404 for missing, 409 for conflict, 429 for rate limit
- Include `details` array for field-level validation errors
- Never expose stack traces, SQL errors, or internal paths in error responses

## 5. Design Authentication and Authorization

Plan the security model before implementing endpoints:
- **Authentication**: who is calling? (API key, JWT, OAuth2)
- **Authorization**: what can they do? (RBAC, ABAC, resource ownership)
- **Default deny** — explicitly grant access per endpoint, never implicitly allow
- **Document per endpoint**: public, authenticated, or admin-only — this goes in the OpenAPI spec

## 6. Write the OpenAPI Specification

Produce a machine-readable contract before implementing:
- Write `openapi.yaml` (or `.json`) with paths, schemas, and examples
- Include `example` values for every schema property — consumers use these for mocking
- Use `$ref` for shared schemas — define once in `components/schemas/`, reference everywhere
- Validate the spec: `npx @redocly/cli lint openapi.yaml`

## 7. Verify the Contract

Confirm the API matches its specification:
- Generate client SDKs or types from the OpenAPI spec — if generation fails, the spec is wrong
- Write contract tests: each endpoint returns the documented status codes and response shapes
- Test error paths: invalid input, missing auth, nonexistent resources, rate limiting
- Run `npx @redocly/cli lint openapi.yaml` — zero warnings before merging
- If any check fails, fix the issue and re-run the entire chain

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/fricklers) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-14 -->

