Uma alternativa ao JSONPlaceholder em que as escritas ficam salvas

Os mesmos tipos de recurso, mas as escritas ficam salvas, entradas ruins são rejeitadas e os erros estão disponíveis quando você quiser.

Exemplos executados pela última vez contra a API em

O JSONPlaceholder finge as escritas: um POST devolve id: 101, mas um GET desse id devolve 404, e um DELETE deixa o registro onde estava. Se o seu app precisa ler de volta o que acabou de escrever, use https://api.testingapis.com/apientre para ver. Ela tem os mesmos tipos de recurso (posts, comentários, álbuns, fotos, tarefas e usuários), e criar, atualizar e apagar fica salvo. Ela também rejeita entradas inválidas com 400 e pode fazer qualquer requisição falhar quando você quiser, então dá para construir e testar os estados de erro também. É gratuita, não precisa de chave e aceita requisições de qualquer origem.

Escritas que ficam salvas

Isto é o que o JSONPlaceholder faz com um post novo:

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

Os mesmos passos aqui: criar um post, ler de volta, editar, apagar e conferir que sumiu.

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."}

Correspondência de rotas

JSONPlaceholdertestingapis.comRegistros
/posts/api/posts15 (JSONPlaceholder: 100)
/posts/1/comments/api/posts/1/commentsComentários do post 1
/comments/api/commentsdocs50 (500)
/albums/api/albumsdocs10 (100)
/albums/1/photos/api/albums/1/photosentre para ver5 por álbum
/photos/api/photosdocs50 (5.000)
/todos/api/todos30 (200)
/users/api/peopledocs20 (10), com endereço, coordenadas e empresa
/users/1/posts/api/posts/user/101Os ids de usuário começam em 101

Os caminhos não diferenciam maiúsculas: /api/posts e /api/Posts são a mesma coisa. Há menos registros que no JSONPlaceholder, mas cada um tem mais campos. Os posts têm tags, curtidas e data de publicação, as tarefas têm prioridade e prazo, e as pessoas têm endereço e empresa aninhados. A documentação da API lista mais 13 tipos de recurso, de produtos e carrinhos a livros, filmes e países.

GET/api/posts/1

Entrada ruim recebe erro

O JSONPlaceholder aceita qualquer corpo, até um vazio. Aqui, um campo obrigatório ausente devolve 400 com uma mensagem, então o caminho de erro do seu formulário tem algo real para 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"}

Erros e respostas lentas quando quiser

Adicione ?error=500 a qualquer requisição para fazê-la falhar com esse status, ou ?delay=3 para responder três segundos depois. Juntos, ?delay=2&error=503 mostra um estado de carregamento seguido de um erro. O guia de respostas de erro cobre timeouts, retries e limites de taxa.

GET/api/todos/1?error=503

Filtros, ordenação e paginação

As duas APIs filtram listas por campo, como em ?userId=101, e as duas ordenam, buscam e paginam. Os nomes dos parâmetros mudam:

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

Migrando um app

As leituras devolvem o registro diretamente, como o JSONPlaceholder. As escritas o embrulham com uma mensagem, como { message, data }, e os ids de usuário começam em 101. São as duas mudanças de que a maioria dos apps precisa:

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 exemplo usa endpoints para membros conectados.EntrarCriar uma conta gratuita

Quando o JSONPlaceholder é a melhor escolha

  • Você precisa de listas grandes, como 5.000 fotos para testar rolagem virtual.
  • Você está seguindo um tutorial que usa exatamente os ids e campos do JSONPlaceholder.
  • Você só lê dados e nunca precisa que uma escrita apareça depois.

Para ir além, a lição de teste CRUD mostra como conferir que cada criação, atualização e exclusão aconteceu de verdade.