Skip to main content
Laravel, shipping fast.

Generated documentation can still be wrong, in two ways. It can be stale, because nobody regenerated it. And the code can change the contract without anybody noticing that it did.

Both are solved by treating the OpenAPI document as a build artifact that is checked in.

Commit the document. Export it to a file in the repository, openapi.json, and commit it. Now a change to the API’s contract shows up in a pull request as a diff to that file, where a reviewer can see it. “You added a required field” stops being something a consumer discovers and becomes something a reviewer approves.

Fail the build when it is stale. In the pipeline from Chapter 14, regenerate the document and compare:

- run: php artisan scramble:export --path=openapi.json
- run: git diff --exit-code openapi.json

The first line is Scramble’s export command at the time of writing. Scribe has its own.

If the code and the committed document disagree, the build is red. The developer regenerates, looks at the diff, and commits it.

Detect breaking changes mechanically. Chapter 16 lists what breaks a consumer: a removed field, a renamed one, a changed type, a new required parameter. Every one of those is visible as a difference between two OpenAPI documents, and there are tools that compare two versions and classify each change as breaking or not. Run one in the pipeline against the document on the main branch, and a breaking change can’t merge by accident. It can only merge on purpose, with a new version.

That turns Chapter 16’s rule from something reviewers have to remember into something the pipeline enforces.

Document the Errors

The part of an API that gets the least documentation is the part consumers spend the most time in.

For each error, a consumer needs three things: how to recognize it, what caused it, and what to do. A table does it:

| Status | code | What to do | |--------|--------|-----------| | 400 | | The Idempotency-Key isn’t a UUID. Fix the client | | 401 | | Check the token. It may have expired | | 403 | | The token lacks an ability. Ask for one that has it | | 404 | | It doesn’t exist, or isn’t yours to see | | 409 | request_in_progress | Retry after Retry-After seconds | | 409 | license_limit_reached | Don’t retry. Remove a license or ask for a higher limit | | 422 | | Fix the fields named in errors. Don’t retry unchanged | | 422 | | No errors: the idempotency key was already used for a different request | | 429 | | Wait for Retry-After seconds, then retry | | 502 | provider_failed | Safe to retry with the same idempotency key | | 502 | provider_rejected | Retrying won’t help. Contact support | | 504 | provider_unavailable | Safe to retry with the same idempotency key |

The last column is the one most documentation leaves out, and the one that saves a support request.

The code values come from the ErrorCode enum in Chapter 7. Generate this table’s rows from the enum, and a code can’t be added to the API without appearing in the documentation.

The audio could not be loaded. Try again in a moment.