Building JSON APIs
Slim is an especially popular choice for building JSON REST APIs — it stays out of the way, gives you routing and middleware, and leaves the response format entirely up to you. Building a JSON API in Slim really comes down to two things: encoding data as JSON and writing it to the response body, and setting the right Content-Type header so clients know how to parse it.
A Reusable JSON Response Helper
Since almost every route in an API needs to do the same two steps — json_encode() the data and set the header — it's worth writing a small helper function once instead of repeating both lines in every route handler.
<?php
function jsonResponse($response, $data, int $status = 200) {
$response->getBody()->write(json_encode($data));
return $response
->withHeader('Content-Type', 'application/json')
->withStatus($status);
}
Every route below simply calls jsonResponse($response, $data) instead of repeating the encode-and-header dance by hand.
Worked Example: A Books Resource
A minimal REST resource for /api/books needs at least a way to list books and a way to create one. Here both routes are grouped together, as covered on the Route Groups page.
<?php
$app->group('/api/books', function ($group) {
// GET /api/books - return every book as a JSON array
$group->get('', function ($request, $response) {
$books = [
['id' => 1, 'title' => 'PHP Basics'],
['id' => 2, 'title' => 'Learning Slim'],
];
return jsonResponse($response, $books);
});
// POST /api/books - create a book from the JSON request body
$group->post('', function ($request, $response) {
$input = json_decode((string)$request->getBody(), true);
if (empty($input['title'])) {
return jsonResponse($response, ['error' => 'title is required'], 400);
}
$created = ['id' => 3, 'title' => $input['title']];
// 201 Created, along with the resource that was just created
return jsonResponse($response, $created, 201);
});
});
Using the Right HTTP Status Code
A JSON API is only as useful as its status codes are accurate. Clients (and other developers) rely on the status code — not just the JSON body — to know what happened.
| Status | Meaning | When to use it |
|---|---|---|
| 200 OK | Success | A GET, PUT, or DELETE completed normally |
| 201 Created | Resource created | A POST successfully created a new resource — return the new resource too |
| 400 Bad Request | Invalid input | The request body is missing required fields or is malformed |
| 404 Not Found | No such resource | A GET/PUT/DELETE targets an id that doesn't exist |
<?php
// Example: returning 404 when a specific book id isn't found
$group->get('/{id}', function ($request, $response, $args) {
$book = null; // pretend a lookup happened and found nothing
if ($book === null) {
return jsonResponse($response, ['error' => 'Book not found'], 404);
}
return jsonResponse($response, $book);
});