agentleFS
AnyOrgNameAnyOrgName/php-skills/skills/api/openapi/SKILL.md

openapi

Skill4 starsChanged 4 months agoMITView on GitHub

Describe PHP HTTP APIs with OpenAPI 3 — author or generate the spec from route attributes (zircote/swagger-php), serve Swagger UI, validate requests and responses against it, version the contract, and choose contract-first vs code-first. Use when the user wants a machine-readable description of their PHP HTTP API — an OpenAPI/Swagger spec, interactive docs, or a client-facing contract; the user wants to generate an OpenAPI spec from PHP code — route attributes or annotations via zircote/swagger-php — rather than hand-writing YAML; the user wants to validate incoming requests or outgoing responses against an OpenAPI spec, or choose between contract-first and code-first workflows. Keywords: openapi, swagger, api, spec, contract-first, code-first, swagger-php, validation, versioning, documentation.

13 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

10 rules. 0 are common, 9 are distinctive, and 1 is very specific to this project.

  • 0

    Common

    Most of the 10 edited versions we read keep these.

  • 9

    Distinctive

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Do not use OpenAPI to describe a GraphQL API.

    line 81
  2. Distinctive:

    Do not model internal function calls, message-queue payloads, or gRPC services with OpenAPI.

    line 83
  3. Distinctive:

    Verify: The controllers carry OA attributes describing every public operation.

    line 137
  4. Very specific:

    Run the swagger-php scanner to emit openapi.json/openapi.yaml, commit it, and serve Swagger UI or Redoc from a docs route pointed at the …

    line 138
  5. Distinctive:

    Verify: The docs route renders Swagger UI listing every annotated operation.

    line 140
  6. Distinctive:

    Add a CI step that regenerates the spec and diffs it against the committed copy (failing on mismatch), and enable request validation …

    line 141
  7. Distinctive:

    Verify: CI fails when code and spec diverge, and request-validation tests pass against the spec.

    line 143
  8. Distinctive:

    Verify: The spec lints clean and consuming teams have signed off on the contract.

    line 159
  9. Distinctive:

    Verify: Generated server stubs compile and a generated client can call the documented operations.

    line 162
  10. Distinctive:

    Verify: Non-conforming requests are rejected and CI blocks breaking changes to the published contract.

    line 165

“Common” is measured: kept by at least 6 in 10 of the 10 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md
<!-- generated: do not edit — source: knowledge/atoms/api/openapi/ --><!-- schema: atomVersion=3 skillVersion=2 graphVersion=1 --><!-- compile: @php-skills/compiler v1.0.0 (deterministic build) -->

OpenAPI 3 for PHP APIs

When to use

  • The user wants a machine-readable description of their PHP HTTP API — an OpenAPI/Swagger spec, interactive docs, or a client-facing contract.
  • The user wants to generate an OpenAPI spec from PHP code — route attributes or annotations via zircote/swagger-php — rather than hand-writing YAML.
  • The user wants to validate incoming requests or outgoing responses against an OpenAPI spec, or choose between contract-first and code-first workflows.

When NOT to use

  • Do not use OpenAPI to describe a GraphQL API; GraphQL has its own SDL schema and introspection that already serves as the contract.
  • Do not model internal function calls, message-queue payloads, or gRPC services with OpenAPI; it describes HTTP/REST surfaces, not in-process or RPC contracts.

Core guidance

  • Choose contract-first for shared APIs, code-first for internal ones — Author the spec by hand first (contract-first) when multiple teams or external consumers depend on a stable interface; generate it from attributes (code-first) when one team owns both the API and its clients and wants the code as the source.
  • Declare auth with securitySchemes, never inline secrets — Describe authentication under components.securitySchemes (bearer/JWT, OAuth2, API key) and apply it per-operation with security, never embedding real tokens or example secrets in the spec.
  • Generate code-first specs with zircote/swagger-php attributes — For code-first APIs on PHP 8.1+, annotate controllers with zircote/swagger-php #[OA\...] attributes and run the scanner to emit openapi.json/yaml in CI.

Decision Engine

Walk this section before choosing an implementation path.

Do external teams or public clients depend on a stable, reviewed interface before
the code exists, or does one team own both the API and its consumers?

├── One team owns the API and its clients: → code-first — annotate controllers with zircote/swagger-php attributes and generate
the spec from code in CI so it stays in sync with the implementation.

├── External or cross-team consumers need a frozen contract: → contract-first — hand-author and review the spec before coding, publish it, and
generate server stubs and client SDKs from it so all sides build to one agreement.

├── Large existing API with no spec yet: → hybrid — generate a first draft from attributes to capture the current surface,
then hand-curate the spec and gate future changes with spec validation in CI.

└── Interface is GraphQL, gRPC, or internal RPC: → no OpenAPI — use the protocol's own contract (GraphQL SDL, protobuf/gRPC) instead
of forcing a REST description onto a non-REST interface.

Full engine: references/decision-engine.md — Decision Tree, Priority Matrix, Decision Table.

Workflows

Workflow: Code First Spec

Progress:
- [ ] Require `zircote/swagger-php`, add a root `#[OA\Info]` attribute, and annotate each
controller action with `#[OA\Get]`/`#[OA\Post]`, parameters, and response schemas
- [ ] Run the swagger-php scanner to emit `openapi.json`/`openapi.yaml`, commit it, and
serve Swagger UI or Redoc from a docs route pointed at the generated file
- [ ] Add a CI step that regenerates the spec and diffs it against the committed copy
(failing on mismatch), and enable request validation against the spec in tests
  1. Require zircote/swagger-php, add a root #[OA\Info] attribute, and annotate each controller action with #[OA\Get]/#[OA\Post], parameters, and response schemas.
    • Verify: The controllers carry OA attributes describing every public operation.
  2. Run the swagger-php scanner to emit openapi.json/openapi.yaml, commit it, and serve Swagger UI or Redoc from a docs route pointed at the generated file.
    • Verify: The docs route renders Swagger UI listing every annotated operation.
  3. Add a CI step that regenerates the spec and diffs it against the committed copy (failing on mismatch), and enable request validation against the spec in tests.
    • Verify: CI fails when code and spec diverge, and request-validation tests pass against the spec.

Workflow: Contract First Spec

Progress:
- [ ] Hand-write `openapi.yaml` with paths, `components.schemas`, and securitySchemes,
then review it with consumers and lint it (spectral) before any code is written
- [ ] Generate server interface stubs and client SDKs from the spec with openapi-generator
so both sides implement to the same reviewed contract
- [ ] Validate incoming requests against the committed spec with middleware, and add a CI
contract-diff step that fails on any breaking change to the current major version
  1. Hand-write openapi.yaml with paths, components.schemas, and securitySchemes, then review it with consumers and lint it (spectral) before any code is written.
    • Verify: The spec lints clean and consuming teams have signed off on the contract.
  2. Generate server interface stubs and client SDKs from the spec with openapi-generator so both sides implement to the same reviewed contract.
    • Verify: Generated server stubs compile and a generated client can call the documented operations.
  3. Validate incoming requests against the committed spec with middleware, and add a CI contract-diff step that fails on any breaking change to the current major version.
    • Verify: Non-conforming requests are rejected and CI blocks breaking changes to the published contract.

Best practices

  • Define reusable schemas, parameters, responses, and security schemes under components and reference them with $ref instead of repeating inline definitions
  • Enforce the spec at runtime by validating incoming requests (and optionally responses in tests) with middleware such as league/openapi-psr7-validator
  • Carry a semantic info.version, expose a major version in the path or header (/v1), and bump the major only for breaking changes while adding fields additively

Anti-patterns

Anti-patternWhy it failsDo instead
Publishing a spec but never validating against itHand-rolled per-endpoint validation drifts from the spec, so the documented contract and the enforced one diverge.Validate incoming requests against the spec with middleware (e.g.<br>league/openapi-psr7-validator) so the spec is the single enforced source of truth.
Embedding real tokens or internal endpoints in the public specA published spec is world-readable to its audience, so secrets and internal surfaces leak straight to clients.Declare auth via securitySchemes with placeholder examples, scope the public spec to<br>public operations, and serve any internal spec behind authentication.
Writing the spec once and never regenerating itThe code evolves while the untouched spec rots, so published docs and generated clients become wrong.Wire spec generation or validation into CI so the contract is regenerated or diffed<br>on every change and the build fails on drift.

See references/anti-patterns.md.

Debugging

  1. Making breaking changes without a version bump — Consumers cannot distinguish an intended breaking change from a bug; requests start failing in production. Fix: Prefer additive changes (add fields, deprecate old ones); when a break is unavoidable, ship a new major version path and run both until clients migrate.
  2. Documenting entities directly leaks internal fields — Internal fields (password hashes, soft-delete flags, foreign keys) leak to every consumer, and any refactor of the entity becomes a breaking API change. Fix: Map responses to explicit DTOs or resource classes and generate the spec from those, so the public shape is decoupled from persistence.
  3. Dangling or duplicated schema definitions — Duplicated shapes drift independently, and a dangling $ref fails validation and client generation. Fix: Define each shape once under components.schemas and $ref it everywhere; run a spec linter that resolves all references before publishing.
  4. The committed spec silently drifts from the code — Consumers trust the spec, so drift ships broken clients and undocumented behavior without any error. Fix: Regenerate (code-first) or diff (contract-first) the spec on every build and fail CI on any mismatch, plus validate responses against the spec in tests.

Production checklist

  • CI regenerates or diffs the OpenAPI spec on every build and fails on any mismatch with the code.
  • Reusable schemas, parameters, and responses are defined once under components and referenced with $ref, with no dangling refs.
  • The published spec is generated from response DTOs and scoped to public endpoints, with no entity fields or admin routes exposed.
  • Incoming requests are validated against the spec at the boundary so the contract is enforced, not just documented.
  • Every protected operation references a declared securityScheme and the spec contains no real secrets.
  • The spec carries a semantic info.version and a major version in the path or header, bumped only on breaking changes.

Version notes

  • OpenAPI 3.1 aligns with JSON Schema; swagger-php needs 8.1 for attributes (PHP >=8.1) — OpenAPI 3.1 is a full JSON Schema 2020-12 dialect (nullable via type arrays, webhooks) while 3.0 uses its own subset; zircote/swagger-php attribute syntax requires PHP 8.1+, with annotation (docblock) mode as the older fallback.

Security

  • Never leak internal schemas or secrets in a published spec — Treat the published OpenAPI spec as attacker-visible: generate schemas from response DTOs (not ORM entities), scope generation to public endpoints, strip internal fields, and put only placeholder examples in securitySchemes.

Testing

  • Activation and decision behavior are verified in eval/scenarios/api/openapi.yaml.

Additional resources

  • references/anti-patterns.md
  • references/core.md
  • references/decision-engine.md
  • references/examples.md
  • references/pitfalls.md
  • references/recipes.md
  • references/version-differences.md

Knowledge graph

Related: api/pagination, api/rest-design, api/versioning, laravel/routing, symfony/routing

<!-- graph-fragment: graph/fragments/api/openapi.yaml -->

Skill contract

Produces: api.openapi-spec
Requires: http.api-routes-defined
Risk: medium · Confidence: 0.9

<!-- contract-fragment: contracts/fragments/api/openapi.yaml -->

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.