diff --git a/src/main/java/nl/utwente/mod4/pokemon/dao/PokemonDao.java b/src/main/java/nl/utwente/mod4/pokemon/dao/PokemonDao.java
new file mode 100644
index 0000000000000000000000000000000000000000..28397ed0ff6b0d0cc965ad87955f384c45e22d2d
--- /dev/null
+++ b/src/main/java/nl/utwente/mod4/pokemon/dao/PokemonDao.java
@@ -0,0 +1,94 @@
+package nl.utwente.mod4.pokemon.dao;
+
+import jakarta.ws.rs.BadRequestException;
+import jakarta.ws.rs.NotFoundException;
+import jakarta.ws.rs.NotSupportedException;
+import nl.utwente.mod4.pokemon.Utils;
+import nl.utwente.mod4.pokemon.model.Pokemon;
+
+import java.io.InputStreamReader;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+public enum PokemonDao {
+    INSTANCE;
+    private static final String POKEMON = Utils.getAbsolutePathToResources() + "/pokemon.json";
+    private HashMap<String, Pokemon> pokemons = new HashMap<>();
+
+    public List<Pokemon> getPokemons(int pageSize, int pageNumber, String sortBy) {
+        List<Pokemon> list = new ArrayList<>(pokemons.values());
+
+        if(sortBy == null || sortBy.isEmpty() || "id".equals(sortBy)) {
+            list.sort((p1, p2) -> Utils.compare(Integer.parseInt(p1.id), Integer.parseInt(p2.id)));
+        }
+        else if("lastUpdate".equals(sortBy)) {
+            list.sort((p1, p2) -> Utils.compare(Integer.parseInt(p1.lastUpDate), Integer.parseInt(p2.lastUpDate)));
+        }
+        else if("name".equals(sortBy)) {
+            list.sort((p1, p2) -> Utils.compare(p1.name, p2.name));
+        }
+        else {
+            throw new NotSupportedException("Sort field not supported");
+        }
+        return (List<Pokemon>) Utils.pageSlice(list, pageSize, pageNumber);
+    }
+
+    public int getTotalPokemonTypes() {
+        return pokemons.keySet().size();
+    }
+
+    public Pokemon getPokemon(String id) {
+        var p = pokemons.get(id);
+
+        if(p == null) {
+            throw new NotFoundException("Pokemon '" + id + "' not found!");
+        }
+
+        return p;
+    }
+
+    public void delete(String id) {
+        if(pokemons.containsKey(id)) {
+            pokemons.remove(id);
+        }
+        else {
+            throw new NotFoundException("Pokemon '" + id + "' not found!");
+        }
+    }
+
+    public Pokemon replace(Pokemon updated) {
+        if(!updated.checkIsValid()) {
+            throw new BadRequestException("Invalid pokemon");
+        }
+        if(pokemons.get(updated.id) == null) {
+            throw new NotFoundException("Pokemon '" + updated.id + "' not found!");
+        }
+
+        updated.lastUpDate = Instant.now().toString();
+        pokemons.put(updated.id, updated);
+
+        return updated;
+    }
+
+    public Pokemon create(Pokemon newPokemon) {
+        String nextId = "" + (getMaxId() + 1);
+
+        newPokemon.id = nextId;
+        newPokemon.created = Instant.now().toString();
+        newPokemon.lastUpDate = Instant.now().toString();
+        pokemons.put(nextId, newPokemon);
+
+        return newPokemon;
+    }
+
+    private int getMaxId() {
+        Set<String> ids = pokemons.keySet();
+        return ids.isEmpty() ? 0 : ids.stream()
+                .map(Integer::parseInt)
+                .max(Integer::compareTo)
+                .get();
+    }
+}
diff --git a/src/main/java/nl/utwente/mod4/pokemon/model/Pokemon.java b/src/main/java/nl/utwente/mod4/pokemon/model/Pokemon.java
new file mode 100644
index 0000000000000000000000000000000000000000..30e0dfff8316b14b216dd11c6ef376acd0405f86
--- /dev/null
+++ b/src/main/java/nl/utwente/mod4/pokemon/model/Pokemon.java
@@ -0,0 +1,13 @@
+package nl.utwente.mod4.pokemon.model;
+
+
+public class Pokemon extends NamedEntity {
+    public int pokemonType;
+    public int trainerId;
+
+    public Pokemon() {
+        super();
+        pokemonType = 0;
+        trainerId = 0;
+    }
+}
diff --git a/src/main/java/nl/utwente/mod4/pokemon/routes/PokemonRoute.java b/src/main/java/nl/utwente/mod4/pokemon/routes/PokemonRoute.java
new file mode 100644
index 0000000000000000000000000000000000000000..7382a92ca0ab8144a1e0101e6f5c78e315651be2
--- /dev/null
+++ b/src/main/java/nl/utwente/mod4/pokemon/routes/PokemonRoute.java
@@ -0,0 +1,63 @@
+package nl.utwente.mod4.pokemon.routes;
+
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+import nl.utwente.mod4.pokemon.dao.PokemonDao;
+import nl.utwente.mod4.pokemon.model.Pokemon;
+import nl.utwente.mod4.pokemon.model.ResourceCollection;
+
+import javax.print.attribute.standard.Media;
+
+@Path("/pokemon")
+public class PokemonRoute {
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public ResourceCollection<Pokemon> getPokemons(
+            @QueryParam("sortBy") String sortBy,
+            @QueryParam("pageSize") int pageSize,
+            @QueryParam("pageNumber") int pageNumber
+    ) {
+        int ps = pageSize > 0 ? pageSize : Integer.MAX_VALUE;
+        int pn = pageNumber > 0 ? pageNumber : 1;
+
+        Pokemon[] resources = PokemonDao.INSTANCE.getPokemons(ps, pn, sortBy).toArray(new Pokemon[0]);
+
+        int total = PokemonDao.INSTANCE.getTotalPokemonTypes();
+        ps = resources == null ? 0 : resources.length;
+
+        return new ResourceCollection<>(resources, ps, pn, total);
+    }
+
+    @GET
+    @Path("/{id}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Pokemon getPokemon(@PathParam("id") String id) {
+        return PokemonDao.INSTANCE.getPokemon(id);
+    }
+
+    @DELETE
+    @Path("/{id}")
+    public void deletePokemon(@PathParam("id") String id) {
+        PokemonDao.INSTANCE.delete(id);
+    }
+
+    @PUT
+    @Path("/{id}")
+    @Produces(MediaType.APPLICATION_JSON)
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Pokemon updatePokemon(@PathParam("id") String id, Pokemon toReplace) {
+        if(id == null || !id.equals(toReplace.id)) {
+            throw new BadRequestException("Id mismatch");
+        }
+
+        return PokemonDao.INSTANCE.replace(toReplace);
+    }
+
+    @POST
+    @Produces(MediaType.APPLICATION_JSON)
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Pokemon createPokemon(Pokemon pokemon) {
+        return PokemonDao.INSTANCE.create(pokemon);
+    }
+
+}