Codeskill

Learn to code, step by step

Mini project: small JSON API

This mini project adds a small JSON API alongside your CRUD app – or as a separate endpoint group. Same auth ideas, different response format. Useful for mobile clients, JavaScript front ends, or webhooks.

API routes

GET    /api/notes          list current user's notes (JSON)
GET    /api/notes/{id}      single note
POST   /api/notes          create (JSON body)
PUT    /api/notes/{id}     update
DELETE /api/notes/{id}     delete

JSON responses

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

// Success:
jsonResponse(['notes' => $notes]);

// Error:
jsonResponse(['error' => 'Title is required'], 422);

Reading JSON input

$raw = file_get_contents('php://input');
$input = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);

$title = trim($input['title'] ?? '');

Auth for APIs

Browser forms use session cookies. APIs often use a token in the Authorization header. For learning, session cookies on same-origin fetch calls are fine. For a token approach:

$header = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
if (preg_match('/Bearers+(S+)/', $header, $m)) {
    $token = $m[1];
    // Look up user by api_token hash in database
}

Consistent error shape

jsonResponse([
    'error' => 'Validation failed',
    'fields' => ['title' => 'Required'],
], 422);

CORS (if needed)

If a JavaScript app on another domain calls your API, send CORS headers deliberately – do not use * with credentials. For same-site apps you may not need CORS at all.

Testing with curl

curl -X POST http://localhost:8080/api/notes 
  -H 'Content-Type: application/json' 
  -H 'Cookie: PHPSESSID=your_session_id' 
  -d '{"title":"Test","body":"Hello"}'

You now have HTML pages for humans and JSON for machines, sharing the same repositories and auth rules. That split is how most modern PHP apps are structured – even before you reach for a full framework.

PreviousMini project: CRUD app with login