Una alternativa a JSONPlaceholder donde las escrituras se guardan

Los mismos tipos de recursos, pero las escrituras se guardan, la entrada mala se rechaza y los errores están disponibles cuando quieras.

Ejemplos ejecutados por última vez contra la API el

JSONPlaceholder finge sus escrituras: un POST devuelve id: 101, pero un GET de ese id devuelve 404, y un DELETE deja el registro donde estaba. Si tu app necesita volver a leer lo que acaba de escribir, usa https://api.testingapis.com/apiinicia sesión para verlo. Tiene los mismos tipos de recursos (posts, comentarios, álbumes, fotos, tareas y usuarios), y crear, actualizar y borrar se guarda de verdad. Además rechaza la entrada inválida con un 400 y puede hacer fallar cualquier petición cuando quieras, así que también puedes construir y probar los estados de error. Es gratuita, no necesita clave y acepta peticiones desde cualquier origen.

Escrituras que se guardan

Esto es lo que hace JSONPlaceholder con un post nuevo:

Terminal
$ curl -X POST https://jsonplaceholder.typicode.com/posts \
  -H "Content-Type: application/json" \
  -d '{"title":"hello","body":"world","userId":1}'
{ "title": "hello", "body": "world", "userId": 1, "id": 101 }

$ curl -i https://jsonplaceholder.typicode.com/posts/101
HTTP/1.1 404 Not Found

Los mismos pasos aquí: crear un post, volver a leerlo, editarlo, borrarlo y comprobar que ha desaparecido.

Terminal
$ curl -X POST https://api.testingapis.com/api/Posts \
  -H "Content-Type: application/json" \
  -d '{"userId":101,"title":"Hello from the guide","body":"Checking that writes persist."}'
{"message":"Post created successfully","data":{"id":16,"userId":101,"title":"Hello from the guide","body":"Checking that writes persist.","tags":[],"publishedAt":"2026-10-07T02:58:58Z","likes":0}}

$ curl https://api.testingapis.com/api/Posts/16
{"id":16,"userId":101,"title":"Hello from the guide","body":"Checking that writes persist.","tags":[],"publishedAt":"2026-10-07T02:58:58Z","likes":0}

$ curl -X PUT https://api.testingapis.com/api/Posts/16 \
  -H "Content-Type: application/json" \
  -d '{"userId":101,"title":"Edited title","body":"Checking that writes persist."}'
{"message":"Post updated successfully","data":{"id":16,"userId":101,"title":"Edited title",...}}

$ curl -X DELETE https://api.testingapis.com/api/Posts/16
{"message":"Post deleted successfully"}

$ curl -i https://api.testingapis.com/api/Posts/16
HTTP/1.1 404 Not Found

{"status":404,"error":"Not Found","message":"Post with ID 16 does not exist."}

Equivalencia de rutas

JSONPlaceholdertestingapis.comRegistros
/posts/api/posts15 (JSONPlaceholder: 100)
/posts/1/comments/api/posts/1/commentsComentarios del post 1
/comments/api/commentsdocs50 (500)
/albums/api/albumsdocs10 (100)
/albums/1/photos/api/albums/1/photosinicia sesión para verlo5 por álbum
/photos/api/photosdocs50 (5.000)
/todos/api/todos30 (200)
/users/api/peopledocs20 (10), con dirección, coordenadas y empresa
/users/1/posts/api/posts/user/101Los ids de usuario empiezan en 101

Las rutas no distinguen mayúsculas: /api/posts y /api/Posts son lo mismo. Hay menos registros que en JSONPlaceholder, pero cada uno tiene más campos. Los posts tienen etiquetas, likes y fecha de publicación, las tareas tienen prioridad y fecha límite, y las personas tienen una dirección y una empresa anidadas. La documentación de la API lista 13 tipos de recurso más, desde productos y carritos hasta libros, películas y países.

GET/api/posts/1

La entrada mala recibe un error

JSONPlaceholder acepta cualquier cuerpo, incluso uno vacío. Aquí, un campo obligatorio que falta devuelve un 400 con un mensaje, así que la rama de error de tu formulario tiene algo real que mostrar:

Terminal
$ curl -i -X POST https://jsonplaceholder.typicode.com/posts -H "Content-Type: application/json" -d '{}'
HTTP/1.1 201 Created

{ "id": 101 }

$ curl -i -X POST https://api.testingapis.com/api/Posts -H "Content-Type: application/json" -d '{"title":""}'
HTTP/1.1 400 Bad Request

{"status":400,"error":"Bad Request","message":"Missing required field: title"}

Errores y respuestas lentas cuando quieras

Añade ?error=500 a cualquier petición para que falle con ese estado, o ?delay=3 para que responda tres segundos tarde. Juntos, ?delay=2&error=503 muestra un estado de carga seguido de un error. La guía de respuestas de error cubre timeouts, reintentos y límites de frecuencia.

GET/api/todos/1?error=503

Filtros, ordenación y paginación

Las dos APIs filtran listas por campo, como en ?userId=101, y las dos ordenan, buscan y paginan. Los nombres de los parámetros cambian:

JSONPlaceholdertestingapis.com
Filtrar?userId=1?userId=101
Paginar?_page=2&_limit=10?page=2&limit=10
Ordenar?_sort=id&_order=desc?sort=id&order=desc
Buscar?q=word?q=word
TotalX-Total-CountX-Total-Count, X-Total-Pages

Pasar una app de una a otra

Las lecturas devuelven el registro directamente, como JSONPlaceholder. Las escrituras lo envuelven con un mensaje, como { message, data }, y los ids de usuario empiezan en 101. Esos son los dos cambios que necesitan casi todas las apps:

JavaScript
// Before
const BASE = "https://jsonplaceholder.typicode.com";
const post = await (await fetch(`${BASE}/posts/1`)).json();

const created = await (await fetch(`${BASE}/posts`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ userId: 1, title: "Hi", body: "There" }),
})).json();

// After
const BASE = "https://api.testingapis.com/api";
const post = await (await fetch(`${BASE}/posts/1`)).json();

const { data: created } = await (await fetch(`${BASE}/posts`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ userId: 101, title: "Hi", body: "There" }),
})).json();
Este ejemplo usa endpoints para miembros con sesión iniciada.Iniciar sesiónCrear una cuenta gratuita

Cuándo es mejor JSONPlaceholder

  • Necesitas listas grandes, como 5.000 fotos para probar el scroll virtual.
  • Sigues un tutorial que usa exactamente los ids y campos de JSONPlaceholder.
  • Solo lees datos y nunca necesitas que una escritura aparezca después.

Para ir más allá, la lección de testing CRUD explica cómo comprobar que cada creación, actualización y borrado ocurrió de verdad.