@wazir-dev/cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +111 -0
- package/CHANGELOG.md +14 -0
- package/CONTRIBUTING.md +101 -0
- package/LICENSE +21 -0
- package/README.md +314 -0
- package/assets/composition-engine.mmd +34 -0
- package/assets/demo-script.sh +17 -0
- package/assets/logo-dark.svg +14 -0
- package/assets/logo.svg +14 -0
- package/assets/pipeline.mmd +39 -0
- package/assets/record-demo.sh +51 -0
- package/docs/README.md +51 -0
- package/docs/adapters/context-mode.md +60 -0
- package/docs/concepts/architecture.md +87 -0
- package/docs/concepts/artifact-model.md +60 -0
- package/docs/concepts/composition-engine.md +36 -0
- package/docs/concepts/indexing-and-recall.md +160 -0
- package/docs/concepts/observability.md +41 -0
- package/docs/concepts/roles-and-workflows.md +59 -0
- package/docs/concepts/terminology-policy.md +27 -0
- package/docs/getting-started/01-installation.md +78 -0
- package/docs/getting-started/02-first-run.md +102 -0
- package/docs/getting-started/03-adding-to-project.md +15 -0
- package/docs/getting-started/04-host-setup.md +15 -0
- package/docs/guides/ci-integration.md +15 -0
- package/docs/guides/creating-skills.md +15 -0
- package/docs/guides/expertise-module-authoring.md +15 -0
- package/docs/guides/hook-development.md +15 -0
- package/docs/guides/memory-and-learnings.md +34 -0
- package/docs/guides/multi-host-export.md +15 -0
- package/docs/guides/troubleshooting.md +101 -0
- package/docs/guides/writing-custom-roles.md +15 -0
- package/docs/plans/2026-03-15-cli-pipeline-integration-design.md +592 -0
- package/docs/plans/2026-03-15-cli-pipeline-integration-plan.md +598 -0
- package/docs/plans/2026-03-15-docs-enforcement-plan.md +238 -0
- package/docs/readmes/INDEX.md +99 -0
- package/docs/readmes/features/expertise/README.md +171 -0
- package/docs/readmes/features/exports/README.md +222 -0
- package/docs/readmes/features/hooks/README.md +103 -0
- package/docs/readmes/features/hooks/loop-cap-guard.md +133 -0
- package/docs/readmes/features/hooks/post-tool-capture.md +121 -0
- package/docs/readmes/features/hooks/post-tool-lint.md +130 -0
- package/docs/readmes/features/hooks/pre-compact-summary.md +122 -0
- package/docs/readmes/features/hooks/pre-tool-capture-route.md +100 -0
- package/docs/readmes/features/hooks/protected-path-write-guard.md +128 -0
- package/docs/readmes/features/hooks/session-start.md +119 -0
- package/docs/readmes/features/hooks/stop-handoff-harvest.md +125 -0
- package/docs/readmes/features/roles/README.md +157 -0
- package/docs/readmes/features/roles/clarifier.md +152 -0
- package/docs/readmes/features/roles/content-author.md +190 -0
- package/docs/readmes/features/roles/designer.md +193 -0
- package/docs/readmes/features/roles/executor.md +184 -0
- package/docs/readmes/features/roles/learner.md +210 -0
- package/docs/readmes/features/roles/planner.md +182 -0
- package/docs/readmes/features/roles/researcher.md +164 -0
- package/docs/readmes/features/roles/reviewer.md +184 -0
- package/docs/readmes/features/roles/specifier.md +162 -0
- package/docs/readmes/features/roles/verifier.md +215 -0
- package/docs/readmes/features/schemas/README.md +178 -0
- package/docs/readmes/features/skills/README.md +63 -0
- package/docs/readmes/features/skills/brainstorming.md +96 -0
- package/docs/readmes/features/skills/debugging.md +148 -0
- package/docs/readmes/features/skills/design.md +120 -0
- package/docs/readmes/features/skills/prepare-next.md +109 -0
- package/docs/readmes/features/skills/run-audit.md +159 -0
- package/docs/readmes/features/skills/scan-project.md +109 -0
- package/docs/readmes/features/skills/self-audit.md +176 -0
- package/docs/readmes/features/skills/tdd.md +137 -0
- package/docs/readmes/features/skills/using-skills.md +92 -0
- package/docs/readmes/features/skills/verification.md +120 -0
- package/docs/readmes/features/skills/writing-plans.md +104 -0
- package/docs/readmes/features/tooling/README.md +320 -0
- package/docs/readmes/features/workflows/README.md +186 -0
- package/docs/readmes/features/workflows/author.md +181 -0
- package/docs/readmes/features/workflows/clarify.md +154 -0
- package/docs/readmes/features/workflows/design-review.md +171 -0
- package/docs/readmes/features/workflows/design.md +169 -0
- package/docs/readmes/features/workflows/discover.md +162 -0
- package/docs/readmes/features/workflows/execute.md +173 -0
- package/docs/readmes/features/workflows/learn.md +167 -0
- package/docs/readmes/features/workflows/plan-review.md +165 -0
- package/docs/readmes/features/workflows/plan.md +170 -0
- package/docs/readmes/features/workflows/prepare-next.md +167 -0
- package/docs/readmes/features/workflows/review.md +169 -0
- package/docs/readmes/features/workflows/run-audit.md +191 -0
- package/docs/readmes/features/workflows/spec-challenge.md +159 -0
- package/docs/readmes/features/workflows/specify.md +160 -0
- package/docs/readmes/features/workflows/verify.md +177 -0
- package/docs/readmes/packages/README.md +50 -0
- package/docs/readmes/packages/ajv.md +117 -0
- package/docs/readmes/packages/context-mode.md +118 -0
- package/docs/readmes/packages/gray-matter.md +116 -0
- package/docs/readmes/packages/node-test.md +137 -0
- package/docs/readmes/packages/yaml.md +112 -0
- package/docs/reference/configuration-reference.md +159 -0
- package/docs/reference/expertise-index.md +52 -0
- package/docs/reference/git-flow.md +43 -0
- package/docs/reference/hooks.md +87 -0
- package/docs/reference/host-exports.md +50 -0
- package/docs/reference/launch-checklist.md +172 -0
- package/docs/reference/marketplace-listings.md +76 -0
- package/docs/reference/release-process.md +34 -0
- package/docs/reference/roles-reference.md +77 -0
- package/docs/reference/skills.md +33 -0
- package/docs/reference/templates.md +29 -0
- package/docs/reference/tooling-cli.md +94 -0
- package/docs/truth-claims.yaml +222 -0
- package/expertise/PROGRESS.md +63 -0
- package/expertise/README.md +18 -0
- package/expertise/antipatterns/PROGRESS.md +56 -0
- package/expertise/antipatterns/backend/api-design-antipatterns.md +1271 -0
- package/expertise/antipatterns/backend/auth-antipatterns.md +1195 -0
- package/expertise/antipatterns/backend/caching-antipatterns.md +622 -0
- package/expertise/antipatterns/backend/database-antipatterns.md +1038 -0
- package/expertise/antipatterns/backend/index.md +24 -0
- package/expertise/antipatterns/backend/microservices-antipatterns.md +850 -0
- package/expertise/antipatterns/code/architecture-antipatterns.md +919 -0
- package/expertise/antipatterns/code/async-antipatterns.md +622 -0
- package/expertise/antipatterns/code/code-smells.md +1186 -0
- package/expertise/antipatterns/code/dependency-antipatterns.md +1209 -0
- package/expertise/antipatterns/code/error-handling-antipatterns.md +1360 -0
- package/expertise/antipatterns/code/index.md +27 -0
- package/expertise/antipatterns/code/naming-and-abstraction.md +1118 -0
- package/expertise/antipatterns/code/state-management-antipatterns.md +1076 -0
- package/expertise/antipatterns/code/testing-antipatterns.md +1053 -0
- package/expertise/antipatterns/design/accessibility-antipatterns.md +1136 -0
- package/expertise/antipatterns/design/dark-patterns.md +1121 -0
- package/expertise/antipatterns/design/index.md +22 -0
- package/expertise/antipatterns/design/ui-antipatterns.md +1202 -0
- package/expertise/antipatterns/design/ux-antipatterns.md +680 -0
- package/expertise/antipatterns/frontend/css-layout-antipatterns.md +691 -0
- package/expertise/antipatterns/frontend/flutter-antipatterns.md +1827 -0
- package/expertise/antipatterns/frontend/index.md +23 -0
- package/expertise/antipatterns/frontend/mobile-antipatterns.md +573 -0
- package/expertise/antipatterns/frontend/react-antipatterns.md +1128 -0
- package/expertise/antipatterns/frontend/spa-antipatterns.md +1235 -0
- package/expertise/antipatterns/index.md +31 -0
- package/expertise/antipatterns/performance/index.md +20 -0
- package/expertise/antipatterns/performance/performance-antipatterns.md +1013 -0
- package/expertise/antipatterns/performance/premature-optimization.md +623 -0
- package/expertise/antipatterns/performance/scaling-antipatterns.md +785 -0
- package/expertise/antipatterns/process/ai-coding-antipatterns.md +853 -0
- package/expertise/antipatterns/process/code-review-antipatterns.md +656 -0
- package/expertise/antipatterns/process/deployment-antipatterns.md +920 -0
- package/expertise/antipatterns/process/index.md +23 -0
- package/expertise/antipatterns/process/technical-debt-antipatterns.md +647 -0
- package/expertise/antipatterns/security/index.md +20 -0
- package/expertise/antipatterns/security/secrets-antipatterns.md +849 -0
- package/expertise/antipatterns/security/security-theater.md +843 -0
- package/expertise/antipatterns/security/vulnerability-patterns.md +801 -0
- package/expertise/architecture/PROGRESS.md +70 -0
- package/expertise/architecture/data/caching-architecture.md +671 -0
- package/expertise/architecture/data/data-consistency.md +574 -0
- package/expertise/architecture/data/data-modeling.md +536 -0
- package/expertise/architecture/data/event-streams-and-queues.md +634 -0
- package/expertise/architecture/data/index.md +25 -0
- package/expertise/architecture/data/search-architecture.md +663 -0
- package/expertise/architecture/data/sql-vs-nosql.md +708 -0
- package/expertise/architecture/decisions/architecture-decision-records.md +640 -0
- package/expertise/architecture/decisions/build-vs-buy.md +616 -0
- package/expertise/architecture/decisions/index.md +23 -0
- package/expertise/architecture/decisions/monolith-to-microservices.md +790 -0
- package/expertise/architecture/decisions/technology-selection.md +616 -0
- package/expertise/architecture/distributed/cap-theorem-and-tradeoffs.md +800 -0
- package/expertise/architecture/distributed/circuit-breaker-bulkhead.md +741 -0
- package/expertise/architecture/distributed/consensus-and-coordination.md +796 -0
- package/expertise/architecture/distributed/distributed-systems-fundamentals.md +564 -0
- package/expertise/architecture/distributed/idempotency-and-retry.md +796 -0
- package/expertise/architecture/distributed/index.md +25 -0
- package/expertise/architecture/distributed/saga-pattern.md +797 -0
- package/expertise/architecture/foundations/architectural-thinking.md +460 -0
- package/expertise/architecture/foundations/coupling-and-cohesion.md +770 -0
- package/expertise/architecture/foundations/design-principles-solid.md +649 -0
- package/expertise/architecture/foundations/domain-driven-design.md +719 -0
- package/expertise/architecture/foundations/index.md +25 -0
- package/expertise/architecture/foundations/separation-of-concerns.md +472 -0
- package/expertise/architecture/foundations/twelve-factor-app.md +797 -0
- package/expertise/architecture/index.md +34 -0
- package/expertise/architecture/integration/api-design-graphql.md +638 -0
- package/expertise/architecture/integration/api-design-grpc.md +804 -0
- package/expertise/architecture/integration/api-design-rest.md +892 -0
- package/expertise/architecture/integration/index.md +25 -0
- package/expertise/architecture/integration/third-party-integration.md +795 -0
- package/expertise/architecture/integration/webhooks-and-callbacks.md +1152 -0
- package/expertise/architecture/integration/websockets-realtime.md +791 -0
- package/expertise/architecture/mobile-architecture/index.md +22 -0
- package/expertise/architecture/mobile-architecture/mobile-app-architecture.md +780 -0
- package/expertise/architecture/mobile-architecture/mobile-backend-for-frontend.md +670 -0
- package/expertise/architecture/mobile-architecture/offline-first.md +719 -0
- package/expertise/architecture/mobile-architecture/push-and-sync.md +782 -0
- package/expertise/architecture/patterns/cqrs-event-sourcing.md +717 -0
- package/expertise/architecture/patterns/event-driven.md +797 -0
- package/expertise/architecture/patterns/hexagonal-clean-architecture.md +870 -0
- package/expertise/architecture/patterns/index.md +27 -0
- package/expertise/architecture/patterns/layered-architecture.md +736 -0
- package/expertise/architecture/patterns/microservices.md +753 -0
- package/expertise/architecture/patterns/modular-monolith.md +692 -0
- package/expertise/architecture/patterns/monolith.md +626 -0
- package/expertise/architecture/patterns/plugin-architecture.md +735 -0
- package/expertise/architecture/patterns/serverless.md +780 -0
- package/expertise/architecture/scaling/database-scaling.md +615 -0
- package/expertise/architecture/scaling/feature-flags-and-rollouts.md +757 -0
- package/expertise/architecture/scaling/horizontal-vs-vertical.md +606 -0
- package/expertise/architecture/scaling/index.md +24 -0
- package/expertise/architecture/scaling/multi-tenancy.md +800 -0
- package/expertise/architecture/scaling/stateless-design.md +787 -0
- package/expertise/backend/embedded-firmware.md +625 -0
- package/expertise/backend/go.md +853 -0
- package/expertise/backend/index.md +24 -0
- package/expertise/backend/java-spring.md +448 -0
- package/expertise/backend/node-typescript.md +625 -0
- package/expertise/backend/python-fastapi.md +724 -0
- package/expertise/backend/rust.md +458 -0
- package/expertise/backend/solidity.md +711 -0
- package/expertise/composition-map.yaml +443 -0
- package/expertise/content/foundations/content-modeling.md +395 -0
- package/expertise/content/foundations/editorial-standards.md +449 -0
- package/expertise/content/foundations/index.md +24 -0
- package/expertise/content/foundations/microcopy.md +455 -0
- package/expertise/content/foundations/terminology-governance.md +509 -0
- package/expertise/content/index.md +34 -0
- package/expertise/content/patterns/accessibility-copy.md +518 -0
- package/expertise/content/patterns/index.md +24 -0
- package/expertise/content/patterns/notification-content.md +433 -0
- package/expertise/content/patterns/sample-content.md +486 -0
- package/expertise/content/patterns/state-copy.md +439 -0
- package/expertise/design/PROGRESS.md +58 -0
- package/expertise/design/disciplines/dark-mode-theming.md +577 -0
- package/expertise/design/disciplines/design-systems.md +595 -0
- package/expertise/design/disciplines/index.md +25 -0
- package/expertise/design/disciplines/information-architecture.md +800 -0
- package/expertise/design/disciplines/interaction-design.md +788 -0
- package/expertise/design/disciplines/responsive-design.md +552 -0
- package/expertise/design/disciplines/usability-testing.md +516 -0
- package/expertise/design/disciplines/user-research.md +792 -0
- package/expertise/design/foundations/accessibility-design.md +796 -0
- package/expertise/design/foundations/color-theory.md +797 -0
- package/expertise/design/foundations/iconography.md +795 -0
- package/expertise/design/foundations/index.md +26 -0
- package/expertise/design/foundations/motion-and-animation.md +653 -0
- package/expertise/design/foundations/rtl-design.md +585 -0
- package/expertise/design/foundations/spacing-and-layout.md +607 -0
- package/expertise/design/foundations/typography.md +800 -0
- package/expertise/design/foundations/visual-hierarchy.md +761 -0
- package/expertise/design/index.md +32 -0
- package/expertise/design/patterns/authentication-flows.md +474 -0
- package/expertise/design/patterns/content-consumption.md +789 -0
- package/expertise/design/patterns/data-display.md +618 -0
- package/expertise/design/patterns/e-commerce.md +1494 -0
- package/expertise/design/patterns/feedback-and-states.md +642 -0
- package/expertise/design/patterns/forms-and-input.md +819 -0
- package/expertise/design/patterns/gamification.md +801 -0
- package/expertise/design/patterns/index.md +31 -0
- package/expertise/design/patterns/microinteractions.md +449 -0
- package/expertise/design/patterns/navigation.md +800 -0
- package/expertise/design/patterns/notifications.md +705 -0
- package/expertise/design/patterns/onboarding.md +700 -0
- package/expertise/design/patterns/search-and-filter.md +601 -0
- package/expertise/design/patterns/settings-and-preferences.md +768 -0
- package/expertise/design/patterns/social-and-community.md +748 -0
- package/expertise/design/platforms/desktop-native.md +612 -0
- package/expertise/design/platforms/index.md +25 -0
- package/expertise/design/platforms/mobile-android.md +825 -0
- package/expertise/design/platforms/mobile-cross-platform.md +983 -0
- package/expertise/design/platforms/mobile-ios.md +699 -0
- package/expertise/design/platforms/tablet.md +794 -0
- package/expertise/design/platforms/web-dashboard.md +790 -0
- package/expertise/design/platforms/web-responsive.md +550 -0
- package/expertise/design/psychology/behavioral-nudges.md +449 -0
- package/expertise/design/psychology/cognitive-load.md +1191 -0
- package/expertise/design/psychology/error-psychology.md +778 -0
- package/expertise/design/psychology/index.md +22 -0
- package/expertise/design/psychology/persuasive-design.md +736 -0
- package/expertise/design/psychology/user-mental-models.md +623 -0
- package/expertise/design/tooling/open-pencil.md +266 -0
- package/expertise/frontend/angular.md +1073 -0
- package/expertise/frontend/desktop-electron.md +546 -0
- package/expertise/frontend/flutter.md +782 -0
- package/expertise/frontend/index.md +27 -0
- package/expertise/frontend/native-android.md +409 -0
- package/expertise/frontend/native-ios.md +490 -0
- package/expertise/frontend/react-native.md +1160 -0
- package/expertise/frontend/react.md +808 -0
- package/expertise/frontend/vue.md +1089 -0
- package/expertise/humanize/domain-rules-code.md +79 -0
- package/expertise/humanize/domain-rules-content.md +67 -0
- package/expertise/humanize/domain-rules-technical-docs.md +56 -0
- package/expertise/humanize/index.md +35 -0
- package/expertise/humanize/self-audit-checklist.md +87 -0
- package/expertise/humanize/sentence-patterns.md +218 -0
- package/expertise/humanize/vocabulary-blacklist.md +105 -0
- package/expertise/i18n/PROGRESS.md +65 -0
- package/expertise/i18n/advanced/accessibility-and-i18n.md +28 -0
- package/expertise/i18n/advanced/bidirectional-text-algorithm.md +38 -0
- package/expertise/i18n/advanced/complex-scripts.md +30 -0
- package/expertise/i18n/advanced/performance-and-i18n.md +27 -0
- package/expertise/i18n/advanced/testing-i18n.md +28 -0
- package/expertise/i18n/content/content-adaptation.md +23 -0
- package/expertise/i18n/content/locale-specific-formatting.md +23 -0
- package/expertise/i18n/content/machine-translation-integration.md +28 -0
- package/expertise/i18n/content/translation-management.md +29 -0
- package/expertise/i18n/foundations/date-time-calendars.md +67 -0
- package/expertise/i18n/foundations/i18n-architecture.md +272 -0
- package/expertise/i18n/foundations/locale-and-language-tags.md +79 -0
- package/expertise/i18n/foundations/numbers-currency-units.md +61 -0
- package/expertise/i18n/foundations/pluralization-and-gender.md +109 -0
- package/expertise/i18n/foundations/string-externalization.md +236 -0
- package/expertise/i18n/foundations/text-direction-bidi.md +241 -0
- package/expertise/i18n/foundations/unicode-and-encoding.md +86 -0
- package/expertise/i18n/index.md +38 -0
- package/expertise/i18n/platform/backend-i18n.md +31 -0
- package/expertise/i18n/platform/flutter-i18n.md +148 -0
- package/expertise/i18n/platform/native-android-i18n.md +36 -0
- package/expertise/i18n/platform/native-ios-i18n.md +36 -0
- package/expertise/i18n/platform/react-i18n.md +103 -0
- package/expertise/i18n/platform/web-css-i18n.md +81 -0
- package/expertise/i18n/rtl/arabic-specific.md +175 -0
- package/expertise/i18n/rtl/hebrew-specific.md +149 -0
- package/expertise/i18n/rtl/rtl-animations-and-transitions.md +111 -0
- package/expertise/i18n/rtl/rtl-forms-and-input.md +161 -0
- package/expertise/i18n/rtl/rtl-fundamentals.md +211 -0
- package/expertise/i18n/rtl/rtl-icons-and-images.md +181 -0
- package/expertise/i18n/rtl/rtl-layout-mirroring.md +252 -0
- package/expertise/i18n/rtl/rtl-navigation-and-gestures.md +107 -0
- package/expertise/i18n/rtl/rtl-testing-and-qa.md +147 -0
- package/expertise/i18n/rtl/rtl-typography.md +160 -0
- package/expertise/index.md +113 -0
- package/expertise/index.yaml +216 -0
- package/expertise/infrastructure/cloud-aws.md +597 -0
- package/expertise/infrastructure/cloud-gcp.md +599 -0
- package/expertise/infrastructure/cybersecurity.md +816 -0
- package/expertise/infrastructure/database-mongodb.md +447 -0
- package/expertise/infrastructure/database-postgres.md +400 -0
- package/expertise/infrastructure/devops-cicd.md +787 -0
- package/expertise/infrastructure/index.md +27 -0
- package/expertise/performance/PROGRESS.md +50 -0
- package/expertise/performance/backend/api-latency.md +1204 -0
- package/expertise/performance/backend/background-jobs.md +506 -0
- package/expertise/performance/backend/connection-pooling.md +1209 -0
- package/expertise/performance/backend/database-query-optimization.md +515 -0
- package/expertise/performance/backend/index.md +23 -0
- package/expertise/performance/backend/rate-limiting-and-throttling.md +971 -0
- package/expertise/performance/foundations/algorithmic-complexity.md +954 -0
- package/expertise/performance/foundations/caching-strategies.md +489 -0
- package/expertise/performance/foundations/concurrency-and-parallelism.md +847 -0
- package/expertise/performance/foundations/index.md +24 -0
- package/expertise/performance/foundations/measuring-and-profiling.md +440 -0
- package/expertise/performance/foundations/memory-management.md +964 -0
- package/expertise/performance/foundations/performance-budgets.md +1314 -0
- package/expertise/performance/index.md +31 -0
- package/expertise/performance/infrastructure/auto-scaling.md +1059 -0
- package/expertise/performance/infrastructure/cdn-and-edge.md +1081 -0
- package/expertise/performance/infrastructure/index.md +22 -0
- package/expertise/performance/infrastructure/load-balancing.md +1081 -0
- package/expertise/performance/infrastructure/observability.md +1079 -0
- package/expertise/performance/mobile/index.md +23 -0
- package/expertise/performance/mobile/mobile-animations.md +544 -0
- package/expertise/performance/mobile/mobile-memory-battery.md +416 -0
- package/expertise/performance/mobile/mobile-network.md +452 -0
- package/expertise/performance/mobile/mobile-rendering.md +599 -0
- package/expertise/performance/mobile/mobile-startup-time.md +505 -0
- package/expertise/performance/platform-specific/flutter-performance.md +647 -0
- package/expertise/performance/platform-specific/index.md +22 -0
- package/expertise/performance/platform-specific/node-performance.md +1307 -0
- package/expertise/performance/platform-specific/postgres-performance.md +1366 -0
- package/expertise/performance/platform-specific/react-performance.md +1403 -0
- package/expertise/performance/web/bundle-optimization.md +1239 -0
- package/expertise/performance/web/image-and-media.md +636 -0
- package/expertise/performance/web/index.md +24 -0
- package/expertise/performance/web/network-optimization.md +1133 -0
- package/expertise/performance/web/rendering-performance.md +1098 -0
- package/expertise/performance/web/ssr-and-hydration.md +918 -0
- package/expertise/performance/web/web-vitals.md +1374 -0
- package/expertise/quality/accessibility.md +985 -0
- package/expertise/quality/evidence-based-verification.md +499 -0
- package/expertise/quality/index.md +24 -0
- package/expertise/quality/ml-model-audit.md +614 -0
- package/expertise/quality/performance.md +600 -0
- package/expertise/quality/testing-api.md +891 -0
- package/expertise/quality/testing-mobile.md +496 -0
- package/expertise/quality/testing-web.md +849 -0
- package/expertise/security/PROGRESS.md +54 -0
- package/expertise/security/agentic-identity.md +540 -0
- package/expertise/security/compliance-frameworks.md +601 -0
- package/expertise/security/data/data-encryption.md +364 -0
- package/expertise/security/data/data-privacy-gdpr.md +692 -0
- package/expertise/security/data/database-security.md +1171 -0
- package/expertise/security/data/index.md +22 -0
- package/expertise/security/data/pii-handling.md +531 -0
- package/expertise/security/foundations/authentication.md +1041 -0
- package/expertise/security/foundations/authorization.md +603 -0
- package/expertise/security/foundations/cryptography.md +1001 -0
- package/expertise/security/foundations/index.md +25 -0
- package/expertise/security/foundations/owasp-top-10.md +1354 -0
- package/expertise/security/foundations/secrets-management.md +1217 -0
- package/expertise/security/foundations/secure-sdlc.md +700 -0
- package/expertise/security/foundations/supply-chain-security.md +698 -0
- package/expertise/security/index.md +31 -0
- package/expertise/security/infrastructure/cloud-security-aws.md +1296 -0
- package/expertise/security/infrastructure/cloud-security-gcp.md +1376 -0
- package/expertise/security/infrastructure/container-security.md +721 -0
- package/expertise/security/infrastructure/incident-response.md +1295 -0
- package/expertise/security/infrastructure/index.md +24 -0
- package/expertise/security/infrastructure/logging-and-monitoring.md +1618 -0
- package/expertise/security/infrastructure/network-security.md +1337 -0
- package/expertise/security/mobile/index.md +23 -0
- package/expertise/security/mobile/mobile-android-security.md +1218 -0
- package/expertise/security/mobile/mobile-binary-protection.md +1229 -0
- package/expertise/security/mobile/mobile-data-storage.md +1265 -0
- package/expertise/security/mobile/mobile-ios-security.md +1401 -0
- package/expertise/security/mobile/mobile-network-security.md +1520 -0
- package/expertise/security/smart-contract-security.md +594 -0
- package/expertise/security/testing/index.md +22 -0
- package/expertise/security/testing/penetration-testing.md +1258 -0
- package/expertise/security/testing/security-code-review.md +1765 -0
- package/expertise/security/testing/threat-modeling.md +1074 -0
- package/expertise/security/testing/vulnerability-scanning.md +1062 -0
- package/expertise/security/web/api-security.md +586 -0
- package/expertise/security/web/cors-and-headers.md +433 -0
- package/expertise/security/web/csrf.md +562 -0
- package/expertise/security/web/file-upload.md +1477 -0
- package/expertise/security/web/index.md +25 -0
- package/expertise/security/web/injection.md +1375 -0
- package/expertise/security/web/session-management.md +1101 -0
- package/expertise/security/web/xss.md +1158 -0
- package/exports/README.md +17 -0
- package/exports/hosts/claude/.claude/agents/clarifier.md +42 -0
- package/exports/hosts/claude/.claude/agents/content-author.md +63 -0
- package/exports/hosts/claude/.claude/agents/designer.md +55 -0
- package/exports/hosts/claude/.claude/agents/executor.md +55 -0
- package/exports/hosts/claude/.claude/agents/learner.md +51 -0
- package/exports/hosts/claude/.claude/agents/planner.md +53 -0
- package/exports/hosts/claude/.claude/agents/researcher.md +43 -0
- package/exports/hosts/claude/.claude/agents/reviewer.md +54 -0
- package/exports/hosts/claude/.claude/agents/specifier.md +47 -0
- package/exports/hosts/claude/.claude/agents/verifier.md +71 -0
- package/exports/hosts/claude/.claude/commands/author.md +42 -0
- package/exports/hosts/claude/.claude/commands/clarify.md +38 -0
- package/exports/hosts/claude/.claude/commands/design-review.md +46 -0
- package/exports/hosts/claude/.claude/commands/design.md +44 -0
- package/exports/hosts/claude/.claude/commands/discover.md +37 -0
- package/exports/hosts/claude/.claude/commands/execute.md +48 -0
- package/exports/hosts/claude/.claude/commands/learn.md +38 -0
- package/exports/hosts/claude/.claude/commands/plan-review.md +42 -0
- package/exports/hosts/claude/.claude/commands/plan.md +39 -0
- package/exports/hosts/claude/.claude/commands/prepare-next.md +37 -0
- package/exports/hosts/claude/.claude/commands/review.md +40 -0
- package/exports/hosts/claude/.claude/commands/run-audit.md +41 -0
- package/exports/hosts/claude/.claude/commands/spec-challenge.md +41 -0
- package/exports/hosts/claude/.claude/commands/specify.md +38 -0
- package/exports/hosts/claude/.claude/commands/verify.md +37 -0
- package/exports/hosts/claude/.claude/settings.json +34 -0
- package/exports/hosts/claude/CLAUDE.md +19 -0
- package/exports/hosts/claude/export.manifest.json +38 -0
- package/exports/hosts/claude/host-package.json +67 -0
- package/exports/hosts/codex/AGENTS.md +19 -0
- package/exports/hosts/codex/export.manifest.json +38 -0
- package/exports/hosts/codex/host-package.json +41 -0
- package/exports/hosts/cursor/.cursor/hooks.json +16 -0
- package/exports/hosts/cursor/.cursor/rules/wazir-core.mdc +19 -0
- package/exports/hosts/cursor/export.manifest.json +38 -0
- package/exports/hosts/cursor/host-package.json +42 -0
- package/exports/hosts/gemini/GEMINI.md +19 -0
- package/exports/hosts/gemini/export.manifest.json +38 -0
- package/exports/hosts/gemini/host-package.json +41 -0
- package/hooks/README.md +18 -0
- package/hooks/definitions/loop_cap_guard.yaml +21 -0
- package/hooks/definitions/post_tool_capture.yaml +24 -0
- package/hooks/definitions/pre_compact_summary.yaml +19 -0
- package/hooks/definitions/pre_tool_capture_route.yaml +19 -0
- package/hooks/definitions/protected_path_write_guard.yaml +19 -0
- package/hooks/definitions/session_start.yaml +19 -0
- package/hooks/definitions/stop_handoff_harvest.yaml +20 -0
- package/hooks/loop-cap-guard +17 -0
- package/hooks/post-tool-lint +36 -0
- package/hooks/protected-path-write-guard +17 -0
- package/hooks/session-start +41 -0
- package/llms-full.txt +2355 -0
- package/llms.txt +43 -0
- package/package.json +79 -0
- package/roles/README.md +20 -0
- package/roles/clarifier.md +42 -0
- package/roles/content-author.md +63 -0
- package/roles/designer.md +55 -0
- package/roles/executor.md +55 -0
- package/roles/learner.md +51 -0
- package/roles/planner.md +53 -0
- package/roles/researcher.md +43 -0
- package/roles/reviewer.md +54 -0
- package/roles/specifier.md +47 -0
- package/roles/verifier.md +71 -0
- package/schemas/README.md +24 -0
- package/schemas/accepted-learning.schema.json +20 -0
- package/schemas/author-artifact.schema.json +156 -0
- package/schemas/clarification.schema.json +19 -0
- package/schemas/design-artifact.schema.json +80 -0
- package/schemas/docs-claim.schema.json +18 -0
- package/schemas/export-manifest.schema.json +20 -0
- package/schemas/hook.schema.json +67 -0
- package/schemas/host-export-package.schema.json +18 -0
- package/schemas/implementation-plan.schema.json +19 -0
- package/schemas/proposed-learning.schema.json +19 -0
- package/schemas/research.schema.json +18 -0
- package/schemas/review.schema.json +29 -0
- package/schemas/run-manifest.schema.json +18 -0
- package/schemas/spec-challenge.schema.json +18 -0
- package/schemas/spec.schema.json +20 -0
- package/schemas/usage.schema.json +102 -0
- package/schemas/verification-proof.schema.json +29 -0
- package/schemas/wazir-manifest.schema.json +173 -0
- package/skills/README.md +40 -0
- package/skills/brainstorming/SKILL.md +77 -0
- package/skills/debugging/SKILL.md +50 -0
- package/skills/design/SKILL.md +61 -0
- package/skills/dispatching-parallel-agents/SKILL.md +128 -0
- package/skills/executing-plans/SKILL.md +70 -0
- package/skills/finishing-a-development-branch/SKILL.md +169 -0
- package/skills/humanize/SKILL.md +123 -0
- package/skills/init-pipeline/SKILL.md +124 -0
- package/skills/prepare-next/SKILL.md +20 -0
- package/skills/receiving-code-review/SKILL.md +123 -0
- package/skills/requesting-code-review/SKILL.md +105 -0
- package/skills/requesting-code-review/code-reviewer.md +108 -0
- package/skills/run-audit/SKILL.md +197 -0
- package/skills/scan-project/SKILL.md +41 -0
- package/skills/self-audit/SKILL.md +153 -0
- package/skills/subagent-driven-development/SKILL.md +154 -0
- package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -0
- package/skills/subagent-driven-development/implementer-prompt.md +102 -0
- package/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/skills/tdd/SKILL.md +23 -0
- package/skills/using-git-worktrees/SKILL.md +163 -0
- package/skills/using-skills/SKILL.md +95 -0
- package/skills/verification/SKILL.md +22 -0
- package/skills/wazir/SKILL.md +463 -0
- package/skills/writing-plans/SKILL.md +30 -0
- package/skills/writing-skills/SKILL.md +157 -0
- package/skills/writing-skills/anthropic-best-practices.md +122 -0
- package/skills/writing-skills/persuasion-principles.md +50 -0
- package/templates/README.md +20 -0
- package/templates/artifacts/README.md +10 -0
- package/templates/artifacts/accepted-learning.md +19 -0
- package/templates/artifacts/accepted-learning.template.json +12 -0
- package/templates/artifacts/author.md +74 -0
- package/templates/artifacts/author.template.json +19 -0
- package/templates/artifacts/clarification.md +21 -0
- package/templates/artifacts/clarification.template.json +12 -0
- package/templates/artifacts/execute-notes.md +19 -0
- package/templates/artifacts/implementation-plan.md +21 -0
- package/templates/artifacts/implementation-plan.template.json +11 -0
- package/templates/artifacts/learning-proposal.md +19 -0
- package/templates/artifacts/next-run-handoff.md +21 -0
- package/templates/artifacts/plan-review.md +19 -0
- package/templates/artifacts/proposed-learning.template.json +12 -0
- package/templates/artifacts/research.md +21 -0
- package/templates/artifacts/research.template.json +12 -0
- package/templates/artifacts/review-findings.md +19 -0
- package/templates/artifacts/review.template.json +11 -0
- package/templates/artifacts/run-manifest.template.json +8 -0
- package/templates/artifacts/spec-challenge.md +19 -0
- package/templates/artifacts/spec-challenge.template.json +11 -0
- package/templates/artifacts/spec.md +21 -0
- package/templates/artifacts/spec.template.json +12 -0
- package/templates/artifacts/verification-proof.md +19 -0
- package/templates/artifacts/verification-proof.template.json +11 -0
- package/templates/examples/accepted-learning.example.json +14 -0
- package/templates/examples/author.example.json +152 -0
- package/templates/examples/clarification.example.json +15 -0
- package/templates/examples/docs-claim.example.json +8 -0
- package/templates/examples/export-manifest.example.json +7 -0
- package/templates/examples/host-export-package.example.json +11 -0
- package/templates/examples/implementation-plan.example.json +17 -0
- package/templates/examples/proposed-learning.example.json +13 -0
- package/templates/examples/research.example.json +15 -0
- package/templates/examples/research.example.md +6 -0
- package/templates/examples/review.example.json +17 -0
- package/templates/examples/run-manifest.example.json +9 -0
- package/templates/examples/spec-challenge.example.json +14 -0
- package/templates/examples/spec.example.json +21 -0
- package/templates/examples/verification-proof.example.json +21 -0
- package/templates/examples/wazir-manifest.example.yaml +65 -0
- package/templates/task-definition-schema.md +99 -0
- package/tooling/README.md +20 -0
- package/tooling/src/adapters/context-mode.js +50 -0
- package/tooling/src/capture/command.js +376 -0
- package/tooling/src/capture/store.js +99 -0
- package/tooling/src/capture/usage.js +270 -0
- package/tooling/src/checks/branches.js +50 -0
- package/tooling/src/checks/brand-truth.js +110 -0
- package/tooling/src/checks/changelog.js +231 -0
- package/tooling/src/checks/command-registry.js +36 -0
- package/tooling/src/checks/commits.js +102 -0
- package/tooling/src/checks/docs-drift.js +103 -0
- package/tooling/src/checks/docs-truth.js +201 -0
- package/tooling/src/checks/runtime-surface.js +156 -0
- package/tooling/src/cli.js +116 -0
- package/tooling/src/command-options.js +56 -0
- package/tooling/src/commands/validate.js +320 -0
- package/tooling/src/doctor/command.js +91 -0
- package/tooling/src/export/command.js +77 -0
- package/tooling/src/export/compiler.js +498 -0
- package/tooling/src/guards/loop-cap-guard.js +52 -0
- package/tooling/src/guards/protected-path-write-guard.js +67 -0
- package/tooling/src/index/command.js +152 -0
- package/tooling/src/index/storage.js +1061 -0
- package/tooling/src/index/summarizers.js +261 -0
- package/tooling/src/loaders.js +18 -0
- package/tooling/src/project-root.js +22 -0
- package/tooling/src/recall/command.js +225 -0
- package/tooling/src/schema-validator.js +30 -0
- package/tooling/src/state-root.js +40 -0
- package/tooling/src/status/command.js +71 -0
- package/wazir.manifest.yaml +135 -0
- package/workflows/README.md +19 -0
- package/workflows/author.md +42 -0
- package/workflows/clarify.md +38 -0
- package/workflows/design-review.md +46 -0
- package/workflows/design.md +44 -0
- package/workflows/discover.md +37 -0
- package/workflows/execute.md +48 -0
- package/workflows/learn.md +38 -0
- package/workflows/plan-review.md +42 -0
- package/workflows/plan.md +39 -0
- package/workflows/prepare-next.md +37 -0
- package/workflows/review.md +40 -0
- package/workflows/run-audit.md +41 -0
- package/workflows/spec-challenge.md +41 -0
- package/workflows/specify.md +38 -0
- package/workflows/verify.md +37 -0
|
@@ -0,0 +1,892 @@
|
|
|
1
|
+
# API Design — REST — Architecture Expertise Module
|
|
2
|
+
|
|
3
|
+
> REST (Representational State Transfer) is the dominant API paradigm for web services. A well-designed REST API is intuitive, consistent, and evolvable. REST is the right default for public APIs and most internal APIs — but it has real limitations for complex queries, real-time data, and high-performance internal communication. Knowing when REST is the wrong tool matters as much as knowing how to design a good one.
|
|
4
|
+
|
|
5
|
+
> **Category:** Integration
|
|
6
|
+
> **Complexity:** Moderate
|
|
7
|
+
> **Applies when:** Building HTTP APIs for web/mobile clients, public APIs, or internal service-to-service communication where simplicity, cacheability, and broad tooling support are valued
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## What This Is (and What It Isn't)
|
|
12
|
+
|
|
13
|
+
### The Core Idea
|
|
14
|
+
|
|
15
|
+
REST was defined by Roy Fielding in his 2000 doctoral dissertation as an architectural style for distributed hypermedia systems. It describes a set of constraints — client-server, stateless, cacheable, uniform interface, layered system, and (optionally) code-on-demand — that, when followed together, produce systems with desirable properties: scalability, simplicity, modifiability, and visibility.
|
|
16
|
+
|
|
17
|
+
In practice, "REST API" has come to mean "JSON over HTTP with resource-oriented URLs." This is Level 2 on the Richardson Maturity Model. True REST (Level 3, with HATEOAS) is rare in production systems. The industry overwhelmingly builds at Level 2, and this module reflects that reality while explaining why Level 3 exists and when it matters.
|
|
18
|
+
|
|
19
|
+
### The Richardson Maturity Model
|
|
20
|
+
|
|
21
|
+
Leonard Richardson proposed a four-level model that grades APIs by how fully they use HTTP and REST concepts:
|
|
22
|
+
|
|
23
|
+
**Level 0 — The Swamp of POX (Plain Old XML/JSON).** A single endpoint handles everything. Clients POST a blob describing what they want. The URL is a tunnel; HTTP is just a transport. Most SOAP services live here. Example: `POST /api` with a body like `{"action": "getUser", "id": 42}`.
|
|
24
|
+
|
|
25
|
+
**Level 1 — Resources.** Individual resources get their own URIs (`/users/42`, `/orders/101`), but the API still uses a single HTTP method (usually POST) for all operations. This is a common intermediate state in APIs migrating from RPC patterns.
|
|
26
|
+
|
|
27
|
+
**Level 2 — HTTP Verbs.** Resources have dedicated URIs and the API uses HTTP methods semantically: GET to read, POST to create, PUT/PATCH to update, DELETE to remove. Status codes carry meaning (201 Created, 404 Not Found, 409 Conflict). This is where the vast majority of production REST APIs operate. Stripe, GitHub, Twilio, and nearly every major public API lives here.
|
|
28
|
+
|
|
29
|
+
**Level 3 — Hypermedia Controls (HATEOAS).** Responses include links that tell the client what actions are available next. A payment resource might include links to `cancel`, `refund`, or `capture`. The client discovers capabilities at runtime rather than hardcoding URL patterns. PayPal's API is one of the few major APIs that implements this level.
|
|
30
|
+
|
|
31
|
+
### What REST Is NOT
|
|
32
|
+
|
|
33
|
+
**Not "just HTTP endpoints."** Slapping JSON responses onto HTTP routes does not make an API RESTful. If your `GET /users` endpoint modifies state, or your `POST /getReport` endpoint is really a query, you have an RPC API wearing a REST costume.
|
|
34
|
+
|
|
35
|
+
**Not a protocol.** REST is an architectural style — a set of constraints. HTTP is a protocol. REST uses HTTP, but HTTP usage does not imply REST. SOAP also uses HTTP; nobody calls SOAP RESTful.
|
|
36
|
+
|
|
37
|
+
**Not a specification.** There is no formal REST spec the way there is an OpenAPI spec or a GraphQL spec. This is both a strength (flexibility) and a weakness (inconsistency). Every team interprets REST slightly differently, which is why conventions and style guides matter enormously.
|
|
38
|
+
|
|
39
|
+
**Not inherently the best choice for every API.** REST optimizes for simplicity, cacheability, and broad client compatibility. It does not optimize for query flexibility (GraphQL does), transport efficiency (gRPC does), or real-time bidirectional communication (WebSockets do).
|
|
40
|
+
|
|
41
|
+
### HATEOAS — The Theory vs. The Practice
|
|
42
|
+
|
|
43
|
+
HATEOAS (Hypermedia as the Engine of Application State) is the most debated aspect of REST. In theory, it enables truly decoupled clients: the server's responses contain all the links a client needs to navigate the API, so clients never hardcode URLs beyond the entry point. If the server changes a URL, clients follow the new links automatically.
|
|
44
|
+
|
|
45
|
+
**Why it mostly failed in practice:**
|
|
46
|
+
|
|
47
|
+
- **Clients need semantics, not just links.** Knowing that a link exists at `rel="cancel"` doesn't tell a mobile app where to put the cancel button, what confirmation dialog to show, or how to handle the response. Real clients need deep knowledge of what operations mean, not just where they live.
|
|
48
|
+
- **Bloated responses.** Every response must carry navigation metadata. For high-volume APIs, this overhead adds up. A list of 100 orders, each with 5 hypermedia links, adds substantial payload for links that clients already know about.
|
|
49
|
+
- **Chatty interaction patterns.** Pure HATEOAS encourages clients to "discover" the API by following links, which can create unnecessary round-trips compared to clients that know the URL patterns upfront.
|
|
50
|
+
- **Industry verdict.** The overwhelming majority of successful public APIs — Stripe, GitHub, Twilio, Shopify — operate at Level 2 without HATEOAS. The pragmatic industry consensus is that good documentation, SDKs, and OpenAPI specs solve the discoverability problem better than hypermedia links.
|
|
51
|
+
|
|
52
|
+
**When HATEOAS still has value:** Long-running workflow APIs where the available actions genuinely change based on state (e.g., an order that can be cancelled only before shipment). PayPal's API uses HATEOAS for payment workflows, and it works well there because the available transitions are the primary information clients need.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## When to Use It
|
|
57
|
+
|
|
58
|
+
### The Default Choice for Good Reasons
|
|
59
|
+
|
|
60
|
+
REST should be your starting point for any new API unless you have a specific reason to choose otherwise. The reasons are pragmatic, not dogmatic:
|
|
61
|
+
|
|
62
|
+
**Public APIs where developer experience matters.** REST's simplicity makes it accessible to any developer with `curl` and a browser. Every programming language has HTTP client libraries. No code generation, no schema compilation, no special tooling required. Stripe built arguably the best public API in the industry on REST, and their design is studied as a gold standard. Their core philosophy: APIs are products, and developers are customers.
|
|
63
|
+
|
|
64
|
+
**Web and mobile backends.** Browsers speak HTTP natively. Mobile SDKs wrap HTTP trivially. REST's request-response model maps cleanly to user interactions: tap a button, make a request, show the result. Caching with ETags and Cache-Control headers works out of the box for read-heavy mobile apps on spotty connections.
|
|
65
|
+
|
|
66
|
+
**CRUD-dominant applications.** When your domain maps naturally to resources with create/read/update/delete operations — users, orders, products, invoices — REST's resource-oriented model is a near-perfect fit. The mapping from domain objects to endpoints is intuitive and predictable.
|
|
67
|
+
|
|
68
|
+
**Systems requiring cacheability.** REST's stateless constraint and HTTP's built-in caching infrastructure (CDNs, browser caches, reverse proxies) make REST uniquely cacheable among API paradigms. A `GET /products/42` response can be cached at every layer of the stack. GraphQL queries are POST requests with unique bodies — caching them requires custom infrastructure.
|
|
69
|
+
|
|
70
|
+
**Brownfield integration.** Every API gateway, load balancer, monitoring tool, and security scanner understands HTTP/REST. Choosing REST means your entire infrastructure stack works without modification.
|
|
71
|
+
|
|
72
|
+
### Real-World Gold Standards
|
|
73
|
+
|
|
74
|
+
**Stripe's API** — Widely considered the best-designed REST API in the industry. Key principles that make it exceptional:
|
|
75
|
+
- *Predictable resource naming*: `/v1/customers`, `/v1/charges`, `/v1/subscriptions`. No surprises.
|
|
76
|
+
- *Idempotency keys*: Clients send an `Idempotency-Key` header so retries are safe. Critical for payment APIs where double-charging is catastrophic.
|
|
77
|
+
- *Expand parameter*: Instead of forcing N+1 requests to fetch related resources, Stripe lets clients request `?expand[]=customer` to inline related objects. Pragmatic solution to REST's over-fetching problem.
|
|
78
|
+
- *Versioned via date*: API versions are dates (`2023-10-16`), not integers. Each Stripe account is pinned to its creation-date version and can upgrade explicitly. This avoids the "v47" version sprawl problem.
|
|
79
|
+
- *Consistent error format*: Every error includes `type`, `code`, `message`, and `param` (the field that caused the error). Actionable, machine-readable, human-friendly.
|
|
80
|
+
- *Test mode*: A parallel sandbox environment with test API keys. Developers test without moving real money.
|
|
81
|
+
- *Every change reviewed*: An internal API Review Board reviews every API change for consistency and backward compatibility.
|
|
82
|
+
|
|
83
|
+
**GitHub's REST API (v3)** — Demonstrates REST at scale with thousands of endpoints. Uses Link headers for pagination, OAuth for authentication, and conditional requests with ETags. Their migration from v3 REST to v4 GraphQL illustrates both REST's strengths (simplicity, caching) and its limits (complex nested data queries across repositories, issues, pull requests, and comments).
|
|
84
|
+
|
|
85
|
+
**Twilio's API** — A communication API that proves REST works for non-CRUD domains. Sending an SMS is `POST /Messages` with a body. The resource metaphor extends naturally: a call is a resource, a conference is a resource, a participant is a sub-resource of a conference. Twilio's API also demonstrates excellent error design — every error has a unique code, a human message, and a link to documentation with resolution steps.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## When NOT to Use It
|
|
90
|
+
|
|
91
|
+
This section is intentionally as long as "When to Use It." Choosing the wrong API paradigm is a costly mistake, and REST's dominance means teams often default to it when they shouldn't.
|
|
92
|
+
|
|
93
|
+
### Complex Data Fetching with Deep Nesting — Use GraphQL
|
|
94
|
+
|
|
95
|
+
**The problem:** A mobile app needs to display a user's profile, their 5 most recent orders, the items in each order, and the reviews for each item. With REST, this requires either:
|
|
96
|
+
- Multiple requests: `GET /users/42` → `GET /users/42/orders?limit=5` → `GET /orders/{id}/items` (×5) → `GET /items/{id}/reviews` (×N). This is the N+1 problem, and it devastates mobile performance on high-latency connections.
|
|
97
|
+
- A bespoke endpoint: `GET /users/42/profile-with-orders-and-reviews`. This creates a one-off endpoint that couples the API to a specific client's screen layout. Do this enough times and your "REST" API becomes a collection of RPC endpoints.
|
|
98
|
+
|
|
99
|
+
**GraphQL solves this** by letting the client specify exactly what data it needs in a single request. The query describes the shape of the response. No over-fetching, no under-fetching, one round-trip.
|
|
100
|
+
|
|
101
|
+
**Real example:** GitHub moved their API from REST (v3) to GraphQL (v4) precisely because developer tool integrations needed to fetch deeply nested data (repository → branches → commits → statuses → check runs) and REST required too many round-trips.
|
|
102
|
+
|
|
103
|
+
### High-Performance Internal Service-to-Service — Use gRPC
|
|
104
|
+
|
|
105
|
+
**The problem:** Two backend services exchange thousands of messages per second. JSON serialization/deserialization is a measurable CPU cost. HTTP/1.1 request-response overhead adds latency. Schema enforcement is manual — a field gets renamed and nothing catches it until runtime.
|
|
106
|
+
|
|
107
|
+
**gRPC solves this** with Protocol Buffers (binary serialization, 5-10x smaller than JSON), HTTP/2 (multiplexed streams, header compression), and code-generated clients with compile-time type safety. Google uses gRPC internally for virtually all service-to-service communication.
|
|
108
|
+
|
|
109
|
+
**When specifically:** Latency-sensitive internal calls, polyglot microservice environments (gRPC generates clients for 10+ languages from one `.proto` file), streaming data between services.
|
|
110
|
+
|
|
111
|
+
### Real-Time Bidirectional Communication — Use WebSockets
|
|
112
|
+
|
|
113
|
+
**The problem:** A chat application, live dashboard, or collaborative editor needs the server to push updates to the client without polling. REST is request-response only — the client must poll, which means either stale data (long poll intervals) or wasted resources (short poll intervals).
|
|
114
|
+
|
|
115
|
+
**WebSockets solve this** with a persistent, bidirectional connection. The server pushes updates the instant they occur. No polling overhead, no stale data.
|
|
116
|
+
|
|
117
|
+
**When specifically:** Chat, multiplayer games, live trading dashboards, collaborative editing, real-time notifications where latency matters.
|
|
118
|
+
|
|
119
|
+
### Batch Operations
|
|
120
|
+
|
|
121
|
+
**The problem:** A client needs to create 500 products, update 200 prices, and delete 50 discontinued items. With REST, that is 750 individual HTTP requests. Even with connection pooling and HTTP/2, the overhead is significant.
|
|
122
|
+
|
|
123
|
+
**Solutions:** Some REST APIs add batch endpoints (`POST /batch` with an array of operations), but this breaks the resource model. GraphQL handles batching more naturally through mutations. For bulk data operations, dedicated import/export endpoints or message queues are often better than any synchronous API.
|
|
124
|
+
|
|
125
|
+
### File Upload and Binary Data
|
|
126
|
+
|
|
127
|
+
REST's JSON-centric model handles binary data awkwardly. Multipart form uploads work but are painful to document and test. Base64-encoding files into JSON wastes 33% bandwidth. For file-heavy APIs, consider dedicated upload endpoints with streaming support, pre-signed URLs (S3-style), or tus protocol for resumable uploads.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## How It Works
|
|
132
|
+
|
|
133
|
+
### Resource Naming
|
|
134
|
+
|
|
135
|
+
Resource URLs are the most visible part of your API. Get them right and the API is intuitive. Get them wrong and developers will curse you for years.
|
|
136
|
+
|
|
137
|
+
**Rules that matter:**
|
|
138
|
+
|
|
139
|
+
1. **Use nouns, not verbs.** Resources are things: `/users`, `/orders`, `/products`. Not `/getUsers`, `/createOrder`, `/deleteProduct`. The HTTP method is the verb.
|
|
140
|
+
|
|
141
|
+
2. **Use plural nouns.** `/users/42`, not `/user/42`. The collection is `/users`; a single item is `/users/42`. Mixing plurals and singulars creates confusion about which endpoints exist.
|
|
142
|
+
|
|
143
|
+
3. **Nest for clear ownership.** `/users/42/orders` — orders belonging to user 42. But limit nesting depth to 2-3 levels. `/users/42/orders/101/items/7/reviews/3` is too deep — flatten it to `/reviews/3` if reviews have their own identity.
|
|
144
|
+
|
|
145
|
+
4. **Use kebab-case.** `/user-profiles`, not `/userProfiles` or `/user_profiles`. URLs are case-insensitive by convention, and kebab-case is the most readable in a URL bar. (Note: query parameters typically use snake_case or camelCase depending on your language ecosystem.)
|
|
146
|
+
|
|
147
|
+
5. **Avoid actions in URLs — mostly.** Prefer `POST /orders/42/cancellation` (creating a cancellation resource) over `POST /orders/42/cancel`. But be pragmatic: if `POST /orders/42/cancel` is clearly more intuitive for your users, do that. Purity is not the goal; usability is.
|
|
148
|
+
|
|
149
|
+
### HTTP Methods — The Full Picture
|
|
150
|
+
|
|
151
|
+
| Method | Semantics | Idempotent | Safe | Request Body | Typical Response |
|
|
152
|
+
|--------|-----------|------------|------|-------------|-----------------|
|
|
153
|
+
| `GET` | Read a resource or collection | Yes | Yes | No | 200 + resource |
|
|
154
|
+
| `POST` | Create a resource, trigger an action | No | No | Yes | 201 + created resource + Location header |
|
|
155
|
+
| `PUT` | Replace a resource entirely | Yes | No | Yes | 200 + updated resource |
|
|
156
|
+
| `PATCH` | Partially update a resource | No* | No | Yes | 200 + updated resource |
|
|
157
|
+
| `DELETE` | Remove a resource | Yes | No | No | 204 No Content |
|
|
158
|
+
| `HEAD` | GET without the body (check existence) | Yes | Yes | No | 200 (headers only) |
|
|
159
|
+
| `OPTIONS` | Describe available methods (CORS preflight) | Yes | Yes | No | 200 + Allow header |
|
|
160
|
+
|
|
161
|
+
*PATCH is not inherently idempotent, but can be implemented idempotently with JSON Merge Patch (RFC 7386). JSON Patch (RFC 6902) operations like "add to array" are not idempotent.
|
|
162
|
+
|
|
163
|
+
**Idempotency matters.** An idempotent operation produces the same result regardless of how many times it's executed. This is critical for retry safety. If a network timeout occurs after `PUT /users/42` and the client retries, the result is the same. If a `POST /orders` times out and the client retries, you might create a duplicate order — which is why idempotency keys exist (see below).
|
|
164
|
+
|
|
165
|
+
### Status Codes — Use Them Correctly
|
|
166
|
+
|
|
167
|
+
Do not return 200 for everything. Status codes are part of your API's contract.
|
|
168
|
+
|
|
169
|
+
**Success codes:**
|
|
170
|
+
- `200 OK` — Request succeeded. Use for GET, PUT, PATCH responses.
|
|
171
|
+
- `201 Created` — Resource was created. Use for POST. Include a `Location` header pointing to the new resource.
|
|
172
|
+
- `202 Accepted` — Request accepted for async processing. The work hasn't completed yet. Include a URL to check status.
|
|
173
|
+
- `204 No Content` — Success, nothing to return. Use for DELETE.
|
|
174
|
+
|
|
175
|
+
**Client error codes:**
|
|
176
|
+
- `400 Bad Request` — Malformed request (invalid JSON, missing required field). The client's fault.
|
|
177
|
+
- `401 Unauthorized` — Not authenticated. The request lacks valid credentials. (The name is misleading — it means unauthenticated.)
|
|
178
|
+
- `403 Forbidden` — Authenticated but not authorized. You know who they are; they don't have permission.
|
|
179
|
+
- `404 Not Found` — Resource doesn't exist. Also use when a user shouldn't know the resource exists (security through obscurity).
|
|
180
|
+
- `409 Conflict` — State conflict (e.g., trying to create a user with an email that already exists).
|
|
181
|
+
- `422 Unprocessable Entity` — Request is syntactically valid but semantically wrong (e.g., "quantity: -5").
|
|
182
|
+
- `429 Too Many Requests` — Rate limit exceeded. Include `Retry-After` header.
|
|
183
|
+
|
|
184
|
+
**Server error codes:**
|
|
185
|
+
- `500 Internal Server Error` — Unhandled server failure. Never intentionally return this; it should only come from unhandled exceptions.
|
|
186
|
+
- `502 Bad Gateway` — Upstream service is down.
|
|
187
|
+
- `503 Service Unavailable` — Server is overloaded or in maintenance. Include `Retry-After` header.
|
|
188
|
+
- `504 Gateway Timeout` — Upstream service timed out.
|
|
189
|
+
|
|
190
|
+
### Pagination
|
|
191
|
+
|
|
192
|
+
Never return unbounded collections. A `GET /products` that returns 100,000 results will crash mobile clients and spike your database.
|
|
193
|
+
|
|
194
|
+
**Offset pagination** — `GET /products?offset=20&limit=10`. Simple, supports "jump to page N." But performance degrades badly at high offsets because the database must count and skip rows. With PostgreSQL, paginating to offset 900,000 in a million-row table is dramatically slower than offset 0. Also unstable: if a row is inserted or deleted between page fetches, items shift and clients see duplicates or miss items.
|
|
195
|
+
|
|
196
|
+
**Cursor pagination** — `GET /products?after=eyJpZCI6NDJ9&limit=10`. The cursor is an opaque token (often a base64-encoded primary key or timestamp). The server uses it to seek directly to the right position. Performance is constant regardless of how deep into the dataset you are — benchmarks show 17x speedup over offset pagination at 1 million rows in PostgreSQL. Stripe, Slack, Facebook, and Twitter all use cursor pagination.
|
|
197
|
+
|
|
198
|
+
**Keyset pagination** — A variant of cursor pagination where the cursor is a known field value (e.g., `?created_after=2024-01-15T00:00:00Z&limit=10`). Transparent and debuggable, but requires a unique, sequential sort key.
|
|
199
|
+
|
|
200
|
+
**Recommendation:** Use cursor pagination for any collection that might grow large. Use offset pagination only for small, stable datasets or admin UIs that genuinely need "jump to page" functionality. Always return pagination metadata:
|
|
201
|
+
|
|
202
|
+
```json
|
|
203
|
+
{
|
|
204
|
+
"data": [...],
|
|
205
|
+
"pagination": {
|
|
206
|
+
"has_more": true,
|
|
207
|
+
"next_cursor": "eyJpZCI6NDJ9"
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Filtering, Sorting, and Field Selection
|
|
213
|
+
|
|
214
|
+
**Filtering:** Use query parameters. `GET /orders?status=shipped&customer_id=42`. For complex filters, consider a lightweight query syntax: `GET /products?price[gte]=10&price[lte]=100`. Avoid inventing your own query language — keep it simple or adopt an existing standard like OData or JSON:API filtering.
|
|
215
|
+
|
|
216
|
+
**Sorting:** `GET /products?sort=price` (ascending) or `GET /products?sort=-price` (descending, prefixed with minus). For multi-field sorting: `GET /products?sort=-created_at,name`.
|
|
217
|
+
|
|
218
|
+
**Field selection:** `GET /users/42?fields=id,name,email`. Reduces payload size for bandwidth-constrained clients. Stripe uses `expand[]` for the inverse: include related objects that would otherwise be just IDs.
|
|
219
|
+
|
|
220
|
+
### Versioning
|
|
221
|
+
|
|
222
|
+
APIs change. Versioning controls how changes reach clients. There are three mainstream strategies:
|
|
223
|
+
|
|
224
|
+
**URL versioning** — `GET /v1/users/42`. The most common approach. Used by Stripe, Twilio, Google, and most major APIs. Advantages: visible, cacheable (different versions are different cache keys), easy to route at the gateway level. Disadvantage: implies that the entire API is versioned as one unit, which can lead to large version jumps for small changes.
|
|
225
|
+
|
|
226
|
+
**Header versioning** — `GET /users/42` with `Api-Version: 2024-01-15` or `Accept: application/vnd.myapp.v2+json`. Keeps URLs clean. Follows REST principles more closely (the resource identity doesn't change; the representation does). Disadvantage: harder to test in a browser, invisible in server logs without custom configuration, less obvious for developers new to the API. GitHub uses this approach with the `X-GitHub-Api-Version` header.
|
|
227
|
+
|
|
228
|
+
**Date-based versioning** — Stripe's approach. Each API version is a date (`2023-10-16`). New accounts are pinned to the latest version. Existing accounts keep their version until they explicitly upgrade. Stripe maintains backward compatibility across all versions simultaneously using request/response transformers. This is operationally expensive but provides the best developer experience for a payments API where stability is paramount.
|
|
229
|
+
|
|
230
|
+
**Recommendation:** Use URL versioning (`/v1/`) for most APIs. It's the simplest, most visible, and best-supported approach. Reserve date-based versioning for APIs where stability is a top priority and you have the engineering resources to maintain multiple versions simultaneously.
|
|
231
|
+
|
|
232
|
+
### Authentication and Authorization
|
|
233
|
+
|
|
234
|
+
**API Keys** — Simplest approach. A long random string sent in a header (`Authorization: Bearer sk_live_...`) or query parameter. Appropriate for server-to-server APIs where the caller is a known service. Not appropriate for client-side use (keys can be extracted from mobile apps and browser code). Stripe uses publishable keys (safe for client-side, limited permissions) and secret keys (server-side only, full access).
|
|
235
|
+
|
|
236
|
+
**OAuth 2.0** — The standard for delegated authorization. A user grants a third-party app limited access to their account without sharing their password. Required when your API is consumed by third-party applications acting on behalf of users. GitHub, Google, and Slack APIs all use OAuth 2.0. Complex to implement correctly, but essential for platform APIs.
|
|
237
|
+
|
|
238
|
+
**JWT (JSON Web Tokens)** — Self-contained tokens that encode user identity and permissions. The server can validate them without a database lookup (stateless). Common for first-party mobile/web apps. Danger: JWTs cannot be revoked before expiration unless you add a revocation list, which partially defeats the stateless benefit. Use short-lived access tokens (15 minutes) with longer-lived refresh tokens.
|
|
239
|
+
|
|
240
|
+
**Recommendation:** Use API keys for simple server-to-server APIs. Use OAuth 2.0 for platform APIs consumed by third parties. Use JWTs for first-party applications. Never send credentials over plain HTTP — HTTPS only, always.
|
|
241
|
+
|
|
242
|
+
### Rate Limiting
|
|
243
|
+
|
|
244
|
+
Rate limiting protects your service from abuse and ensures fair usage. Essential for any public API.
|
|
245
|
+
|
|
246
|
+
**Headers to expose:**
|
|
247
|
+
```
|
|
248
|
+
X-RateLimit-Limit: 1000 # Requests allowed per window
|
|
249
|
+
X-RateLimit-Remaining: 847 # Requests remaining in current window
|
|
250
|
+
X-RateLimit-Reset: 1704067200 # Unix timestamp when the window resets
|
|
251
|
+
Retry-After: 30 # Seconds to wait (on 429 responses)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**Strategies:** Fixed window (simple but allows bursts at window boundaries), sliding window (smoother but more complex), token bucket (best for bursty traffic). Most API gateways implement these out of the box.
|
|
255
|
+
|
|
256
|
+
**Response when limited:**
|
|
257
|
+
```json
|
|
258
|
+
HTTP/1.1 429 Too Many Requests
|
|
259
|
+
Retry-After: 30
|
|
260
|
+
|
|
261
|
+
{
|
|
262
|
+
"type": "https://api.example.com/errors/rate-limit-exceeded",
|
|
263
|
+
"title": "Rate limit exceeded",
|
|
264
|
+
"status": 429,
|
|
265
|
+
"detail": "You have exceeded the limit of 1000 requests per hour. Try again in 30 seconds.",
|
|
266
|
+
"instance": "/users/42/orders"
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Idempotency Keys
|
|
271
|
+
|
|
272
|
+
For non-idempotent operations (POST), clients should be able to safely retry without creating duplicates. The solution: idempotency keys.
|
|
273
|
+
|
|
274
|
+
The client generates a unique key (typically a UUID) and sends it with the request:
|
|
275
|
+
```
|
|
276
|
+
POST /v1/charges
|
|
277
|
+
Idempotency-Key: 8a3b1c2d-4e5f-6a7b-8c9d-0e1f2a3b4c5d
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
The server stores the key and the response. If the same key is sent again, the server returns the stored response without re-executing the operation. Stripe, PayPal, and most payment APIs require idempotency keys on POST requests.
|
|
281
|
+
|
|
282
|
+
**Implementation notes:** Store keys for 24-48 hours, then expire them. Return the original response (including the original status code) on retries. If the original request is still processing when a retry arrives, return `409 Conflict` to prevent race conditions.
|
|
283
|
+
|
|
284
|
+
### Error Format — RFC 9457 (formerly RFC 7807)
|
|
285
|
+
|
|
286
|
+
Standardize your error responses. RFC 9457 "Problem Details for HTTP APIs" defines a machine-readable format:
|
|
287
|
+
|
|
288
|
+
```json
|
|
289
|
+
{
|
|
290
|
+
"type": "https://api.example.com/errors/insufficient-funds",
|
|
291
|
+
"title": "Insufficient Funds",
|
|
292
|
+
"status": 422,
|
|
293
|
+
"detail": "Account acc_123 has a balance of $10.00, but the charge requires $25.00.",
|
|
294
|
+
"instance": "/v1/charges/ch_456",
|
|
295
|
+
"balance": 1000,
|
|
296
|
+
"required": 2500
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**Fields:**
|
|
301
|
+
- `type` — URI identifying the error type. Should link to documentation.
|
|
302
|
+
- `title` — Human-readable summary. Same for all instances of this error type.
|
|
303
|
+
- `status` — HTTP status code (repeated for convenience when the body is processed outside the HTTP context).
|
|
304
|
+
- `detail` — Human-readable explanation specific to this occurrence. Focus on what the client can do to fix it.
|
|
305
|
+
- `instance` — URI identifying this specific occurrence (useful for support tickets and log correlation).
|
|
306
|
+
|
|
307
|
+
**Extension fields** (like `balance` and `required` above) carry machine-readable data that clients can act on programmatically. This is where RFC 9457 shines over ad-hoc error formats.
|
|
308
|
+
|
|
309
|
+
**Real-world patterns:** Stripe includes `type`, `code`, `message`, `param` (the specific field that caused the error), and a `doc_url` linking to documentation. Twilio includes an error code and a link to a page explaining the error and its resolution. Both approaches are excellent — the key is consistency and actionability.
|
|
310
|
+
|
|
311
|
+
### OpenAPI / Swagger
|
|
312
|
+
|
|
313
|
+
Document your API with the OpenAPI Specification (OAS). An OpenAPI document is a machine-readable description of your API's endpoints, request/response formats, authentication, and errors.
|
|
314
|
+
|
|
315
|
+
**Why it matters:**
|
|
316
|
+
- Auto-generated client SDKs in any language (via openapi-generator)
|
|
317
|
+
- Interactive documentation (Swagger UI, Redocly)
|
|
318
|
+
- Request validation middleware (enforce the spec at runtime)
|
|
319
|
+
- Contract testing (ensure implementation matches the spec)
|
|
320
|
+
- API gateway configuration (import the spec to configure routing and validation)
|
|
321
|
+
|
|
322
|
+
**Design-first vs. code-first:** Design-first (write the OpenAPI spec, then implement) produces better APIs because it forces you to think about the interface before the implementation. Code-first (generate the spec from code annotations) is faster but tends to leak implementation details into the API. For public APIs, always design-first.
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## Trade-Offs Matrix
|
|
327
|
+
|
|
328
|
+
| Dimension | REST | GraphQL | gRPC | WebSockets |
|
|
329
|
+
|-----------|------|---------|------|------------|
|
|
330
|
+
| **Learning curve** | Low — HTTP + JSON are universal | Medium — query language, schema, resolvers | High — protobuf, HTTP/2, code generation | Medium — connection management, reconnection |
|
|
331
|
+
| **Client coupling** | Low — any HTTP client works | Medium — requires GraphQL client library | High — requires generated stubs | Medium — requires WebSocket client |
|
|
332
|
+
| **Cacheability** | Excellent — HTTP caching works natively | Poor — POST requests with unique bodies | Poor — binary protocol, custom caching needed | N/A — persistent connections |
|
|
333
|
+
| **Payload efficiency** | Medium — JSON is verbose, full resources returned | Good — client requests exactly what it needs | Excellent — binary protobuf, 5-10x smaller | Varies — typically JSON, but flexible |
|
|
334
|
+
| **Type safety** | Weak — JSON has no schema enforcement at transport | Strong — schema with introspection | Strong — compile-time type checking from proto | None — application-level concern |
|
|
335
|
+
| **Tooling ecosystem** | Massive — every tool understands HTTP/REST | Growing — Apollo, Relay, GraphiQL | Moderate — official libraries for 10+ languages | Moderate — Socket.IO, ws, native browser API |
|
|
336
|
+
| **Real-time support** | Polling or SSE (unidirectional) | Subscriptions (via WebSockets under the hood) | Server streaming, bidirectional streaming | Native bidirectional real-time |
|
|
337
|
+
| **Browser support** | Native — fetch/XMLHttpRequest | Via HTTP POST — works in browsers | Limited — grpc-web requires a proxy | Native — WebSocket API |
|
|
338
|
+
| **Observability** | Excellent — standard HTTP access logs, status codes | Challenging — all requests are POST 200 | Moderate — binary inspection requires tooling | Challenging — persistent connections, custom metrics |
|
|
339
|
+
| **Versioning** | Well-understood patterns (URL, header, date) | Schema evolution (deprecate fields, add new ones) | Proto file versioning with backward compatibility | Application-level concern |
|
|
340
|
+
| **Error handling** | Standardized (HTTP status codes + RFC 9457) | Always 200, errors in response body | Status codes in gRPC protocol | Application-level concern |
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## Evolution Path
|
|
345
|
+
|
|
346
|
+
### Backward Compatibility Rules
|
|
347
|
+
|
|
348
|
+
An API is a contract. Breaking changes destroy trust and create integration failures. These changes are **backward compatible** (safe):
|
|
349
|
+
|
|
350
|
+
- Adding a new endpoint
|
|
351
|
+
- Adding a new optional field to a request
|
|
352
|
+
- Adding a new field to a response
|
|
353
|
+
- Adding a new query parameter
|
|
354
|
+
- Adding a new enum value (if clients handle unknown values gracefully)
|
|
355
|
+
- Adding a new HTTP method to an existing resource
|
|
356
|
+
|
|
357
|
+
These changes are **breaking** (require a new version):
|
|
358
|
+
|
|
359
|
+
- Removing or renaming a field
|
|
360
|
+
- Changing a field's type (string → integer)
|
|
361
|
+
- Changing a field from optional to required
|
|
362
|
+
- Removing an endpoint
|
|
363
|
+
- Changing the URL structure
|
|
364
|
+
- Changing authentication requirements
|
|
365
|
+
- Changing the meaning of a status code or error code
|
|
366
|
+
|
|
367
|
+
### Deprecation Strategy
|
|
368
|
+
|
|
369
|
+
1. **Announce deprecation.** Add `Deprecation: true` and `Sunset: Sat, 01 Mar 2025 00:00:00 GMT` headers (RFC 8594). Update documentation. Send emails to API consumers.
|
|
370
|
+
2. **Migration period.** Give clients 6-12 months minimum. For payment APIs, 18-24 months. Provide a migration guide with before/after examples.
|
|
371
|
+
3. **Monitor usage.** Track which clients still use deprecated endpoints. Reach out directly to high-volume consumers.
|
|
372
|
+
4. **Soft shutdown.** Return `299 Deprecated` warning headers for 1-2 months before removal.
|
|
373
|
+
5. **Hard shutdown.** Return `410 Gone` with a body explaining the replacement endpoint.
|
|
374
|
+
|
|
375
|
+
### Evolution Without Versioning
|
|
376
|
+
|
|
377
|
+
Sometimes you can evolve an API without creating a new version:
|
|
378
|
+
|
|
379
|
+
- **Additive changes.** New fields, new endpoints — these never break existing clients if clients ignore unknown fields (Postel's Law: be liberal in what you accept).
|
|
380
|
+
- **Stripe's approach.** Stripe maintains a single codebase that serves all API versions simultaneously. Incoming requests are transformed to the latest internal format, processed, then the response is transformed back to the client's pinned version. This is expensive to maintain but eliminates the "which version do I use?" question for developers.
|
|
381
|
+
- **Feature flags.** Use request headers or account settings to opt into new behavior without changing the URL version.
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## Failure Modes
|
|
386
|
+
|
|
387
|
+
These are the ways REST API designs fail in production. Each is common and avoidable.
|
|
388
|
+
|
|
389
|
+
### Chatty APIs (N+1 Problem)
|
|
390
|
+
|
|
391
|
+
**What happens:** A client needs data from multiple related resources and must make separate requests for each. Displaying an order with 10 line items requires 1 + 10 requests (the order + each item). On mobile over a 200ms-latency connection, that's 2+ seconds of network time alone.
|
|
392
|
+
|
|
393
|
+
**Why it happens:** Rigid adherence to "one resource per endpoint" without providing mechanisms to fetch related data efficiently.
|
|
394
|
+
|
|
395
|
+
**How to avoid it:** Provide `expand` or `include` parameters (`GET /orders/42?expand=items,customer`). Support compound documents. Consider GraphQL if your domain is deeply relational and clients have diverse data needs.
|
|
396
|
+
|
|
397
|
+
### Missing Pagination
|
|
398
|
+
|
|
399
|
+
**What happens:** An endpoint returns all results. It works in development with 50 records. In production with 500,000 records, it times out, OOMs the server, or crashes the client.
|
|
400
|
+
|
|
401
|
+
**Why it happens:** "We'll add pagination later." Later never comes until production is on fire.
|
|
402
|
+
|
|
403
|
+
**How to avoid it:** Every collection endpoint gets pagination from day one. Default to 20-50 items per page. Set a maximum page size (e.g., 100). Return `has_more` or total count metadata.
|
|
404
|
+
|
|
405
|
+
### Breaking Changes Without Versioning
|
|
406
|
+
|
|
407
|
+
**What happens:** A field is renamed from `userName` to `user_name`. Every client breaks. A field type changes from string to integer. Every client's JSON parser throws. An endpoint is removed. Every client that called it gets 404s.
|
|
408
|
+
|
|
409
|
+
**Why it happens:** No versioning strategy, no backward compatibility policy, no API review process.
|
|
410
|
+
|
|
411
|
+
**How to avoid it:** Establish a "no breaking changes without a version bump" policy. Add API change review to your development process. Stripe's API Review Board reviews every API change — adopt a similar practice scaled to your team size.
|
|
412
|
+
|
|
413
|
+
### Inconsistent Naming and Structure
|
|
414
|
+
|
|
415
|
+
**What happens:** One endpoint returns `createdAt`, another returns `created_at`, a third returns `creation_date`. One endpoint wraps results in `{"data": [...]}`, another returns a bare array. One endpoint uses `user_id`, another uses `userId`, a third uses `owner`.
|
|
416
|
+
|
|
417
|
+
**Why it happens:** Multiple developers build endpoints independently without a shared style guide.
|
|
418
|
+
|
|
419
|
+
**How to avoid it:** Create and enforce an API style guide. Pick one naming convention (snake_case is most common for JSON APIs) and one envelope format. Use linting tools (Spectral for OpenAPI specs) to enforce consistency automatically.
|
|
420
|
+
|
|
421
|
+
### Misusing HTTP Methods
|
|
422
|
+
|
|
423
|
+
**What happens:** `GET /users/42/delete` deletes a user. `POST /search` performs a read-only search. `PUT /users` creates a new user.
|
|
424
|
+
|
|
425
|
+
**Why it happens:** Developers unfamiliar with REST conventions, or a codebase that evolved from an RPC-style API.
|
|
426
|
+
|
|
427
|
+
**How to avoid it:** `GET` is safe and idempotent — never modify state. `POST` creates. `PUT` replaces. `PATCH` partially updates. `DELETE` removes. No exceptions. Code review for HTTP method correctness.
|
|
428
|
+
|
|
429
|
+
### Exposing Internal Implementation
|
|
430
|
+
|
|
431
|
+
**What happens:** API responses include database column names (`usr_nm`), auto-increment IDs (sequential, guessable), internal error stack traces, or ORM-specific field names.
|
|
432
|
+
|
|
433
|
+
**Why it happens:** The API layer is too thin — it serializes database rows directly to JSON without a presentation layer.
|
|
434
|
+
|
|
435
|
+
**How to avoid it:** Use response DTOs (Data Transfer Objects) or serializers that explicitly define what fields are exposed. Use UUIDs or prefixed IDs (`usr_abc123`) instead of sequential integers. Never expose stack traces in production — log them server-side and return a correlation ID.
|
|
436
|
+
|
|
437
|
+
### Ignoring Partial Failures in Distributed Systems
|
|
438
|
+
|
|
439
|
+
**What happens:** `POST /orders` creates an order in the database but fails to send the confirmation email. The API returns 500 even though the order was created. The client retries and creates a duplicate order.
|
|
440
|
+
|
|
441
|
+
**Why it happens:** Treating multi-step operations as atomic when they aren't.
|
|
442
|
+
|
|
443
|
+
**How to avoid it:** Use idempotency keys for non-idempotent operations. Separate the core operation from side effects (create the order synchronously, send the email asynchronously via a queue). Return 201 for partial success with a status indicating which side effects are pending.
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## Technology Landscape
|
|
448
|
+
|
|
449
|
+
### Frameworks
|
|
450
|
+
|
|
451
|
+
| Framework | Language | Strengths | Best For |
|
|
452
|
+
|-----------|----------|-----------|----------|
|
|
453
|
+
| **Express** | Node.js | Minimal, flexible, massive ecosystem | Small-to-medium APIs, prototypes |
|
|
454
|
+
| **Fastify** | Node.js | 2-3x faster than Express, schema validation built-in | Performance-sensitive Node.js APIs |
|
|
455
|
+
| **NestJS** | TypeScript | Opinionated, modular, decorator-based, OpenAPI generation | Enterprise TypeScript APIs |
|
|
456
|
+
| **FastAPI** | Python | Async, auto-generated OpenAPI docs, type hints as validation | Python APIs, ML model serving |
|
|
457
|
+
| **Django REST Framework** | Python | Batteries-included, ORM integration, browsable API | Data-heavy Python applications |
|
|
458
|
+
| **Spring Boot** | Java/Kotlin | Enterprise-grade, massive ecosystem, Spring Security | Enterprise Java APIs |
|
|
459
|
+
| **ASP.NET Core** | C# | High performance, minimal API syntax, built-in OpenAPI | .NET ecosystem APIs |
|
|
460
|
+
| **Gin** | Go | Extremely fast, minimal memory footprint | High-performance Go APIs |
|
|
461
|
+
| **Phoenix** | Elixir | Real-time capabilities, fault-tolerant (BEAM VM) | APIs needing real-time features |
|
|
462
|
+
| **Rails API** | Ruby | Convention over configuration, rapid development | Rapid prototyping, startups |
|
|
463
|
+
|
|
464
|
+
### API Gateways
|
|
465
|
+
|
|
466
|
+
**Kong** — Open-source, Lua/Nginx-based. Plugin ecosystem for auth, rate limiting, transformations. Dominant in the open-source gateway space.
|
|
467
|
+
|
|
468
|
+
**AWS API Gateway** — Managed service. Integrates with Lambda, IAM, Cognito. Best for AWS-native architectures.
|
|
469
|
+
|
|
470
|
+
**Apigee (Google)** — Enterprise API management. Analytics, monetization, developer portal. Expensive but comprehensive.
|
|
471
|
+
|
|
472
|
+
**Envoy** — High-performance proxy built for service mesh. Used as a data plane in Istio. Not a traditional API gateway but increasingly used as one.
|
|
473
|
+
|
|
474
|
+
### Documentation Tools
|
|
475
|
+
|
|
476
|
+
**Swagger UI / Redocly** — Render OpenAPI specs as interactive documentation. Redocly produces more polished output. Both support "try it out" functionality.
|
|
477
|
+
|
|
478
|
+
**Postman** — API development platform with documentation, testing, and collaboration features. Collections can serve as living documentation.
|
|
479
|
+
|
|
480
|
+
**ReadMe** — Developer hub platform. Integrates OpenAPI specs with guides, changelogs, and API key management.
|
|
481
|
+
|
|
482
|
+
### Testing Tools
|
|
483
|
+
|
|
484
|
+
**Postman/Newman** — Manual and automated API testing. Newman runs Postman collections in CI/CD.
|
|
485
|
+
|
|
486
|
+
**REST Assured** — Java library for testing REST APIs. Fluent DSL: `given().auth().basic("user","pass").when().get("/users").then().statusCode(200)`.
|
|
487
|
+
|
|
488
|
+
**Dredd** — Tests API implementations against OpenAPI/API Blueprint specs. Catches spec drift automatically.
|
|
489
|
+
|
|
490
|
+
**Spectral** — OpenAPI linter. Enforces API style guide rules on your spec file. Catches inconsistencies before implementation.
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
494
|
+
## Decision Tree
|
|
495
|
+
|
|
496
|
+
Use this to choose the right API paradigm for your specific situation:
|
|
497
|
+
|
|
498
|
+
```
|
|
499
|
+
Is this a public API consumed by external developers?
|
|
500
|
+
├── Yes → REST (broadest compatibility, best tooling, lowest learning curve)
|
|
501
|
+
│ Consider: OpenAPI spec, SDKs, sandbox environment
|
|
502
|
+
│
|
|
503
|
+
└── No → Is this internal service-to-service communication?
|
|
504
|
+
├── Yes → Is latency/throughput critical (>1000 req/sec between services)?
|
|
505
|
+
│ ├── Yes → gRPC (binary protocol, code-gen, HTTP/2 multiplexing)
|
|
506
|
+
│ └── No → Do clients need flexible, deeply nested queries?
|
|
507
|
+
│ ├── Yes → GraphQL (client-driven queries, single round-trip)
|
|
508
|
+
│ └── No → REST (simplicity, universal tooling, easy debugging)
|
|
509
|
+
│
|
|
510
|
+
└── No → Is this for a web/mobile frontend?
|
|
511
|
+
├── Yes → Do different screens need very different data shapes?
|
|
512
|
+
│ ├── Yes → GraphQL (avoid bespoke endpoints per screen)
|
|
513
|
+
│ └── No → REST (simpler, cacheable, works everywhere)
|
|
514
|
+
│ Does the app need real-time updates?
|
|
515
|
+
│ ├── Yes → REST + WebSockets (REST for CRUD, WS for live updates)
|
|
516
|
+
│ └── No → REST
|
|
517
|
+
│
|
|
518
|
+
└── Is this for IoT or embedded devices?
|
|
519
|
+
├── Yes → gRPC or MQTT (binary efficiency, low bandwidth)
|
|
520
|
+
└── No → REST (safe default for anything not listed above)
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
**The short version:** If you don't have a specific reason to choose something else, choose REST. If you have a specific problem REST handles poorly (complex queries, high-performance internal calls, real-time), choose the tool designed for that problem. Many production systems use multiple paradigms: REST for the public API, gRPC between internal services, WebSockets for real-time features.
|
|
524
|
+
|
|
525
|
+
---
|
|
526
|
+
|
|
527
|
+
## Implementation Sketch
|
|
528
|
+
|
|
529
|
+
### OpenAPI Specification (Design-First)
|
|
530
|
+
|
|
531
|
+
```yaml
|
|
532
|
+
openapi: 3.1.0
|
|
533
|
+
info:
|
|
534
|
+
title: Order Service API
|
|
535
|
+
version: "1.0"
|
|
536
|
+
description: Manages customer orders
|
|
537
|
+
contact:
|
|
538
|
+
email: api-team@example.com
|
|
539
|
+
|
|
540
|
+
servers:
|
|
541
|
+
- url: https://api.example.com/v1
|
|
542
|
+
description: Production
|
|
543
|
+
- url: https://api.staging.example.com/v1
|
|
544
|
+
description: Staging
|
|
545
|
+
|
|
546
|
+
paths:
|
|
547
|
+
/orders:
|
|
548
|
+
get:
|
|
549
|
+
summary: List orders
|
|
550
|
+
operationId: listOrders
|
|
551
|
+
parameters:
|
|
552
|
+
- name: status
|
|
553
|
+
in: query
|
|
554
|
+
schema:
|
|
555
|
+
type: string
|
|
556
|
+
enum: [pending, confirmed, shipped, delivered, cancelled]
|
|
557
|
+
- name: customer_id
|
|
558
|
+
in: query
|
|
559
|
+
schema:
|
|
560
|
+
type: string
|
|
561
|
+
- name: after
|
|
562
|
+
in: query
|
|
563
|
+
description: Cursor for pagination
|
|
564
|
+
schema:
|
|
565
|
+
type: string
|
|
566
|
+
- name: limit
|
|
567
|
+
in: query
|
|
568
|
+
schema:
|
|
569
|
+
type: integer
|
|
570
|
+
default: 20
|
|
571
|
+
maximum: 100
|
|
572
|
+
responses:
|
|
573
|
+
"200":
|
|
574
|
+
description: List of orders
|
|
575
|
+
content:
|
|
576
|
+
application/json:
|
|
577
|
+
schema:
|
|
578
|
+
type: object
|
|
579
|
+
properties:
|
|
580
|
+
data:
|
|
581
|
+
type: array
|
|
582
|
+
items:
|
|
583
|
+
$ref: "#/components/schemas/Order"
|
|
584
|
+
pagination:
|
|
585
|
+
$ref: "#/components/schemas/Pagination"
|
|
586
|
+
"401":
|
|
587
|
+
$ref: "#/components/responses/Unauthorized"
|
|
588
|
+
"429":
|
|
589
|
+
$ref: "#/components/responses/RateLimited"
|
|
590
|
+
|
|
591
|
+
post:
|
|
592
|
+
summary: Create an order
|
|
593
|
+
operationId: createOrder
|
|
594
|
+
parameters:
|
|
595
|
+
- name: Idempotency-Key
|
|
596
|
+
in: header
|
|
597
|
+
required: true
|
|
598
|
+
schema:
|
|
599
|
+
type: string
|
|
600
|
+
format: uuid
|
|
601
|
+
requestBody:
|
|
602
|
+
required: true
|
|
603
|
+
content:
|
|
604
|
+
application/json:
|
|
605
|
+
schema:
|
|
606
|
+
$ref: "#/components/schemas/CreateOrderRequest"
|
|
607
|
+
responses:
|
|
608
|
+
"201":
|
|
609
|
+
description: Order created
|
|
610
|
+
headers:
|
|
611
|
+
Location:
|
|
612
|
+
schema:
|
|
613
|
+
type: string
|
|
614
|
+
description: URL of the created order
|
|
615
|
+
content:
|
|
616
|
+
application/json:
|
|
617
|
+
schema:
|
|
618
|
+
$ref: "#/components/schemas/Order"
|
|
619
|
+
"422":
|
|
620
|
+
$ref: "#/components/responses/ValidationError"
|
|
621
|
+
|
|
622
|
+
/orders/{order_id}:
|
|
623
|
+
get:
|
|
624
|
+
summary: Retrieve an order
|
|
625
|
+
operationId: getOrder
|
|
626
|
+
parameters:
|
|
627
|
+
- name: order_id
|
|
628
|
+
in: path
|
|
629
|
+
required: true
|
|
630
|
+
schema:
|
|
631
|
+
type: string
|
|
632
|
+
- name: expand
|
|
633
|
+
in: query
|
|
634
|
+
description: Related resources to include
|
|
635
|
+
schema:
|
|
636
|
+
type: array
|
|
637
|
+
items:
|
|
638
|
+
type: string
|
|
639
|
+
enum: [customer, items, items.product]
|
|
640
|
+
responses:
|
|
641
|
+
"200":
|
|
642
|
+
description: Order details
|
|
643
|
+
content:
|
|
644
|
+
application/json:
|
|
645
|
+
schema:
|
|
646
|
+
$ref: "#/components/schemas/Order"
|
|
647
|
+
"404":
|
|
648
|
+
$ref: "#/components/responses/NotFound"
|
|
649
|
+
|
|
650
|
+
components:
|
|
651
|
+
schemas:
|
|
652
|
+
Order:
|
|
653
|
+
type: object
|
|
654
|
+
properties:
|
|
655
|
+
id:
|
|
656
|
+
type: string
|
|
657
|
+
example: "ord_abc123"
|
|
658
|
+
status:
|
|
659
|
+
type: string
|
|
660
|
+
enum: [pending, confirmed, shipped, delivered, cancelled]
|
|
661
|
+
customer_id:
|
|
662
|
+
type: string
|
|
663
|
+
total_amount:
|
|
664
|
+
type: integer
|
|
665
|
+
description: Amount in cents
|
|
666
|
+
currency:
|
|
667
|
+
type: string
|
|
668
|
+
example: "usd"
|
|
669
|
+
items:
|
|
670
|
+
type: array
|
|
671
|
+
items:
|
|
672
|
+
$ref: "#/components/schemas/OrderItem"
|
|
673
|
+
created_at:
|
|
674
|
+
type: string
|
|
675
|
+
format: date-time
|
|
676
|
+
updated_at:
|
|
677
|
+
type: string
|
|
678
|
+
format: date-time
|
|
679
|
+
|
|
680
|
+
OrderItem:
|
|
681
|
+
type: object
|
|
682
|
+
properties:
|
|
683
|
+
id:
|
|
684
|
+
type: string
|
|
685
|
+
product_id:
|
|
686
|
+
type: string
|
|
687
|
+
quantity:
|
|
688
|
+
type: integer
|
|
689
|
+
unit_price:
|
|
690
|
+
type: integer
|
|
691
|
+
description: Price in cents
|
|
692
|
+
|
|
693
|
+
CreateOrderRequest:
|
|
694
|
+
type: object
|
|
695
|
+
required: [customer_id, items]
|
|
696
|
+
properties:
|
|
697
|
+
customer_id:
|
|
698
|
+
type: string
|
|
699
|
+
items:
|
|
700
|
+
type: array
|
|
701
|
+
minItems: 1
|
|
702
|
+
items:
|
|
703
|
+
type: object
|
|
704
|
+
required: [product_id, quantity]
|
|
705
|
+
properties:
|
|
706
|
+
product_id:
|
|
707
|
+
type: string
|
|
708
|
+
quantity:
|
|
709
|
+
type: integer
|
|
710
|
+
minimum: 1
|
|
711
|
+
|
|
712
|
+
Pagination:
|
|
713
|
+
type: object
|
|
714
|
+
properties:
|
|
715
|
+
has_more:
|
|
716
|
+
type: boolean
|
|
717
|
+
next_cursor:
|
|
718
|
+
type: string
|
|
719
|
+
nullable: true
|
|
720
|
+
|
|
721
|
+
ProblemDetail:
|
|
722
|
+
type: object
|
|
723
|
+
properties:
|
|
724
|
+
type:
|
|
725
|
+
type: string
|
|
726
|
+
format: uri
|
|
727
|
+
title:
|
|
728
|
+
type: string
|
|
729
|
+
status:
|
|
730
|
+
type: integer
|
|
731
|
+
detail:
|
|
732
|
+
type: string
|
|
733
|
+
instance:
|
|
734
|
+
type: string
|
|
735
|
+
|
|
736
|
+
responses:
|
|
737
|
+
Unauthorized:
|
|
738
|
+
description: Authentication required
|
|
739
|
+
content:
|
|
740
|
+
application/problem+json:
|
|
741
|
+
schema:
|
|
742
|
+
$ref: "#/components/schemas/ProblemDetail"
|
|
743
|
+
NotFound:
|
|
744
|
+
description: Resource not found
|
|
745
|
+
content:
|
|
746
|
+
application/problem+json:
|
|
747
|
+
schema:
|
|
748
|
+
$ref: "#/components/schemas/ProblemDetail"
|
|
749
|
+
ValidationError:
|
|
750
|
+
description: Request validation failed
|
|
751
|
+
content:
|
|
752
|
+
application/problem+json:
|
|
753
|
+
schema:
|
|
754
|
+
$ref: "#/components/schemas/ProblemDetail"
|
|
755
|
+
RateLimited:
|
|
756
|
+
description: Rate limit exceeded
|
|
757
|
+
headers:
|
|
758
|
+
Retry-After:
|
|
759
|
+
schema:
|
|
760
|
+
type: integer
|
|
761
|
+
content:
|
|
762
|
+
application/problem+json:
|
|
763
|
+
schema:
|
|
764
|
+
$ref: "#/components/schemas/ProblemDetail"
|
|
765
|
+
|
|
766
|
+
securitySchemes:
|
|
767
|
+
BearerAuth:
|
|
768
|
+
type: http
|
|
769
|
+
scheme: bearer
|
|
770
|
+
description: API key prefixed with sk_live_ or sk_test_
|
|
771
|
+
|
|
772
|
+
security:
|
|
773
|
+
- BearerAuth: []
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
### Request/Response Examples
|
|
777
|
+
|
|
778
|
+
**Creating an order:**
|
|
779
|
+
```http
|
|
780
|
+
POST /v1/orders HTTP/1.1
|
|
781
|
+
Host: api.example.com
|
|
782
|
+
Authorization: Bearer sk_live_abc123
|
|
783
|
+
Content-Type: application/json
|
|
784
|
+
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
|
|
785
|
+
|
|
786
|
+
{
|
|
787
|
+
"customer_id": "cus_xyz789",
|
|
788
|
+
"items": [
|
|
789
|
+
{"product_id": "prod_001", "quantity": 2},
|
|
790
|
+
{"product_id": "prod_042", "quantity": 1}
|
|
791
|
+
]
|
|
792
|
+
}
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
**Successful response:**
|
|
796
|
+
```http
|
|
797
|
+
HTTP/1.1 201 Created
|
|
798
|
+
Location: /v1/orders/ord_abc123
|
|
799
|
+
Content-Type: application/json
|
|
800
|
+
X-RateLimit-Limit: 1000
|
|
801
|
+
X-RateLimit-Remaining: 999
|
|
802
|
+
|
|
803
|
+
{
|
|
804
|
+
"id": "ord_abc123",
|
|
805
|
+
"status": "pending",
|
|
806
|
+
"customer_id": "cus_xyz789",
|
|
807
|
+
"total_amount": 4500,
|
|
808
|
+
"currency": "usd",
|
|
809
|
+
"items": [
|
|
810
|
+
{"id": "oli_001", "product_id": "prod_001", "quantity": 2, "unit_price": 1500},
|
|
811
|
+
{"id": "oli_002", "product_id": "prod_042", "quantity": 1, "unit_price": 1500}
|
|
812
|
+
],
|
|
813
|
+
"created_at": "2024-01-15T10:30:00Z",
|
|
814
|
+
"updated_at": "2024-01-15T10:30:00Z"
|
|
815
|
+
}
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
**Validation error:**
|
|
819
|
+
```http
|
|
820
|
+
HTTP/1.1 422 Unprocessable Entity
|
|
821
|
+
Content-Type: application/problem+json
|
|
822
|
+
|
|
823
|
+
{
|
|
824
|
+
"type": "https://api.example.com/errors/validation-error",
|
|
825
|
+
"title": "Validation Error",
|
|
826
|
+
"status": 422,
|
|
827
|
+
"detail": "The 'quantity' field must be a positive integer.",
|
|
828
|
+
"instance": "/v1/orders",
|
|
829
|
+
"errors": [
|
|
830
|
+
{
|
|
831
|
+
"field": "items[0].quantity",
|
|
832
|
+
"code": "invalid_value",
|
|
833
|
+
"message": "Must be greater than 0. Received: -1"
|
|
834
|
+
}
|
|
835
|
+
]
|
|
836
|
+
}
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
**Paginated list:**
|
|
840
|
+
```http
|
|
841
|
+
GET /v1/orders?status=shipped&limit=2&after=eyJpZCI6Im9yZF8wNTAifQ HTTP/1.1
|
|
842
|
+
Authorization: Bearer sk_live_abc123
|
|
843
|
+
```
|
|
844
|
+
|
|
845
|
+
```http
|
|
846
|
+
HTTP/1.1 200 OK
|
|
847
|
+
Content-Type: application/json
|
|
848
|
+
|
|
849
|
+
{
|
|
850
|
+
"data": [
|
|
851
|
+
{"id": "ord_051", "status": "shipped", "total_amount": 3200, "...": "..."},
|
|
852
|
+
{"id": "ord_052", "status": "shipped", "total_amount": 7800, "...": "..."}
|
|
853
|
+
],
|
|
854
|
+
"pagination": {
|
|
855
|
+
"has_more": true,
|
|
856
|
+
"next_cursor": "eyJpZCI6Im9yZF8wNTIifQ"
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
---
|
|
862
|
+
|
|
863
|
+
## API Design Checklist
|
|
864
|
+
|
|
865
|
+
Use this checklist before launching any REST API:
|
|
866
|
+
|
|
867
|
+
- [ ] Every resource uses plural nouns (`/users`, not `/user`)
|
|
868
|
+
- [ ] HTTP methods match semantics (GET reads, POST creates, PUT replaces, PATCH updates, DELETE removes)
|
|
869
|
+
- [ ] Status codes are correct (201 for creation, 204 for deletion, 404 for missing, 422 for validation)
|
|
870
|
+
- [ ] Every collection endpoint is paginated with a maximum page size
|
|
871
|
+
- [ ] Error responses follow a consistent format (preferably RFC 9457)
|
|
872
|
+
- [ ] Error messages tell the client how to fix the problem
|
|
873
|
+
- [ ] Authentication is required and uses HTTPS exclusively
|
|
874
|
+
- [ ] Rate limiting is implemented with appropriate headers
|
|
875
|
+
- [ ] POST endpoints accept idempotency keys
|
|
876
|
+
- [ ] Field naming is consistent across all endpoints (pick one: snake_case or camelCase)
|
|
877
|
+
- [ ] Response envelopes are consistent (`{"data": ...}` everywhere or nowhere)
|
|
878
|
+
- [ ] Dates use ISO 8601 format (`2024-01-15T10:30:00Z`)
|
|
879
|
+
- [ ] Monetary amounts use smallest currency unit (cents, not dollars) to avoid floating-point issues
|
|
880
|
+
- [ ] API is versioned from day one
|
|
881
|
+
- [ ] OpenAPI spec exists and is kept in sync with implementation
|
|
882
|
+
- [ ] No internal implementation details leak (no DB column names, no stack traces, no sequential IDs)
|
|
883
|
+
|
|
884
|
+
---
|
|
885
|
+
|
|
886
|
+
## Cross-References
|
|
887
|
+
|
|
888
|
+
- **[api-design-graphql](../integration/api-design-graphql.md)** — When REST's resource model doesn't fit and clients need flexible queries
|
|
889
|
+
- **[api-design-grpc](../integration/api-design-grpc.md)** — When binary efficiency and type safety matter more than simplicity
|
|
890
|
+
- **[websockets-realtime](../integration/websockets-realtime.md)** — When you need server-to-client push or bidirectional communication
|
|
891
|
+
- **[webhooks-and-callbacks](../integration/webhooks-and-callbacks.md)** — When the server needs to notify external systems of events
|
|
892
|
+
- **[microservices](../patterns/microservices.md)** — REST is often the inter-service protocol; understanding both patterns together is essential
|