Modern applications often need to communicate with mobile applications or other services. This is where APIs come in. Today, we are going to dig deeper into APIs and look at how they can be integrated with Laravel.
But before we go into Laravel, let’s first review REST APIs or Representational State Transfer APIs, and how they allow different applications to communicate with each other.
What is a REST API?
A REST API or Representational State Transfer API is an architectural style for creating web services and allows different applications to exchange data with each other.
REST APIs typically use standard HTTP methods to perform different operations on resources:
- GET – Retrieve data
- POST – Create new data
- PUT – Replace or update existing data
- PATCH – Partially update existing data
- DELETE – Remove data
REST APIs are generally stateless, meaning each request contains the information needed to process it. This allows different systems to communicate regardless of their underlying technology.
Integration in Laravel
Laravel provides two packages for handling your API authentication: Laravel Sanctum and Laravel Passport. The main difference between these two is the way authentication is handled, but more on that later. For our examples, we will be using Laravel Sanctum throughout the post.
It can easily be installed using the following command:
php artisan install:api
This gives your application the tools needed to authenticate API requests and protect routes using Sanctum's authentication middleware.
Routes and Middleware
When you installed Sanctum, Laravel automatically created a routes/api.php file where we can define our API routes.
We now also have our first API endpoint. Before the request is passed to your application, it passes through middleware. Small, single purpose filters that can inspect, modify or reject requests.
By default Laravel maintains two separate middleware groups:
- web – Applied to routes in routes/web.php. Includes session handling, CSRF protection, cookie encryption and so on.
- api – Applied to routes in routes/api.php. Skips sessions and CSRF by default, keeping things stateless. When authentication requires a stateful approach this can be enabled in bootstrap/app.php for the api group.
Any custom built middleware can be appended to one of these groups using the withMiddleware method in the bootstrap/app.php file.
The desired middleware can then be added to your route or route group, as usual.
In the above example, the Sanctum authentication middleware was applied to the route.
API Responses
Typically REST APIs use the JSON format. As seen above, for a basic exchange Laravel’s default JsonResponse does the trick.
Our index method in our controller would look something like this:
When you need more control over the response shape, a custom Resource can be made using the following Artisan command:
php artisan make:resource MovieResource
In the created resource, you can then alter the returned data to your needs.
The controller then would look something like this:
Pagination
Returning Movie::all() works fine for a handful of records. However, in a production environment you would rarely do this. Here’s where pagination comes in. Pagination splits the results into numbered pages, allowing you to send the results page by page.
We can implement this in the following way:
The response would then return a data array, with the movies for the page, and metadata like current_page, last_page, first_page_url, links (with URLs for the next and previous pages), etc.
Forcing a JSON Response
Often Laravel returns a redirect or HTML response on API routes. For example, if the response is an error. For this case you can easily force a JSON response on all API routes by adding a custom middleware.
After that, just register the created middleware to your bootstrap/app.php:
By using prepend, this middleware will be run before all the other middleware in the group. Now all Accept headers are changed to JSON responses. Behind the scenes, Laravel does the rest. In the rare case an exception should bypass the middleware, our exception handler catches it.
Authentication
Now that we discussed the basics of REST APIs and their data handling, we can take a closer look at authentication.
Three common ways of authenticating with APIs:
- Session based authentication - Using this method the server stores a session ID and the browser sends it back through a cookie on each request. This is the only non-stateless method we are going to discuss. It works well with web apps that are hosted on the same domain as the backend.
- Token based authentication - In this stateless method authentication gets done by verifying the tokens that are delivered with every request.
- OAuth2 based authentication – With this approach, a separate authorization server authenticates the user and issues short lived access tokens. The resource server then validates them without knowing the user’s password.
In Laravel the Sanctum package can handle session and token based authentication, while Passport can handle OAuth2 authentication. In general, Sanctum does the trick, but if you don’t control both sides of the API connection and OAuth2 authentication is required then Laravel Passport is the go-to option.
Timeouts and failure handling
When working with APIs, failures are inevitable. An external API might be unavailable, take too long to respond, or return an error. Laravel’s HTTP client can handle these failures gracefully:
$response = Http::timeout(5)->get('https://example.com/api/movies');
In the above example the application will wait 5 seconds for a response, if no response was received after that a timeout exception will be thrown.
It’s also possible to use retries for temporary failures:
$response = Http::retry(3, 100)-> get('https://example.com/api/movies');
This tells the application to retry up to 3 times, leaving 100ms between attempts.
Laravel also provides a centralized way to customize exception handling in bootstrap/app.php. For example, we can customize how validation errors are returned:
This keeps the API’s error format consistent instead of having to manually construct the same response throughout the application.
Security and Rate Limiting
Laravel Sanctum and Passport also provide authorization scopes, by which you can determine whether a user is allowed to perform a certain action.
$user->createToken('token-name', ['movies:read']);
In the above example we created a token, which only has read access to our movies.
Other options could be movies:update, movies:create or movies:delete.
This can then later be checked using tokenCan('movies:read') method.
For rate limiting we can use the familiar throttle middleware. By default 60 requests per minute are allowed. This limit can be reduced to protect against abuse, minimize server load and secure your endpoints.
For example:
Conclusion
APIs are an important part of application development, and there is far more to learn then I can sammurize in this post. However, in my experience, Sanctum and Passport make working with APIs a elegant and manageable experience.