{"id":24838217,"url":"https://github.com/remojs/gottafetchthemall-api","last_synced_at":"2026-04-12T03:38:23.427Z","repository":{"id":186327495,"uuid":"675007292","full_name":"Remojs/GottaFetchThemAll-API","owner":"Remojs","description":"🌳 Gotta Fetch Them All backend","archived":false,"fork":false,"pushed_at":"2026-03-17T22:32:51.000Z","size":143,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-03-18T12:24:39.754Z","etag":null,"topics":["api","cors","express","javascript","mongodb","mongoose","node","pokemon"],"latest_commit_sha":null,"homepage":"https://gottafetchthemall.onrender.com/pokedex","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Remojs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-08-05T13:17:53.000Z","updated_at":"2026-03-17T22:32:54.000Z","dependencies_parsed_at":null,"dependency_job_id":"deb52d38-3832-4726-b25a-3736ca66e451","html_url":"https://github.com/Remojs/GottaFetchThemAll-API","commit_stats":null,"previous_names":["remojs/gottafetchthemall-api"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Remojs/GottaFetchThemAll-API","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Remojs%2FGottaFetchThemAll-API","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Remojs%2FGottaFetchThemAll-API/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Remojs%2FGottaFetchThemAll-API/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Remojs%2FGottaFetchThemAll-API/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Remojs","download_url":"https://codeload.github.com/Remojs/GottaFetchThemAll-API/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Remojs%2FGottaFetchThemAll-API/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31703501,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-11T21:17:31.016Z","status":"online","status_checked_at":"2026-04-12T02:00:06.763Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","cors","express","javascript","mongodb","mongoose","node","pokemon"],"created_at":"2025-01-31T06:09:48.352Z","updated_at":"2026-04-12T03:38:23.410Z","avatar_url":"https://github.com/Remojs.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GottaFetchThemAll API\n\nLa **GottaFetchThemAll API** es una REST API que provee datos esenciales de los 1025 Pokémon de las 9 generaciones, optimizada para no cargar información irrelevante. \n\n## Modelo de datos — Pokemon\n\nCada documento en la colección tiene la siguiente estructura:\n\n```json\n{\n  \"_id\": \"6394ccde0444413377f32891\",\n  \"ID\": 25,\n  \"name\": \"pikachu\",\n  \"image\": \"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/25.png\",\n  \"first_type\": \"electric\",\n  \"second_type\": null,\n  \"ability\": \"static\",\n  \"height\": \"0.4m\",\n  \"weight\": \"6kg\",\n  \"stats\": {\n    \"hp\": 35,\n    \"attack\": 55,\n    \"defense\": 40,\n    \"special_attack\": 50,\n    \"special_defense\": 50,\n    \"speed\": 90\n  }\n}\n```\n\n---\n\n## Valores válidos\n\n### Tipos (`first_type` / `second_type`)\n`normal` `fire` `water` `grass` `flying` `fighting` `poison` `electric` `ground` `rock` `psychic` `ice` `bug` `ghost` `steel` `dragon` `dark` `fairy`\n\n### Stats\n`hp` `attack` `defense` `special_attack` `special_defense` `speed`\n\n### Generaciones\n`1` (1–151) · `2` (152–251) · `3` (252–386) · `4` (387–494) · `5` (495–649) · `6` (650–721) · `7` (722–809) · `8` (810–905) · `9` (906–1010)\n\n---\n\n## Endpoints\n\n### `GET /pokedex`\n\nDevuelve todos los Pokémon de la base de datos con **paginación**.\n\n**Query params**\n\n| Param | Tipo | Requerido | Descripción |\n|---|---|---|---|\n| `page` | number | No | Página (default: `1`) |\n| `limit` | number | No | Resultados por página, máx `200` (default: `100`) |\n| `first_type` | string | No | Filtra por tipo primario |\n| `second_type` | string | No | Filtra por tipo secundario |\n| `ability` | string | No | Filtra por habilidad exacta |\n\n**Respuesta `200`**\n```json\n{\n  \"data\": [ ...pokémon ],\n  \"total\": 1010,\n  \"page\": 1,\n  \"limit\": 100,\n  \"pages\": 11\n}\n```\n\n**Ejemplo**\n```\nGET /pokedex?page=2\u0026limit=50\u0026first_type=fire\n```\n\n---\n\n### `GET /pokedex/between`\n\nDevuelve todos los Pokémon cuyo número de Pokédex está dentro de un rango.\n\n**Query params**\n\n| Param | Tipo | Requerido | Descripción |\n|---|---|---|---|\n| `min` | number | Sí | ID mínimo |\n| `max` | number | Sí | ID máximo |\n\n**Respuesta `200`** — Array de Pokémon\n\n**Ejemplo**\n```\nGET /pokedex/between?min=1\u0026max=50\n```\n\n---\n\n### `GET /pokedex/random`\n\nDevuelve uno o más Pokémon aleatorios.\n\n**Query params**\n\n| Param | Tipo | Requerido | Descripción |\n|---|---|---|---|\n| `count` | number | No | Cantidad, máx `10` (default: `1`) |\n\n**Respuesta `200`** — Array de Pokémon\n\n**Ejemplo**\n```\nGET /pokedex/random?count=3\n```\n\n---\n\n### `GET /pokedex/types`\n\nDevuelve la lista de todos los tipos únicos presentes en la base de datos, ordenados alfabéticamente.\n\n**Respuesta `200`**\n```json\n[\"bug\", \"dark\", \"dragon\", \"electric\", \"fairy\", \"fighting\", ...]\n```\n\n---\n\n### `GET /pokedex/abilities`\n\nDevuelve la lista de todas las habilidades únicas presentes en la base de datos, ordenadas alfabéticamente.\n\n**Respuesta `200`**\n```json\n[\"blaze\", \"chlorophyll\", \"compound-eyes\", \"overgrow\", \"static\", ...]\n```\n\n---\n\n### `GET /pokedex/gen/:gen`\n\nDevuelve todos los Pokémon de una generación específica.\n\n**Path params**\n\n| Param | Tipo | Valores válidos |\n|---|---|---|\n| `gen` | string | `1` a `9` |\n\n**Respuesta `200`** — Array de Pokémon · **`500`** si la generación no es válida\n\n**Ejemplo**\n```\nGET /pokedex/gen/1\n```\n\n---\n\n### `GET /pokedex/name/:name`\n\nBusca Pokémon por nombre. La búsqueda es **parcial y case-insensitive** (buscar `char` devuelve Charmander, Charmeleon y Charizard).\n\n**Path params**\n\n| Param | Tipo | Descripción |\n|---|---|---|\n| `name` | string | Nombre o fragmento del nombre |\n\n**Respuesta `200`** — Array de Pokémon\n\n**Ejemplo**\n```\nGET /pokedex/name/char\n```\n\n---\n\n### `GET /pokedex/number/:id`\n\nDevuelve el Pokémon con ese número de Pokédex.\n\n**Path params**\n\n| Param | Tipo | Descripción |\n|---|---|---|\n| `id` | number | Número de Pokédex |\n\n**Respuesta `200`** — Array con un Pokémon · **`500`** si el ID no es un número\n\n**Ejemplo**\n```\nGET /pokedex/number/25\n```\n\n---\n\n### `GET /pokedex/type/:type`\n\nDevuelve todos los Pokémon que tienen ese tipo como `first_type` **o** `second_type`.\n\n**Path params**\n\n| Param | Tipo | Descripción |\n|---|---|---|\n| `type` | string | Nombre del tipo (ver valores válidos) |\n\n**Respuesta `200`** — Array de Pokémon · **`500`** si el tipo no es válido\n\n**Ejemplo**\n```\nGET /pokedex/type/flying\n```\n\n---\n\n### `GET /pokedex/dual-type/:first/:second`\n\nDevuelve todos los Pokémon que tienen exactamente esos dos tipos (en cualquier orden).\n\n**Path params**\n\n| Param | Tipo | Descripción |\n|---|---|---|\n| `first` | string | Primer tipo |\n| `second` | string | Segundo tipo |\n\n**Respuesta `200`** — Array de Pokémon\n\n**Ejemplo**\n```\nGET /pokedex/dual-type/fire/flying\n```\n\n---\n\n### `GET /pokedex/ability/:ability`\n\nDevuelve todos los Pokémon con una habilidad específica. La búsqueda es **parcial y case-insensitive**.\n\n**Path params**\n\n| Param | Tipo | Descripción |\n|---|---|---|\n| `ability` | string | Nombre o fragmento de la habilidad |\n\n**Respuesta `200`** — Array de Pokémon\n\n**Ejemplo**\n```\nGET /pokedex/ability/static\n```\n\n---\n\n### `GET /pokedex/stat/min/:stat`\n\nDevuelve todos los Pokémon ordenados **de menor a mayor** por el stat indicado.\n\n**Path params**\n\n| Param | Tipo | Valores válidos |\n|---|---|---|\n| `stat` | string | `hp` `attack` `defense` `special_attack` `special_defense` `speed` |\n\n**Respuesta `200`** — Array de Pokémon ordenado · **`500`** si el stat no es válido\n\n**Ejemplo**\n```\nGET /pokedex/stat/min/speed\n```\n\n---\n\n### `GET /pokedex/stat/max/:stat`\n\nDevuelve todos los Pokémon ordenados **de mayor a menor** por el stat indicado.\n\n**Path params**\n\n| Param | Tipo | Valores válidos |\n|---|---|---|\n| `stat` | string | `hp` `attack` `defense` `special_attack` `special_defense` `speed` |\n\n**Respuesta `200`** — Array de Pokémon ordenado · **`500`** si el stat no es válido\n\n**Ejemplo**\n```\nGET /pokedex/stat/max/attack\n```\n\n---\n\n### `GET /pokedex/stat/range/:stat`\n\nDevuelve todos los Pokémon cuyo valor en el stat indicado está dentro del rango especificado, ordenados de menor a mayor.\n\n**Path params**\n\n| Param | Tipo | Descripción |\n|---|---|---|\n| `stat` | string | Nombre del stat (ver valores válidos) |\n\n**Query params**\n\n| Param | Tipo | Requerido | Descripción |\n|---|---|---|---|\n| `min` | number | No* | Valor mínimo del stat |\n| `max` | number | No* | Valor máximo del stat |\n\n*Al menos uno de los dos es requerido.\n\n**Respuesta `200`** — Array de Pokémon · **`400`** si no se pasa ni `min` ni `max` · **`500`** si el stat no es válido\n\n**Ejemplo**\n```\nGET /pokedex/stat/range/attack?min=100\u0026max=150\n```\n\n---\n\n## Resumen de endpoints\n\n| Método | Ruta | Descripción |\n|---|---|---|\n| GET | `/pokedex` | Todos los Pokémon (paginado, filtrable) |\n| GET | `/pokedex/between?min=\u0026max=` | Por rango de ID |\n| GET | `/pokedex/random?count=` | Aleatorio/s |\n| GET | `/pokedex/types` | Lista de tipos únicos |\n| GET | `/pokedex/abilities` | Lista de habilidades únicas |\n| GET | `/pokedex/gen/:gen` | Por generación (1–9) |\n| GET | `/pokedex/name/:name` | Por nombre (parcial, case-insensitive) |\n| GET | `/pokedex/number/:id` | Por número de Pokédex |\n| GET | `/pokedex/type/:type` | Por tipo (first o second) |\n| GET | `/pokedex/dual-type/:first/:second` | Por doble tipo exacto |\n| GET | `/pokedex/ability/:ability` | Por habilidad (parcial, case-insensitive) |\n| GET | `/pokedex/stat/min/:stat` | Ordenado por stat ascendente |\n| GET | `/pokedex/stat/max/:stat` | Ordenado por stat descendente |\n| GET | `/pokedex/stat/range/:stat?min=\u0026max=` | Por rango de valor de stat |\n\n---\n\n## Changelog\n\n### v2.0.0 — 2026-03-05\n\n#### Nuevos endpoints\n- `GET /pokedex/types` — lista todos los tipos únicos de la DB\n- `GET /pokedex/abilities` — lista todas las habilidades únicas de la DB\n- `GET /pokedex/random?count=N` — devuelve N Pokémon aleatorios (máx 10)\n- `GET /pokedex/dual-type/:first/:second` — filtra por doble tipo exacto en cualquier orden\n- `GET /pokedex/stat/range/:stat?min=\u0026max=` — filtra por rango de valor de un stat\n\n#### Correcciones de bugs\n- Middleware (`cors`, `morgan`, `express.json`) se registraba **después** del router, por lo que nunca se aplicaba a ninguna request\n- `throw new error` (minúscula) en gen y type controllers causaba un `ReferenceError` silencioso en runtime\n- `/pokedex/type/:type` solo filtraba `first_type`, ignorando el `second_type` — Pokémon como Charizard no aparecían en `/type/flying`\n- `min` y `max` en `/pokedex/between` se pasaban como strings a una query numérica de MongoDB, produciendo resultados incorrectos\n- Stat inválido en min/max fallaba silenciosamente sin devolver error\n- Variables `pokes` declaradas sin `const`/`let` en todos los controllers (variables globales accidentales)\n- Eliminadas opciones deprecadas `useNewUrlParser` y `useUnifiedTopology` de la conexión a Mongoose\n\n#### Mejoras de rendimiento\n- Paginación en `GET /pokedex`: ya no devuelve todos los documentos de una vez; ahora acepta `page` y `limit` (máx 200) y devuelve metadata `{ data, total, page, limit, pages }`\n- `.lean()` agregado a todas las queries — retorna objetos JS planos en vez de documentos Mongoose completos\n- Índices de MongoDB agregados al modelo: `ID` (unique), `name`, `first_type`, `second_type`, `ability`\n\n#### Mejoras de usabilidad\n- Búsqueda por nombre (`/name/:name`) ahora es parcial y case-insensitive\n- Búsqueda por habilidad (`/ability/:ability`) ahora es parcial y case-insensitive\n- Validación de parámetros con mensajes de error descriptivos en todos los endpoints\n\n### v1.0.0 — 2024\n\n- Release inicial con 9 endpoints básicos de la Pokédex","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fremojs%2Fgottafetchthemall-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fremojs%2Fgottafetchthemall-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fremojs%2Fgottafetchthemall-api/lists"}