← All guides

📡 We check pokeapi.co (and 75+ other public dev APIs) with a plain GET every 30 minutes — see the live status page. As of publishing it's up and fast. This is one of the best-run free APIs in existence; nothing below is a reliability complaint.

PokéAPI alternative — a Pokédex without the 290 KB payloads

PokéAPI is probably the most-used tutorial API on the planet: 1,351 Pokémon with sprites, moves, types, evolutions — all of it keyless, CORS-open, community-run, and served fast for a decade. If a coding course asks you to "fetch and render something," odds are it's this. Genuinely great — and if you're browsing the canon read-only, use it happily.

But the moment your tutorial Pokédex becomes an app, four walls appear (all checked live on September 18, 2026):

The fix that keeps your rendering code: extract a compact Pokédex once — using their own GraphQL beta, so it's a single request, no N+1 — and host it on a free mock API you control, with substring search, field selection, sorting, real writes, and GraphQL. No signup, no key.

1. Migrate a compact Pokédex in two curls

# 1. one request to PokéAPI's GraphQL beta → 30 compact records (id, name,
#    types, sprite URL, height, weight, base_experience) wrapped as db.json
curl -s -X POST https://graphql.pokeapi.co/v1beta2 -H 'content-type: application/json' \
  -d '{"query":"{ pokemon(limit:30){ id name height weight base_experience pokemontypes{ type{ name } } } }"}' \
  | python3 -c "
import sys, json
rows = json.load(sys.stdin)['data']['pokemon']
recs = [{'id': p['id'], 'name': p['name'],
         'types': ','.join(t['type']['name'] for t in p['pokemontypes']),
         'sprite': f\"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/{p['id']}.png\",
         'height': p['height'], 'weight': p['weight'],
         'base_experience': p['base_experience']} for p in rows]
print(json.dumps({'pokemon': recs}))" > db.json

# 2. import — the response includes your project id + admin key
curl -X POST "https://mockbird.mockbird.workers.dev/api/projects/import?name=pokedex" \
  -H 'content-type: application/json' --data-binary @db.json

That hosted the first 30 Pokémon for us with their real ids preserved (Pikachu is still /pokemon/25), types flattened to "grass,poison", and sprite pointing at PokéAPI's own hosted sprite images (that's how the tutorials use them anyway). Want 100? Change limit:30. Want different fields? Edit the query — you're shaping your own API now.

2. The translation table

PokéAPIYour Mockbird project
/api/v2/pokemon?limit=20&offset=20 → names+URLs only/pokemon?page=2&limit=20 → full records, total in X-Total-Count. The grid is ONE request.
search: none (?name=pika silently ignored)?name_like=chu → [{"id":25,"name":"pikachu"…},{"id":26,"name":"raichu"…}]; a miss is 200 []
sort: none?sortBy=base_experience&order=desc
290 KB per Pokémon, no field trimming?select=name,sprite,types — a 20-card grid (their default page size too) is 3.4 KB measured; all 30 records still fit in 5 KB
filter by type: separate /api/v2/type/:name endpoint, then join client-side?types_like=poison on the same list
/api/v2/pokemon/25/pokemon/25 — same id, same idea
GraphQL: graphql.pokeapi.co beta/graphql — { pokemon(q:"chu"){ name types } pokemonCount }
writes: POST → 404full CRUD, persists (§3)
curl "https://mockbird.mockbird.workers.dev/m/PROJECT_ID/pokemon?name_like=chu&select=name"
# → [{"id":25,"name":"pikachu"},{"id":26,"name":"raichu"}]

curl "https://mockbird.mockbird.workers.dev/m/PROJECT_ID/pokemon?sortBy=base_experience&order=desc&limit=2&select=name,base_experience"
# → [{"id":6,"name":"charizard","base_experience":240},{"id":9,"name":"blastoise","base_experience":239}]

Prefer PokéAPI's count/results envelope so existing pagination code keeps working? One param — ?mock_envelope= with {"count":"$total","results":"$data"} — reproduces it exactly (set it once as the project default; details in docs → envelope):

curl "https://mockbird.mockbird.workers.dev/m/PROJECT_ID/pokemon?mock_envelope=%7B%22count%22%3A%22%24total%22%2C%22results%22%3A%22%24data%22%7D&name_like=chu&select=name"
# → {"count":2,"results":[{"id":25,"name":"pikachu"},{"id":26,"name":"raichu"}]}

3. The part PokéAPI can't do at all: writes

curl -X POST https://mockbird.mockbird.workers.dev/m/PROJECT_ID/pokemon \
  -H 'content-type: application/json' \
  -d '{"name":"mockbirdmon","types":"flying","height":3,"weight":9,"base_experience":100}'
# → 201 {"id":31}   — and GET /pokemon/31 returns it. It persists.

That upgrades the standard read-only Pokédex into a portfolio piece: a team builder that survives refresh, favourites, ratings, an add-your-own-Pokémon form, a delete button that actually deletes. PATCH and PUT work too.

4. Rehearse the bad days it will never show you

PokéAPI is so reliable you can't practise failure against it. Yours can fail on demand:

# two 429s, then success — exercise retry/backoff
curl "https://mockbird.mockbird.workers.dev/m/PROJECT_ID/pokemon?mock_seq=429,429,200&mock_seq_key=drill1"

# 2-second response for your skeleton state
curl "https://mockbird.mockbird.workers.dev/m/PROJECT_ID/pokemon?mock_delay=2000"

More recipes in testing loading & error states.

Where PokéAPI still wins

Almost everywhere, honestly — the depth is the product. Moves, abilities, evolution chains, encounter locations, game versions, forms, 1,351 Pokémon of cross-linked canon that no snapshot reproduces; hosted sprite and artwork files; a decade of reliability; and a GraphQL beta (graphql.pokeapi.co) that genuinely solves the over-fetch and N+1 problems server-side — we used it for the extraction above precisely because it's good. Your import is a snapshot, not a live mirror, and it only carries the fields you chose. The honest split: exploring the full canon read-only → pokeapi.co, happily (mind their fair-use policy: cache what you fetch). A compact Pokédex with one-request grids, search, sort, field selection, writes that persist, and failure drills → your import.

Start now

The two-curl block in section 1, or zero setup at all:

curl https://mockbird.mockbird.workers.dev/m/demo/products?limit=3

Facts checked live on September 18, 2026: GET /api/v2/pokemon/pikachu measured 290,912 bytes; /api/v2/pokemon?limit=2 returns name+url pairs only with count: 1351; ?name=pika and ordering= on the list are silently ignored (full list returned, no error); /api/v2/pokemon/pikachuu answers 404 {"status":404,"message":"Not Found"}; POST /api/v2/pokemon answers 404; the GraphQL beta at graphql.pokeapi.co/v1beta2 answered our extraction query correctly. Every Mockbird command on this page was run against a live project before publishing (the 3.4 KB figure is the real measured response for the default 20-record page with ?select=name,sprite,types — 3,352 bytes), and the scratch project was deleted after.

Full API reference in the docs. More guides: Rick and Morty API alternative · Jikan (MyAnimeList) API alternative · SWAPI alternative · JSONPlaceholder alternative · Free GraphQL mock API · Mock API for React. Create your API →

⚡ Skip the terminal: this link opens the dashboard's import panel — paste the db.json from section 1 and you're done. No signup.