PHP · REST API · JSON · PDO

Crear una API REST con PHP: JSON, PDO y autenticación

Una API REST con PHP puede recibir solicitudes HTTP, ejecutar lógica de negocio, consultar MySQL mediante PDO y devolver respuestas JSON a aplicaciones web, móviles u otros sistemas. Para construirla correctamente necesitas comprender rutas, métodos HTTP, códigos de estado, validación, autenticación, autorización, errores, CORS y separación de responsabilidades.

GET · POST · PATCH · DELETE JSON · PDO · MySQL Auth · CORS · Seguridad
Respuesta rápida

¿Cómo crear una API REST con PHP?

Primero debes definir recursos y endpoints. Por ejemplo: /api/productos y /api/productos/15.

Después debes interpretar el método HTTP utilizado: GET para consultar, POST para crear, PATCH o PUT para modificar y DELETE para eliminar, según el diseño de tu API.

PHP procesa la solicitud, valida los datos, ejecuta la lógica necesaria, consulta MySQL mediante PDO y devuelve una respuesta normalmente codificada como JSON.

Una API lista para producción también necesita autenticación, autorización, manejo de errores, códigos HTTP, CORS cuando corresponda, límites de acceso y seguridad.

Publicidad
Arquitectura básica

Una API conecta clientes, lógica de aplicación y datos

01

Cliente

Web, app móvil u otro sistema envía una solicitud.

02

Ruta

La API identifica qué endpoint se está solicitando.

03

Método HTTP

GET, POST, PATCH, PUT o DELETE.

04

Lógica

Se validan datos y reglas.

05

Datos

PDO puede consultar MySQL.

06

Respuesta

HTTP status + JSON.

Publicidad
Antes de programar

Una API permite que diferentes aplicaciones se comuniquen mediante un contrato

Imagina que tienes un sistema de productos.

La información está almacenada en MySQL, pero quieres mostrarla dentro de:

01

Una aplicación web.

02

Una aplicación móvil.

03

Un dashboard interno.

04

Un sistema externo.

Esos clientes no necesitan conectarse directamente a la base de datos.

Pueden comunicarse con una API PHP.

La API se convierte en una frontera

Decide qué información puede consultarse, qué operaciones están permitidas y bajo qué condiciones.

Nunca expongas MySQL directamente a una aplicación cliente como sustituto de una API.

La capa backend debe controlar autenticación, permisos, reglas y acceso a los datos.

REST

REST organiza la API alrededor de recursos y operaciones HTTP

Supongamos que la aplicación administra productos.

En lugar de crear URLs como:

Evitar Ruta
/obtener-productos.php
/crear-producto.php
/borrar-producto.php

podemos representar el recurso mediante:

Recurso REST
/api/productos
/api/productos/15

Y utilizar el método HTTP para expresar la operación.

Publicidad
Métodos HTTP

GET, POST, PUT, PATCH y DELETE expresan diferentes intenciones

Método Uso habitual Ejemplo
GET Consultar recursos GET /productos
POST Crear un recurso POST /productos
PUT Sustituir o actualizar un recurso según el contrato de la API PUT /productos/15
PATCH Modificar parcialmente un recurso PATCH /productos/15
DELETE Eliminar un recurso DELETE /productos/15
El significado exacto debe quedar documentado en el contrato de tu API.

Especialmente PUT y PATCH pueden implementarse de manera diferente según el diseño del servicio.

PHP

PHP puede identificar el método de la solicitud

Método HTTP PHP
<?php

$metodo = $_SERVER['REQUEST_METHOD'];

switch ($metodo) {

    case 'GET':
        // Consultar.
        break;

    case 'POST':
        // Crear.
        break;

    case 'PATCH':
        // Modificar.
        break;

    case 'DELETE':
        // Eliminar.
        break;

    default:
        http_response_code(405);
}

En una aplicación mayor, esta lógica normalmente termina dentro de un router o framework.

Pero comprenderla manualmente primero ayuda a entender qué está automatizando la herramienta.

Respuestas

Una API PHP puede devolver JSON en lugar de una página HTML

JSON PHP
<?php

header(
    'Content-Type: application/json; charset=utf-8'
);

$respuesta = [
    'ok' => true,
    'producto' => [
        'id' => 15,
        'nombre' => 'Teclado',
        'precio' => 19990
    ]
];

echo json_encode(
    $respuesta,
    JSON_UNESCAPED_UNICODE
);

El cliente recibe datos estructurados y decide cómo presentarlos.

Backend y frontend quedan desacoplados

El mismo endpoint puede ser utilizado por una interfaz web, una app móvil o un sistema externo.

Body JSON

Una solicitud POST o PATCH puede enviar información en formato JSON

El cuerpo de una solicitud podría contener:

Request body JSON
{
    "nombre": "Monitor",
    "precio": 129990
}

PHP puede leer el body mediante php://input.

Leer JSON PHP
<?php

$contenido = file_get_contents(
    'php://input'
);

$datos = json_decode(
    $contenido,
    true
);

if (!is_array($datos)) {

    http_response_code(400);

    echo json_encode([
        'error' => 'JSON inválido'
    ]);

    exit;
}

Decodificar JSON no significa que los datos sean válidos

Todavía necesitas comprobar campos, tipos, reglas y permisos.

Publicidad
GET

Crear un endpoint para listar productos

Supongamos que ya tenemos una conexión PDO.

GET /productos PHP + PDO
<?php

$sql = "
    SELECT
        id,
        nombre,
        precio
    FROM productos
    ORDER BY id DESC
    LIMIT 20
";

$stmt = $pdo->query($sql);

$productos = $stmt->fetchAll(
    PDO::FETCH_ASSOC
);

http_response_code(200);

echo json_encode([
    'data' => $productos
]);

Hemos separado la representación del recurso del HTML.

La API entrega los datos y el cliente decide cómo utilizarlos.

GET individual

Consultar un recurso por identificador

GET /productos/15 PDO
<?php

$sql = "
    SELECT
        id,
        nombre,
        precio
    FROM productos
    WHERE id = :id
    LIMIT 1
";

$stmt = $pdo->prepare($sql);

$stmt->execute([
    'id' => $id
]);

$producto = $stmt->fetch(
    PDO::FETCH_ASSOC
);

if (!$producto) {

    http_response_code(404);

    echo json_encode([
        'error' => 'Producto no encontrado'
    ]);

    exit;
}

echo json_encode([
    'data' => $producto
]);

Aquí 404 comunica información importante

El cliente no recibe solamente un texto: también recibe un código HTTP que describe el resultado.

POST

Crear un recurso requiere validar antes de insertar

Supongamos que recibimos:

Request JSON
{
    "nombre": "Teclado mecánico",
    "precio": 39990
}

Primero comprobamos las reglas.

Validación PHP
<?php

$nombre = trim(
    (string) ($datos['nombre'] ?? '')
);

$precio = $datos['precio'] ?? null;

$errores = [];

if ($nombre === '') {
    $errores['nombre'] = 'El nombre es obligatorio.';
}

if (
    !is_numeric($precio)
    || (float) $precio < 0
) {
    $errores['precio'] = 'El precio es inválido.';
}

if ($errores !== []) {

    http_response_code(422);

    echo json_encode([
        'error' => 'Datos inválidos',
        'campos' => $errores
    ]);

    exit;
}

Después insertamos mediante PDO

INSERT PDO
<?php

$sql = "
    INSERT INTO productos (
        nombre,
        precio
    )
    VALUES (
        :nombre,
        :precio
    )
";

$stmt = $pdo->prepare($sql);

$stmt->execute([
    'nombre' => $nombre,
    'precio' => (float) $precio
]);

$id = (int) $pdo->lastInsertId();

http_response_code(201);

echo json_encode([
    'data' => [
        'id' => $id,
        'nombre' => $nombre,
        'precio' => (float) $precio
    ]
]);

201 comunica que se creó un recurso

Una API bien diseñada utiliza también HTTP para comunicar resultados, no solamente una propiedad ok.

PDO

Si las consultas preparadas todavía no están claras, profundiza primero en PHP con MySQL

CRUD, relaciones, transacciones y seguridad SQL.

PHP con MySQL →
Publicidad
PATCH

PATCH puede utilizarse para modificar solamente algunos campos

Supongamos que queremos cambiar únicamente el precio.

PATCH /productos/15 JSON
{
    "precio": 34990
}

La aplicación puede permitir modificaciones parciales.

UPDATE PDO
<?php

$precio = $datos['precio'] ?? null;

if (
    !is_numeric($precio)
    || (float) $precio < 0
) {

    http_response_code(422);

    echo json_encode([
        'error' => 'Precio inválido'
    ]);

    exit;
}

$sql = "
    UPDATE productos
    SET precio = :precio
    WHERE id = :id
";

$stmt = $pdo->prepare($sql);

$stmt->execute([
    'precio' => (float) $precio,
    'id' => $id
]);

echo json_encode([
    'data' => [
        'id' => $id,
        'precio' => (float) $precio
    ]
]);

Una API real debe decidir qué campos pueden modificarse

No utilices automáticamente cualquier clave enviada por el cliente para construir SQL dinámico.

DELETE

Eliminar un recurso también necesita autorización

DELETE /productos/15 PDO
<?php

$sql = "
    DELETE FROM productos
    WHERE id = :id
";

$stmt = $pdo->prepare($sql);

$stmt->execute([
    'id' => $id
]);

if ($stmt->rowCount() === 0) {

    http_response_code(404);

    echo json_encode([
        'error' => 'Producto no encontrado'
    ]);

    exit;
}

http_response_code(204);

204 No Content puede utilizarse cuando la operación fue correcta y no necesitas devolver un body.

Saber el id del producto no debería ser suficiente para poder eliminarlo.

Debes comprobar quién realiza la solicitud y si posee autorización para ejecutar esa operación.

Códigos HTTP

Los códigos de estado forman parte del contrato de una API

Código Significado habitual Ejemplo
200 Operación correcta GET exitoso
201 Recurso creado POST exitoso
204 Éxito sin contenido DELETE exitoso
400 Solicitud incorrecta JSON inválido
401 Falta autenticación válida Token ausente o inválido
403 Acceso no autorizado Usuario sin permiso
404 Recurso no encontrado Producto inexistente
405 Método no permitido POST donde solo se admite GET
422 Datos procesables pero inválidos Campos que no cumplen reglas
500 Error interno Fallo inesperado del servidor
Validación

Una API debe diferenciar entre datos técnicamente válidos y datos válidos para el negocio

Tipo

¿El precio realmente es numérico?

Rango

¿Puede ser negativo?

Longitud

¿Un nombre puede contener miles de caracteres?

Unicidad

¿Puede repetirse un email o código?

Regla de negocio

¿Puede cancelarse un pedido que ya fue despachado?

La base de datos también debería proteger determinadas reglas.

UNIQUE, NOT NULL, claves foráneas y otras restricciones complementan la validación de PHP.

Publicidad
Reutilización

Evita repetir la construcción de respuestas JSON en cada endpoint

Podemos crear una función sencilla:

Respuesta JSON PHP
<?php

function responderJson(
    mixed $datos,
    int $status = 200
): never {

    http_response_code($status);

    header(
        'Content-Type: application/json; charset=utf-8'
    );

    echo json_encode(
        $datos,
        JSON_UNESCAPED_UNICODE
    );

    exit;
}

Después:

Uso PHP
responderJson(
    [
        'data' => $productos
    ],
    200
);

En proyectos mayores, este concepto puede evolucionar hacia objetos de respuesta o abstracciones proporcionadas por frameworks.

POO

Separar controlador, servicio y acceso a datos evita una API formada por archivos gigantes

Un endpoint no debería convertirse en una mezcla de:

01

Routing.

02

Validación.

03

SQL.

04

Reglas de negocio.

05

Autenticación.

06

JSON.

Podemos empezar separando responsabilidades.

Estructura conceptual API
Request
   ↓
Router
   ↓
Controller
   ↓
Service
   ↓
Repository
   ↓
PDO / MySQL

Controller

Recibe información relacionada con HTTP y construye la respuesta.

Service

Ejecuta reglas del negocio.

Repository

Encapsula operaciones relacionadas con persistencia.

Arquitectura PHP

Las clases empiezan a tener sentido cuando necesitas separar responsabilidades

Interfaces, composición e inyección de dependencias.

POO en PHP →
Repository

El controlador no necesita contener directamente todas las consultas SQL

ProductoRepository PHP
<?php

final class ProductoRepository
{
    public function __construct(
        private PDO $pdo
    ) {}

    public function buscar(
        int $id
    ): ?array {

        $sql = "
            SELECT
                id,
                nombre,
                precio
            FROM productos
            WHERE id = :id
            LIMIT 1
        ";

        $stmt = $this->pdo->prepare($sql);

        $stmt->execute([
            'id' => $id
        ]);

        $producto = $stmt->fetch(
            PDO::FETCH_ASSOC
        );

        return $producto ?: null;
    }
}

El resto del sistema puede pedir un producto sin conocer los detalles SQL de esa operación.

Composer

Composer permite organizar las clases de la API mediante autoloading

Podemos utilizar PSR-4 para relacionar namespaces con el directorio src/.

composer.json PSR-4
{
    "autoload": {
        "psr-4": {
            "Ciborg\\Api\\": "src/"
        }
    }
}

Y organizar:

API Estructura
api/
│
├── composer.json
├── composer.lock
├── public/
│   └── index.php
│
├── src/
│   ├── Controllers/
│   ├── Services/
│   ├── Repositories/
│   ├── Http/
│   └── Database/
│
└── vendor/
Dependencias

Composer ayuda a convertir la API en un proyecto PHP organizado

Autoload, namespaces, paquetes y dependencias.

Aprender Composer →
Publicidad
Autenticación

Una API privada necesita saber quién realiza la solicitud

Algunos endpoints pueden ser públicos.

Otros necesitan una identidad autenticada.

Authorization header

Un cliente puede enviar una credencial dentro del header:

Header HTTP
Authorization: Bearer <token>

El servidor debe validar ese token según el sistema de autenticación elegido.

No inventes un sistema criptográfico propio para tokens o contraseñas.

Utiliza mecanismos conocidos, bibliotecas mantenidas y prácticas adecuadas para el tipo de autenticación que implementes.

Autorización

Estar autenticado no significa poder hacer cualquier cosa

Supongamos que un usuario puede consultar sus pedidos.

No debería poder cambiar el identificador de la URL y consultar los pedidos de otra persona.

Debes comprobar propiedad o permisos

La lógica debería responder preguntas como:

01

¿Quién realiza la solicitud?

02

¿Qué recurso quiere utilizar?

03

¿Tiene permiso para verlo?

04

¿Puede modificarlo?

05

¿Puede eliminarlo?

CORS

CORS controla determinados accesos realizados desde navegadores entre orígenes diferentes

Si tu frontend está en un dominio y tu API en otro, el navegador aplica políticas de origen.

El servidor puede responder con headers CORS adecuados cuando quiere permitir determinadas solicitudes.

CORS Ejemplo
<?php

header(
    'Access-Control-Allow-Origin: https://app.ejemplo.cl'
);

header(
    'Access-Control-Allow-Methods: GET, POST, PATCH, DELETE, OPTIONS'
);

header(
    'Access-Control-Allow-Headers: Content-Type, Authorization'
);
CORS no es un sistema de autenticación.

Permitir un origen no significa que ese cliente tenga autorización para acceder a datos privados.

Errores

Una API debe devolver errores consistentes sin revelar detalles internos

El cliente necesita comprender qué ocurrió.

Pero no necesita recibir:

01

Credenciales de base de datos.

02

Rutas internas del servidor.

03

Stack traces completos.

04

SQL sensible.

Respuesta pública

Error JSON
{
    "error": "internal_error",
    "message": "No fue posible completar la operación."
}

El detalle técnico puede registrarse internamente para debugging.

Publicidad
Paginación

Una colección grande no debería devolverse completa en cada solicitud

En lugar de:

Evitar API
GET /productos

devolviendo cien mil registros, puedes admitir parámetros:

Paginación HTTP
GET /productos?page=2&per_page=20

La respuesta también puede incluir metadata:

Response JSON
{
    "data": [],
    "meta": {
        "page": 2,
        "per_page": 20,
        "total": 358
    }
}
Filtros

Query parameters pueden permitir búsquedas y filtros

Filtros URL
GET /productos?categoria=tecnologia
GET /productos?activo=1
GET /productos?buscar=teclado
No conviertas automáticamente nombres de parámetros en columnas SQL.

Define explícitamente qué filtros acepta la API y cómo se traducen a consultas seguras.

Versionado

Una API pública puede necesitar evolucionar sin romper clientes existentes

Si otras aplicaciones dependen de tu respuesta, cambiar su estructura puede romperlas.

Una estrategia posible es incorporar versión en la ruta:

Versiones API
/api/v1/productos
/api/v2/productos

El versionado no debería añadirse simplemente por decoración.

Es útil cuando necesitas administrar cambios incompatibles dentro del contrato.

Protección

Una API pública debería considerar límites de uso

Un cliente puede realizar miles de solicitudes por accidente o de manera abusiva.

Rate limiting

Permite restringir cuántas solicitudes puede realizar una identidad o cliente dentro de un período.

Límites por plan

En un SaaS, también puedes asociar consumo con planes o créditos.

Este tipo de control pertenece a la arquitectura del servicio, no solamente al routing.

Testing

Prueba la API como cliente, no solamente ejecutando funciones PHP

Una API debe comprobarse a nivel HTTP.

Caso exitoso

¿POST crea realmente un recurso y devuelve 201?

Datos inválidos

¿Devuelve un error coherente?

Usuario sin permisos

¿La API bloquea correctamente la operación?

Recurso inexistente

¿Devuelve 404?

Base de datos caída

¿Evita filtrar detalles sensibles?

Publicidad
Ruta recomendada

En qué orden aprender a crear APIs REST con PHP

1

PHP

Funciones, arrays, tipos y errores.

2

HTTP

Request, response, headers y status.

3

JSON

Serialización y parsing.

4

REST

Recursos y métodos HTTP.

5

PDO

Persistencia y consultas seguras.

6

Validación

Protege reglas y datos.

7

POO

Separa controller, service y repository.

8

Autenticación

Identifica clientes y usuarios.

9

Autorización

Controla operaciones permitidas.

10

Producción

CORS, logs, rate limits y testing.

WordPress

Si trabajas con WordPress, ya existe una REST API que puedes extender

No siempre necesitas construir una API PHP desde cero.

WordPress proporciona su propia REST API y permite registrar endpoints personalizados.

Los mismos conceptos siguen siendo importantes: HTTP, JSON, autenticación, permisos, validación y códigos de estado.

WordPress REST API

PHP también permite convertir WordPress en backend para otros sistemas

Plugins, endpoints e integraciones.

PHP para WordPress →
Qué puedes conectar

Una API PHP puede convertirse en la capa central de múltiples aplicaciones

Frontend web

JavaScript consume JSON mediante HTTP.

App móvil

Android o iOS utiliza la misma API.

Ecommerce

Productos, pedidos, pagos e inventario.

SaaS

Usuarios, planes, consumo y suscripciones.

IA

Intermediario entre clientes y modelos externos.

Integraciones

CRM, ERP, pagos y terceros.

Ecosistema

Una API es uno de los mecanismos fundamentales para conectar software

Continúa con arquitectura, webhooks e integraciones.

APIs e integraciones →
Errores frecuentes

Qué evitar al crear una API REST con PHP

Error Crear un archivo PHP diferente para cada operación
Rutas
Error Devolver siempre código HTTP 200
Status
Error Confiar en JSON recibido
Valida
Error Concatenar parámetros en SQL
PDO
Error Confundir autenticación con autorización
Separa
Error Utilizar CORS como seguridad
Auth
Error Mostrar excepciones completas
Registra
Error Devolver miles de registros sin paginación
Pagina
Conclusión

Crear una API REST con PHP exige comprender HTTP tanto como PHP

Define primero recursos y endpoints.

Utiliza métodos HTTP con una semántica coherente.

Devuelve JSON junto con códigos HTTP adecuados.

Valida todos los datos externos.

Utiliza PDO y consultas preparadas para acceder a MySQL.

Separa routing, lógica de negocio y persistencia cuando el proyecto crezca.

Implementa autenticación y autorización como problemas diferentes.

Añade CORS, logs, paginación, rate limiting y testing según las necesidades reales del servicio.

Una buena API no es solamente un archivo PHP que devuelve JSON: es un contrato HTTP estable, seguro y mantenible entre diferentes aplicaciones.

Cluster PHP

Continúa profundizando en PHP

Publicidad
Preguntas frecuentes

Preguntas sobre crear una API REST con PHP

Sí. PHP permite leer solicitudes HTTP, identificar métodos, procesar JSON, consultar bases de datos y devolver respuestas JSON sin utilizar un framework. Hacerlo primero de forma sencilla puede ayudarte a comprender qué automatizan posteriormente los frameworks.

Entre los métodos más habituales se encuentran GET, POST, PUT, PATCH y DELETE. El significado concreto debe quedar definido por el contrato de la API.

Puedes establecer Content-Type como application/json y utilizar json_encode() para convertir arrays u otros datos compatibles en una respuesta JSON.

Puedes utilizar PDO para conectarte con MySQL. Conviene utilizar consultas preparadas, validación, transacciones cuando correspondan y una capa separada para acceso a datos cuando la aplicación crece.

La autenticación determina quién realiza una solicitud. La autorización determina qué recursos y operaciones puede utilizar esa identidad. Una persona puede estar autenticada y aun así no tener permiso para una determinada acción.

CORS es un mecanismo relacionado con solicitudes realizadas desde navegadores entre orígenes diferentes. Una API puede declarar qué orígenes, métodos y headers permite. CORS no reemplaza autenticación ni autorización.

No para un ejemplo pequeño. Sin embargo, cuando una API aumenta de tamaño, POO puede ayudarte a separar controllers, servicios, repositories y otros componentes.

WordPress incluye una REST API y permite registrar endpoints personalizados mediante PHP. Puede utilizarse como backend para aplicaciones externas, siempre que se implementen correctamente permisos, autenticación y validación.

Publicidad
Backend PHP

Una API es el punto donde PHP, HTTP, POO y bases de datos empiezan a trabajar juntos

Construye primero endpoints sencillos, añade PDO y validación, después separa responsabilidades, incorpora autenticación, permisos, paginación y testing.

Continuar con APIs e integraciones →
Carrito de compra
Scroll al inicio