A REST API for retrieving Pokemon information, combining data from PokeAPI with a local database and a banned Pokemon registry.
Stack: Laravel 11, MySQL, Redis, Docker (Laravel Sail)
- Docker
1. Clone the repository
git clone <repository-url>
cd pokemon-api2. Copy the environment file
cp .env.example .env3. Add secret key to .env
Open the .env file and set your key:
SUPER_SECRET_KEY="WhyPikachuIsGoodFriend"
4. Install composer dependencies
docker run --rm \
-u "$(id -u):$(id -g)" \
-v "$(pwd):/var/www/html" \
-w /var/www/html \
laravelsail/php85-composer:latest \
composer install --ignore-platform-reqs
5. Start the containers Now that Sail is installed, you can start the environment:
./vendor/bin/sail up -d6. Run migrations
./vendor/bin/sail artisan migrate✅ API is now available at http://localhost
Protected endpoints require the following header:
| Header | Value |
|---|---|
X-SUPER-SECRET-KEY |
value from .env SUPER_SECRET_KEY |
Missing or invalid key returns 401 Unauthorized.
Returns information about requested Pokemon. Banned Pokemon are excluded. Custom (locally added) Pokemon are marked with is_custom: true.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
names[] |
string | ✅ | Pokemon name(s) to look up |
Example request:
GET /api/info?names[]=pikachu&names[]=mypokemon
Example response 200 OK:
{
"data": [
{
"name": "pikachu",
"base_experience": 112,
"height": 4,
"weight": 60,
"is_custom": false
},
{
"name": "mypokemon",
"base_experience": 100,
"height": 5,
"weight": 10,
"is_custom": true
}
]
}Returns a list of all banned Pokemon names.
Example response 200 OK:
["pikachu", "mewtwo"]Adds a Pokemon to the banned list.
Request body:
{
"name": "pikachu"
}Responses:
| Code | Description |
|---|---|
201 Created |
Pokemon successfully banned |
422 Unprocessable Entity |
Validation error (e.g. already banned) |
401 Unauthorized |
Invalid or missing secret key |
Removes a Pokemon from the banned list.
Example:
DELETE /api/banned/pikachu
Responses:
| Code | Description |
|---|---|
200 OK |
Pokemon removed from banned list |
404 Not Found |
Pokemon not found in banned list |
401 Unauthorized |
Invalid or missing secret key |
Returns all custom (locally added) Pokemon.
Example response 200 OK:
[
{
"id": 1,
"name": "mypokemon",
"base_experience": 100,
"height": 5,
"weight": 10
}
]Creates a new custom Pokemon. Name must be unique across both local database and PokeAPI.
Request body:
{
"name": "mypokemon",
"base_experience": 100,
"height": 5,
"weight": 10
}Responses:
| Code | Description |
|---|---|
201 Created |
Pokemon successfully created |
422 Unprocessable Entity |
Validation error (e.g. name already exists in PokeAPI or local DB) |
401 Unauthorized |
Invalid or missing secret key |
Returns a single custom Pokemon by ID.
Responses:
| Code | Description |
|---|---|
200 OK |
Pokemon data returned |
404 Not Found |
Pokemon not found |
Updates an existing custom Pokemon.
Request body (all fields optional for PATCH):
{
"name": "updatedname",
"base_experience": 150,
"height": 6,
"weight": 12
}Responses:
| Code | Description |
|---|---|
200 OK |
Pokemon successfully updated |
404 Not Found |
Pokemon not found |
401 Unauthorized |
Invalid or missing secret key |
Deletes a custom Pokemon.
Responses:
| Code | Description |
|---|---|
204 No Content |
Pokemon successfully deleted |
404 Not Found |
Pokemon not found |
401 Unauthorized |
Invalid or missing secret key |
- Service Pattern — business logic extracted into
PokemonInfoService - Form Requests — request validation with custom
UniquePokemonNamerule - Redis Cache — PokeAPI responses cached until 12:00 PM (UTC+1) daily
- Middleware —
CheckSecretKeyprotects all admin endpoints
