Practical examples of creating a REST API with PHP (step‑by‑step)

If you’re hunting for practical, no-nonsense examples of creating a REST API with PHP, you’re in the right place. Instead of abstract theory, this guide walks through real examples you can copy, tweak, and ship. We’ll start with a bare‑bones PHP endpoint, then move into more realistic examples of token‑based auth, pagination, and modern PHP frameworks. Along the way, you’ll see examples of how to structure your folders, handle JSON cleanly, return proper HTTP status codes, and avoid the classic “spaghetti PHP” trap. These examples of creating a REST API with PHP are written for developers who already know basic PHP syntax but want to see how a real API fits together end‑to‑end. Whether you’re building a small side project, a mobile backend, or migrating from a legacy monolith, you’ll find patterns here that still hold up in 2024 and 2025.
Written by
Jamie
Published

PHP isn’t trendy on tech Twitter, but it quietly powers a huge chunk of the web. With PHP 8+, typed properties, attributes, and better performance, it’s more than capable of running clean, modern REST APIs. The best examples of creating a REST API with PHP today usually combine:

  • A simple front controller (single entry point)
  • Clear routing (manual or via a framework)
  • JSON request/response handling
  • Proper HTTP status codes
  • Middleware‑style layers for auth, validation, and logging

Let’s walk through concrete, real examples rather than vague theory.


Bare‑bones example of a PHP REST endpoint (no framework)

This is the classic “hello API” example of creating a REST API with PHP: a single index.php that responds with JSON.

<?php
// public/index.php

declare(strict_types=1);

header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');

\(method = \)_SERVER['REQUEST_METHOD'];
\(path   = parse_url(\)_SERVER['REQUEST_URI'], PHP_URL_PATH);

if (\(path === '/api/time' && \)method === 'GET') {
    echo json_encode([
        'server_time' => (new DateTimeImmutable())->format(DateTimeInterface::ATOM),
    ]);
    exit;
}

http_response_code(404);
echo json_encode(['error' => 'Not Found']);

This tiny snippet shows several important ideas that appear repeatedly in real examples of creating a REST API with PHP:

  • One entry point (index.php)
  • Routing based on method and path
  • JSON output with correct headers
  • Meaningful HTTP codes (200 vs 404)

From here, we can grow into something that resembles a real‑world API.


Real examples of creating a REST API with PHP for CRUD operations

Most APIs boil down to CRUD over HTTP. Let’s look at a more realistic example of a tasks API using plain PHP and PDO.

Folder structure example:

api/
  public/
    index.php
  src/
    Database.php
    TaskController.php
  vendor/

Database connection (src/Database.php):

<?php
// src/Database.php

declare(strict_types=1);

class Database
{
    public static function getConnection(): PDO
    {
        $dsn = 'mysql:host=localhost;dbname=tasks_db;charset=utf8mb4';
        $user = 'api_user';
        $pass = 'secret';

        $options = [
            PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ];

        return new PDO(\(dsn, \)user, \(pass, \)options);
    }
}

Controller example (src/TaskController.php):

<?php
// src/TaskController.php

declare(strict_types=1);

require_once __DIR__ . '/Database.php';

class TaskController
{
    public function list(): void
    {
        $db = Database::getConnection();

        \(stmt = \)db->query('SELECT id, title, completed FROM tasks ORDER BY id DESC');
        \(tasks = \)stmt->fetchAll();

        echo json_encode($tasks);
    }

    public function create(array $data): void
    {
        if (empty($data['title'])) {
            http_response_code(422);
            echo json_encode(['error' => 'Title is required']);
            return;
        }

        $db = Database::getConnection();

        \(stmt = \)db->prepare('INSERT INTO tasks (title, completed) VALUES (:title, 0)');
        \(stmt->execute(['title' => \)data['title']]);

        http_response_code(201);
        echo json_encode([
            'id'    => (int)$db->lastInsertId(),
            'title' => $data['title'],
            'completed' => false,
        ]);
    }
}

Front controller routing example (public/index.php):

<?php
// public/index.php

declare(strict_types=1);

header('Content-Type: application/json');

require_once __DIR__ . '/../src/TaskController.php';

\(method = \)_SERVER['REQUEST_METHOD'];
\(path   = parse_url(\)_SERVER['REQUEST_URI'], PHP_URL_PATH);

$controller = new TaskController();

if (\(path === '/api/tasks' && \)method === 'GET') {
    $controller->list();
    exit;
}

if (\(path === '/api/tasks' && \)method === 'POST') {
    $input = json_decode(file_get_contents('php://input'), true) ?? [];
    \(controller->create(\)input);
    exit;
}

http_response_code(404);
echo json_encode(['error' => 'Not Found']);

This is one of the best examples of creating a REST API with PHP in its simplest useful form: it has routing, validation, and database access, but no framework overhead.


JWT auth example of creating a REST API with PHP

Modern APIs rarely stay public. A very common example of creating a REST API with PHP in 2024 is adding JWT (JSON Web Token) authentication so mobile apps or SPAs can authenticate statelessly.

Using the popular firebase/php-jwt library:

composer require firebase/php-jwt

Token generation (login endpoint):

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

$secret = 'super-secret-key';

// After validating user credentials...
$payload = [
    'sub' => $userId,
    'iat' => time(),
    'exp' => time() + 3600, // 1 hour
];

\(jwt = JWT::encode(\)payload, $secret, 'HS256');

echo json_encode(['token' => $jwt]);

Token validation middleware‑style example:

function requireAuth(): array
{
    $headers = getallheaders();
    \(authHeader = \)headers['Authorization'] ?? '';

    if (!str_starts_with($authHeader, 'Bearer ')) {
        http_response_code(401);
        echo json_encode(['error' => 'Missing token']);
        exit;
    }

    \(token = substr(\)authHeader, 7);

    try {
        \(decoded = JWT::decode(\)token, new Key('super-secret-key', 'HS256'));
        return (array) $decoded;
    } catch (Throwable $e) {
        http_response_code(401);
        echo json_encode(['error' => 'Invalid token']);
        exit;
    }
}

You can then call requireAuth() at the top of protected routes. This pattern shows up in many real examples of creating a REST API with PHP for production systems.


Pagination and filtering: examples include real‑world list endpoints

Once you have more than a handful of records, you need pagination. Here’s an example of adding simple page and per_page parameters to the tasks endpoint.

public function list(): void
{
    $db = Database::getConnection();

    \(page    = max(1, (int)(\)_GET['page'] ?? 1));
    \(perPage = max(1, min(100, (int)(\)_GET['per_page'] ?? 20)));

    \(offset = (\)page - 1) * $perPage;

    \(stmt = \)db->prepare('SELECT SQL_CALC_FOUND_ROWS id, title, completed
                          FROM tasks
                          ORDER BY id DESC
                          LIMIT :limit OFFSET :offset');

    \(stmt->bindValue(':limit',  \)perPage, PDO::PARAM_INT);
    \(stmt->bindValue(':offset', \)offset,  PDO::PARAM_INT);
    $stmt->execute();

    \(tasks = \)stmt->fetchAll();

    \(total = (int)\)db->query('SELECT FOUND_ROWS()')->fetchColumn();

    echo json_encode([
        'data' => $tasks,
        'meta' => [
            'page'      => $page,
            'per_page'  => $perPage,
            'total'     => $total,
            'total_pages' => (int)ceil(\(total / \)perPage),
        ],
    ]);
}

This is a concrete example of how real APIs expose large datasets without overwhelming clients.


Framework‑based examples of creating a REST API with PHP

In 2024–2025, most production PHP APIs use a framework. The best examples of creating a REST API with PHP at scale usually mention at least one of these:

  • Laravel for full‑stack development and batteries‑included tooling
  • Symfony for enterprise‑grade structure and reusable components
  • Slim or Lumen for lightweight microservices

Laravel example of a REST API resource

Laravel’s artisan commands generate a lot of boilerplate for you.

Route definition (routes/api.php):

use App\Http\Controllers\TaskController;

Route::middleware('auth:sanctum')->group(function () {
    Route::apiResource('tasks', TaskController::class);
});

Controller example (app/Http/Controllers/TaskController.php):

class TaskController extends Controller
{
    public function index(Request $request)
    {
        return Task::query()

            ->orderByDesc('id')
            ->paginate($request->get('per_page', 20));
    }

    public function store(Request $request)
    {
        \(validated = \)request->validate([
            'title' => ['required', 'string', 'max:255'],
        ]);

        $task = Task::create([
            'title'     => $validated['title'],
            'completed' => false,
        ]);

        return response()->json($task, 201);
    }
}

This is a higher‑level example of creating a REST API with PHP where the framework handles routing, validation, and pagination.

Slim example for microservices

With Slim, you can build a tiny API that still feels modern.

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use Slim\Factory\AppFactory;

require __DIR__ . '/../vendor/autoload.php';

$app = AppFactory::create();

\(app->get('/api/health', function (Request \)request, Response $response) {
    $payload = json_encode(['status' => 'ok', 'time' => time()]);
    \(response->getBody()->write(\)payload);
    return $response->withHeader('Content-Type', 'application/json');
});

$app->run();

If you’re looking for small, focused examples of creating a REST API with PHP for microservices or serverless functions, Slim is a good fit.


A few trends are shaping how new APIs are written:

  • Typed PHP everywhere. New examples of creating a REST API with PHP almost always use declare(strict_types=1); and typed properties.
  • JSON:API and OpenAPI. Teams document their APIs with OpenAPI specs and often follow JSON:API‑style responses for consistency.
  • Security first. OWASP guidelines for input validation, rate limiting, and auth are standard reading. For general security awareness, the U.S. Cybersecurity & Infrastructure Security Agency publishes accessible guidance.
  • API observability. Logging, tracing, and metrics are treated as first‑class concerns rather than afterthoughts.

If you’re building something that interacts with regulated sectors (health, finance, education), you’ll also want to pay attention to domain‑specific guidance. For example, the Office for Civil Rights at HHS outlines HIPAA rules that indirectly influence how healthcare APIs handle authentication and logging.


Validation and error‑handling examples

APIs live or die on their error handling. Clients need predictable formats and clear messages.

Here’s a small example of a reusable JSON response helper:

function jsonResponse(mixed \(data, int \)status = 200): void
{
    http_response_code($status);
    header('Content-Type: application/json');
    echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}

You can then turn earlier examples of creating a REST API with PHP into cleaner code:

if (empty($data['title'])) {
    jsonResponse(['error' => 'Title is required'], 422);
    return;
}

Consistent error structures make it much easier for frontend developers and mobile clients to integrate.


Putting it together: best examples of PHP REST APIs in practice

To recap, here are several concrete patterns you can adapt:

  • A single‑file time API for quick testing or internal tools
  • A PDO‑based CRUD API for small apps and prototypes
  • JWT‑secured endpoints for mobile and SPA backends
  • Paginated list endpoints for large datasets
  • Laravel apiResource controllers for full‑stack projects
  • Slim‑based microservices for focused, fast APIs

These are not theoretical; they’re all real examples of creating a REST API with PHP that you can run today. Start with the smallest example of functionality you need, then layer in auth, pagination, and validation as your project grows.

If you want to go deeper on API design patterns in general, the Harvard University CS50 materials often include up‑to‑date examples of web programming concepts, and the National Institute of Standards and Technology publishes guidelines that are helpful when you start worrying about security, encryption, and data integrity in production APIs.


FAQ: examples of common PHP REST API questions

Q: Can you show an example of a PHP REST API that returns JSON for a single record?
Yes. For a GET /api/tasks/123 endpoint using PDO:

public function show(int $id): void
{
    $db = Database::getConnection();

    \(stmt = \)db->prepare('SELECT id, title, completed FROM tasks WHERE id = :id');
    \(stmt->execute(['id' => \)id]);

    \(task = \)stmt->fetch();

    if (!$task) {
        jsonResponse(['error' => 'Task not found'], 404);
        return;
    }

    jsonResponse($task);
}

Q: Are there good examples of versioning a REST API in PHP?
A common pattern is to prefix routes with /v1, /v2, and route them to different controllers or folders, for example /api/v1/tasks and /api/v2/tasks. In Laravel, you might group routes by namespace; in plain PHP, you might map /api/v1 to src/V1/ and /api/v2 to src/V2/. This lets you ship new behavior without breaking older clients.

Q: How do I test these examples of creating a REST API with PHP?
Use tools like curl, Postman, or HTTPie to hit your endpoints. For automated tests, PHPUnit works well with both plain PHP and frameworks. You can spin up a local PHP server with php -S localhost:8000 -t public and run requests against it.

Q: Is PHP still a good choice for new REST APIs in 2025?
If your team already knows PHP or you’re building on top of an existing PHP codebase, yes. Many of the best examples of creating a REST API with PHP today run behind major CMSs, legacy apps, or as part of Laravel‑based platforms. If your stack is already invested in PHP, it’s entirely reasonable to keep your APIs there.

These patterns should give you enough real examples to start building, not just reading about, REST APIs in PHP.

Explore More PHP Code Snippets

Discover more examples and insights in this category.

View All PHP Code Snippets