Las APIs REST son el lenguaje común entre aplicaciones modernas. Construir una desde cero en PHP puro —sin frameworks— te enseña exactamente cómo funciona HTTP, JSON y la arquitectura cliente-servidor. Esta guía crea una API funcional paso a paso.

¿Qué es una API REST?

REST (Representational State Transfer) es un estilo arquitectónico para construir servicios web usando HTTP. Los recursos se identifican por URLs y las operaciones se hacen con los métodos HTTP estándar:

Método HTTP Operación CRUD Ejemplo
GET Read GET /api/articulos → lista todos
POST Create POST /api/articulos → crea uno nuevo
PUT/PATCH Update PUT /api/articulos/5 → actualiza el #5
DELETE Delete DELETE /api/articulos/5 → elimina el #5

Estructura del proyecto

api/
├── index.php       ← router principal
├── config.php      ← conexión a la base de datos
├── helpers.php     ← funciones utilitarias
└── .htaccess       ← reescritura de URLs
# .htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]

El router: index.php

 handle_articulos($pdo, $metodo, $id, $body),
    default => responder(404, ['error' => 'Recurso no encontrado'])
};

El controlador: CRUD de artículos

prepare("SELECT * FROM articulos WHERE id = ?");
                $stmt->execute([$id]);
                $articulo = $stmt->fetch(PDO::FETCH_ASSOC);
                $articulo ? responder(200, $articulo) : responder(404, ['error' => 'No encontrado']);
            } else {
                // GET /articulos
                $stmt = $pdo->query("SELECT id, titulo, slug, categoria_slug, created_at FROM articulos ORDER BY created_at DESC");
                responder(200, $stmt->fetchAll(PDO::FETCH_ASSOC));
            }
            break;

        case 'POST':
            // Validación básica
            if (empty($body['titulo']) || empty($body['contenido'])) {
                responder(422, ['error' => 'titulo y contenido son requeridos']);
                return;
            }
            $stmt = $pdo->prepare(
                "INSERT INTO articulos (titulo, slug, contenido, categoria_slug) VALUES (?, ?, ?, ?)"
            );
            $slug = strtolower(str_replace(' ', '-', $body['titulo']));
            $stmt->execute([$body['titulo'], $slug, $body['contenido'], $body['categoria_slug'] ?? 'tecnologia']);
            responder(201, ['id' => $pdo->lastInsertId(), 'slug' => $slug]);
            break;

        case 'DELETE':
            if (!$id) { responder(400, ['error' => 'ID requerido']); return; }
            $stmt = $pdo->prepare("DELETE FROM articulos WHERE id = ?");
            $stmt->execute([$id]);
            responder(200, ['eliminado' => $stmt->rowCount() > 0]);
            break;

        default:
            responder(405, ['error' => 'Método no permitido']);
    }
}

function responder(int $codigo, array $datos): void {
    http_response_code($codigo);
    echo json_encode($datos, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
    exit();
}

Probar la API con curl

# Listar artículos
curl http://localhost/api/articulos

# Obtener uno específico
curl http://localhost/api/articulos/1

# Crear un artículo
curl -X POST http://localhost/api/articulos \
  -H "Content-Type: application/json" \
  -d '{"titulo":"Mi primer artículo","contenido":"Contenido aquí","categoria_slug":"redes"}'

# Eliminar
curl -X DELETE http://localhost/api/articulos/5

"Una buena API es un contrato entre sistemas. Rota ese contrato sin avisar y rompes a todos los que dependen de ti."