diff --git a/src/DataProvider/PlaceCollectionDataProvider.php b/src/DataProvider/PlaceCollectionDataProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..f89871e18d330979e219c5c345233817e4d03a8e
--- /dev/null
+++ b/src/DataProvider/PlaceCollectionDataProvider.php
@@ -0,0 +1,42 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DBP\API\StarterBundle\DataProvider;
+
+use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
+use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
+use DBP\API\CoreBundle\Helpers\ArrayFullPaginator;
+use DBP\API\StarterBundle\Entity\Place;
+use DBP\API\StarterBundle\Service\PlaceProviderInterface;
+
+final class PlaceCollectionDataProvider implements CollectionDataProviderInterface, RestrictedDataProviderInterface
+{
+    private $api;
+
+    public function __construct(PlaceProviderInterface $api)
+    {
+        $this->api = $api;
+    }
+
+    public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
+    {
+        return Place::class === $resourceClass;
+    }
+
+    public function getCollection(string $resourceClass, string $operationName = null, array $context = []): ArrayFullPaginator
+    {
+        $perPage = 30;
+        $page = 1;
+
+        $filters = $context['filters'] ?? [];
+        if (isset($filters['page'])) {
+            $page = (int) $filters['page'];
+        }
+        if (isset($filters['perPage'])) {
+            $perPage = (int) $filters['perPage'];
+        }
+
+        return new ArrayFullPaginator($this->api->getPlaces(), $page, $perPage);
+    }
+}
diff --git a/src/DataProvider/PlaceItemDataProvider.php b/src/DataProvider/PlaceItemDataProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..e69721fb6ba423842929780293124b3922e4fc0d
--- /dev/null
+++ b/src/DataProvider/PlaceItemDataProvider.php
@@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DBP\API\StarterBundle\DataProvider;
+
+use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
+use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
+use DBP\API\StarterBundle\Entity\Place;
+use DBP\API\StarterBundle\Service\PlaceProviderInterface;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+
+final class PlaceItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
+{
+    private $api;
+
+    public function __construct(PlaceProviderInterface $api)
+    {
+        $this->api = $api;
+    }
+
+    public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
+    {
+        return Place::class === $resourceClass;
+    }
+
+    /**
+     * @param array|int|string $id
+     */
+    public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []): Place
+    {
+        $place = $this->api->getPlaceById($id);
+        if ($place === null) {
+            throw new NotFoundHttpException();
+        }
+
+        return $place;
+    }
+}
diff --git a/src/DependencyInjection/DbpStarterExtension.php b/src/DependencyInjection/DbpStarterExtension.php
index 058f349f1b1194dadc8c560e1fc9effce488332f..7e03ac7b1f5d8901ab05da6f4b4ded7292c4fdd8 100644
--- a/src/DependencyInjection/DbpStarterExtension.php
+++ b/src/DependencyInjection/DbpStarterExtension.php
@@ -13,10 +13,23 @@ class DbpStarterExtension extends Extension
 {
     public function load(array $configs, ContainerBuilder $container)
     {
+        $this->extendArrayParameter(
+            $container, 'api_platform.resource_class_directories', [__DIR__.'/../Entity']);
+
         $loader = new YamlFileLoader(
             $container,
             new FileLocator(__DIR__.'/../Resources/config')
         );
         $loader->load('services.yaml');
     }
+
+    private function extendArrayParameter(ContainerBuilder $container, string $parameter, array $values)
+    {
+        if (!$container->hasParameter($parameter)) {
+            $container->setParameter($parameter, []);
+        }
+        $oldValues = $container->getParameter($parameter);
+        assert(is_array($oldValues));
+        $container->setParameter($parameter, array_merge($oldValues, $values));
+    }
 }
diff --git a/src/Entity/Place.php b/src/Entity/Place.php
new file mode 100644
index 0000000000000000000000000000000000000000..ef50736d3ad14c701d451192633a3b3ca398abbe
--- /dev/null
+++ b/src/Entity/Place.php
@@ -0,0 +1,53 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DBP\API\StarterBundle\Entity;
+
+use ApiPlatform\Core\Annotation\ApiProperty;
+use ApiPlatform\Core\Annotation\ApiResource;
+use Symfony\Component\Serializer\Annotation\Groups;
+
+/**
+ * @ApiResource(
+ *     collectionOperations={"get"},
+ *     itemOperations={"get"},
+ *     iri="https://schema.org/Place",
+ *     normalizationContext={"groups"={"Place:output"}, "jsonld_embed_context"=true}
+ * )
+ */
+class Place
+{
+    /**
+     * @ApiProperty(identifier=true)
+     */
+    private $identifier;
+
+    /**
+     * @ApiProperty(iri="https://schema.org/name")
+     * @Groups({"Place:output"})
+     *
+     * @var string
+     */
+    private $name;
+
+    public function getName(): string
+    {
+        return $this->name;
+    }
+
+    public function setName(string $name): void
+    {
+        $this->name = $name;
+    }
+
+    public function getIdentifier(): string
+    {
+        return $this->identifier;
+    }
+
+    public function setIdentifier(string $identifier): void
+    {
+        $this->identifier = $identifier;
+    }
+}
diff --git a/src/Resources/config/services.yaml b/src/Resources/config/services.yaml
index ac9d7afd6af249850eeffc7c57c9042e3ad379fc..2eec657704474839bfd63410d12fca609ac866d0 100644
--- a/src/Resources/config/services.yaml
+++ b/src/Resources/config/services.yaml
@@ -1,4 +1,19 @@
 services:
   DBP\API\StarterBundle\Command\TestCommand:
     autowire: true
-    autoconfigure: true
\ No newline at end of file
+    autoconfigure: true
+
+  DBP\API\StarterBundle\DataProvider\PlaceCollectionDataProvider:
+    tags: [{ name: 'api_platform.collection_data_provider'}]
+    autowire: true
+
+  DBP\API\StarterBundle\DataProvider\PlaceItemDataProvider:
+    tags: ['api_platform.item_data_provider']
+    autowire: true
+
+  DBP\API\StarterBundle\Service\ExternalApi:
+    autowire: true
+    autoconfigure: true
+
+  DBP\API\StarterBundle\Service\PlaceProviderInterface:
+    '@DBP\API\StarterBundle\Service\ExternalApi'
\ No newline at end of file
diff --git a/src/Service/ExternalApi.php b/src/Service/ExternalApi.php
index a65c6ccc8e8caa1a4b9df0dd895d663b3908cf96..0bd675d1b1681cab19c006177125f3173dd434bf 100644
--- a/src/Service/ExternalApi.php
+++ b/src/Service/ExternalApi.php
@@ -4,9 +4,40 @@ declare(strict_types=1);
 
 namespace DBP\API\StarterBundle\Service;
 
-class ExternalApi
+use DBP\API\StarterBundle\Entity\Place;
+
+class ExternalApi implements PlaceProviderInterface
 {
+    private $places;
+
     public function __construct()
     {
+        $this->places = [];
+        $place1 = new Place();
+        $place1->setIdentifier('graz');
+        $place1->setName('Graz');
+
+        $place2 = new Place();
+        $place2->setIdentifier('vienna');
+        $place2->setName('Vienna');
+
+        $this->places[] = $place1;
+        $this->places[] = $place2;
+    }
+
+    public function getPlaceById(string $identifier): ?Place
+    {
+        foreach ($this->places as $place) {
+            if ($place->getIdentifier() === $identifier) {
+                return $place;
+            }
+        }
+
+        return null;
+    }
+
+    public function getPlaces(): array
+    {
+        return $this->places;
     }
 }
diff --git a/src/Service/PlaceProviderInterface.php b/src/Service/PlaceProviderInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..2ff2aec799272ff0c5be2729d100c35428ace373
--- /dev/null
+++ b/src/Service/PlaceProviderInterface.php
@@ -0,0 +1,14 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DBP\API\StarterBundle\Service;
+
+use DBP\API\StarterBundle\Entity\Place;
+
+interface PlaceProviderInterface
+{
+    public function getPlaceById(string $identifier): ?Place;
+
+    public function getPlaces(): array;
+}