Version in the URL and mean it
Prefix routes with /api/v1 (or a dedicated subdomain) and treat a version as a compatibility boundary. Breaking changes ship as v2 while v1 stays online with a documented sunset. Laravel makes this painless with route groups and, where useful, dedicated route files per version so diffs stay readable in code review.
Communicate deprecation with response headers (Deprecation, Sunset, Link to migration docs) so automated monitors and client teams get the same signal.
Pick auth to match the client, not the blog post
Laravel Sanctum remains the default sweet spot for first-party SPAs, mobile apps you control, and token-based access without full OAuth ceremony. Use ability-scoped tokens, short lifetimes where appropriate, and rotation policies that your threat model actually requires.
Reach for Laravel Passport (or an external IdP) when third parties need OAuth2 flows, delegated access, or formal client credentials. Mixing “Sanctum because it is easy” with “public developer platform” is how you rebuild auth twice—decide up front.
Validation and authorization at the boundary
Form requests (or dedicated request classes) keep input rules next to the endpoint and give you one place for authorize() checks. Controllers should orchestrate, not re-validate in five branches.
Pair that with policies on model actions so the same rules back both JSON APIs and any internal UI. For SaaS, layer tenant context in middleware and query scopes so a missing clause cannot expose another customer’s primary keys.
Serialization: Api Resources and JSON:API
Eloquent API Resources keep response shape stable as columns and relations evolve—use them for projection, hiding internal fields, and embedding related data deliberately (not via accidental lazy loading).
On Laravel 13, first-party JSON:API resources are the right tool when integrators expect spec-compliant payloads: resource objects, relationship inclusion, sparse fieldsets, and the headers clients like Insomnia and OpenAPI generators understand. You still choose “simple JSON” vs “JSON:API” per audience—just do not pretend they are interchangeable without documentation.
Errors clients can program against
Return a consistent envelope for failures: machine-readable codes, human-readable messages, and structured errors keyed by field for validation. Laravel’s validation exception format is a good baseline; for public platforms, consider aligning with Problem Details (RFC 9457) or JSON:API error objects when you have committed to that spec.
Never leak stack traces or SQL to consumers. Map unexpected exceptions to a generic 500 with a correlation id logged server-side for support.
Pagination, filtering, and sorting—documented
Use Laravel’s cursor or offset pagination consistently and include link/meta blocks your SDKs can rely on. For filters, prefer explicit query parameters (filter[status]=active) over ad-hoc SQL fragments from the client.
Guard sortable columns with allow-lists to prevent sort-based timing attacks and accidental full-table scans.
Rate limiting and abuse resistance
Apply throttle middleware per route group and per user or API key. Public endpoints and expensive aggregations deserve stricter buckets than authenticated CRUD. Combine limits with idempotency keys for critical writes (payments, provisioning) when duplicates are unacceptable—often implemented via cache or dedicated store with a short TTL.
CORS, HTTPS, and CSRF boundaries
Configure CORS explicitly—wildcard origins and credentials are rarely both correct. Terminate TLS at the edge; enforce HTTPS in production. For cookie-based SPA auth, understand when SameSite, CSRF, and Sanctum’s SPA setup apply; for pure bearer-token APIs, document that contract clearly so frontends do not mix models.
Testing and contracts
Feature tests should assert status codes, JSON structure, and critical headers—not just “200 OK.” Snapshot large payloads sparingly; prefer asserting keys and types. Where multiple clients depend on you, publish an OpenAPI description and optionally validate responses against it in CI.
Observability
Log request id, user id, tenant id, and route name. Queue slow queries and N+1 detection in non-production. Laravel’s built-in logging, queue workers, and tools like Telescope (guarded in production) keep API regressions diagnosable without SSH forensics.
Quick 2026 checklist
- Versioned base path and a written deprecation policy
- Auth choice matches client type (Sanctum vs OAuth/Passport)
- Form requests + policies + tenant safety nets
- Resources or JSON:API for stable output
- Predictable errors with correlation ids
- Throttles, CORS, and TLS done deliberately
- Tests (and optionally OpenAPI) backing the contract
Laravel already ships the pieces; the best practice in 2026 is discipline at the HTTP boundary so your API stays boring—in the way operators and integrators love.