En lugar de construir otra API «Hola mundo», usemos como guía una API real en producción: la Webplo License API. Es lo bastante simple como para entenderla rápido, y lo bastante real como para mostrar los patrones que importan.
La API hace una cosa, y la hace bien: gestiona licencias de sitios web.
Cada sitio de Webplo tiene su propia licencia, emitida automáticamente en cuanto el sitio se aprovisiona. A partir de ahí, los motores de Webplo interactúan con esta API para crear, consultar y revocar licencias según haga falta. No es una API pensada para consumo público: es un microservicio interno, uno de los muchos componentes que mueven Webplo entre bastidores.
Por debajo, esta API se integra directamente con la API de licencias de Statamic, ya que todo sitio de Webplo corre sobre Statamic CMS. La integración está estructurada con el patrón Manager-Facade-Driver, lo que nos permite mantener limpia la lógica central mientras soportamos varios drivers y futuras extensiones.
La API también maneja respuestas multilingües, límite de frecuencia, registro asíncrono y compresión de carga —no porque sea vistoso, sino porque necesita ser fiable.
Es una API en producción sirviendo tráfico real. Vamos a entender cómo funciona y qué hace que funcione bien.
Empezar desde cero
Si quieres seguirlo desde cero, levantemos un proyecto nuevo de Laravel:
composer create-project laravel/laravel api-license
cd api-license
php artisan key:generate
Eso es todo. Laravel ha hecho casi todo el trabajo pesado. Cuando empecé a programar en PHP hace doce años, montar un framework significaba conectar a mano ficheros de configuración, ajustar scripts de arranque y coserlo todo antes de poder escribir código de verdad. Laravel simplemente dice: «ya lo hemos pensado por ti, aquí tienes unos valores por defecto sensatos».
Ahora, una cosa que quiero que entiendas desde el principio: no estás obligado a usar los valores por defecto de Laravel. Puedes personalizarlo todo. Pero esto es lo que he aprendido: cuando te encuentras peleando con el framework, eso suele ser señal de que estás tomando decisiones de las que el framework intenta ahorrarte.
La estructura que tiene sentido
Laravel 13 se ha asentado en una estructura muy limpia. Esto es lo que hace realmente cada carpeta:
app/Http/Controllers/ Your API endpoint logic
app/Http/Requests/ Input validation rules
app/Http/Resources/ Response formatting
app/Http/Middleware/ Request/response interception
app/Http/Mappers/ DTO transformations
app/Http/DataObjects/ DTO definitions
app/Http/Integrations/ External API integrations
app/Http/Responses/ Unified Response Wrappers
app/Models/ Database models (like Bearer token)
app/Services/ Business logic with manager pattern
routes/api.php Where you define endpoints
tests/Feature/ Testing full request flows
database/migrations/ Database versioning
Cada carpeta tiene un propósito. Los controladores manejan HTTP. Los modelos manejan la base de datos. Las facades ofrecen interfaces limpias. Las pruebas verifican que todo funciona. Cuando alguien nuevo se une a tu equipo y mira esta estructura, piensa: «ah, esto ya lo he visto». Esa consistencia importa.