What we settle before writing endpoints
The specification is written first
We write the OpenAPI specification first and review it with whoever will consume the API. Arguments about field names, nesting and nullability are settled in a document, where changing your mind costs minutes. Front-end and mobile developers can then work against a mock server generated from the same file while the real endpoints are built. Dates are ISO 8601 in UTC, money is an integer amount in minor units with a currency code, IDs are opaque strings. Small rules like these, applied without exception, remove most integration bugs.
Tokens, OAuth2 or keys
There is no single right answer here, only a fit for each kind of consumer.
- Your own mobile app or SPA: short-lived access tokens with refresh tokens that can be revoked per device, or secure cookies for a same-domain SPA.
- Third parties acting for a user: the OAuth2 authorization code flow with PKCE, so passwords never pass through the partner.
- Server-to-server partners: API keys or client credentials, each with scopes and its own rate limit.
JWTs are useful when several services must verify a token without a database lookup. They are also hard to revoke, so we keep their lifetime short and do not reach for them by default.
Changing the API while old apps are still installed
Mobile apps make this unavoidable, because you cannot force every phone to update. Within a version we only add: new optional fields, new endpoints. Removing or renaming anything means a new version, and the old one stays up for an agreed period while usage logs show who still calls it. Contract tests replay the documented examples against every build, so an accidental change to a response fails the pipeline and never reaches a consumer.
Protecting the API from its own clients
Most overload comes from a well-meaning client stuck in a retry loop, far more often than from an attacker. Rate limits per token and per IP address, counted in Redis, keep one consumer from starving the rest. List endpoints always paginate, with a hard maximum page size. Write endpoints that create payments or orders accept an idempotency key, so a request retried after a timeout does not create a duplicate. Expensive reads get cache headers and conditional requests.
What it is built from in PHP
A small service needs no full framework. We assemble it from PSR-7 request and response objects and PSR-15 middleware for authentication, rate limiting and CORS, with Slim as the router and the PHP League OAuth2 server issuing tokens. Larger APIs with queues, mail and a big data model usually benefit from the tooling a framework brings, which is covered on our Laravel API development and CodeIgniter API development pages. The design rules above stay the same whichever one runs underneath.