# Creating your First API with API Platform, in 5 Minutes [API Platform](https://api-platform.com) is one of the most efficient framework out there to create web APIs. It makes it easy to start creating APIs with the support of industry-leading open standards, while giving you the flexibility to build complex features. To discover the basics, we will create an API to manage a bookshop. In a few minutes and just 2 steps, we will create a fully featured API: 1. Install API Platform 2. Handcraft the API data model as *Plain Old PHP Objects* API Platform uses these model classes to expose a web API having a ton of built-in features: * creating, retrieving, updating and deleting (CRUD) resources * data validation * pagination * filtering * sorting * a nice UI and machine-readable documentation ([Swagger/OpenAPI](https://swagger.io), [Hydra](http://hydra-cg.com)) * hypermedia/[HATEOAS](https://en.wikipedia.org/wiki/HATEOAS) and content negotiation support ([JSON-LD](http://json-ld.org), [HAL](http://blog.stateless.co/post/13296666138/json-linking-with-hal)) * authentication ([Basic HTTP](https://en.wikipedia.org/wiki/Basic_access_authentication), cookies as well as [JWT](https://jwt.io/) and [OAuth](https://oauth.net/) through extensions) * [CORS headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) * security (tested against [OWASP recommendations](https://www.owasp.org/index.php/REST_Security_Cheat_Sheet)) * HTTP caching * and basically everything needed to build modern APIs. One more thing, before we start: API Platform is built on top of [the Symfony framework](https://symfony.com). API Platform is compatible with most [Symfony bundles](https://symfony.com/blog/the-30-most-useful-symfony-bundles-and-making-them-even-better) (plugins) and benefits from the numerous extensions points provided by this rock-solid foundation (events, DIC...). Adding features like custom, service-oriented, API endpoints, JWT or OAuth authentication, HTTP caching, mail sending or asynchronous jobs to your APIs is straightforward. ## Installing the framework ### In Docker Containers API Platform is shipped with a [Docker](https://docker.com) setup that makes it easy to get a containerized development environment up and running. This setup contains a [Docker Compose](https://docs.docker.com/compose/) configuration with several pre-configured and ready-use services with everything needed to run API Platform: | Name | Description | Port(s) | ------- | ------------------------------------------------------------- | ------- | app | The application with PHP and PHP-FPM 7.1, the latest Composer | N/A | db | A database provided by MySQL 5.7 | N/A | nginx | An HTTP server provided by Nginx 1.11 | 8080 | varnish | An HTTP cache provided by Varnish 4.1 | 80 Start by [downloading the API Platform Standard Edition archive](https://github.com/api-platform/api-platform/releases/latest) and extract its content. The resulting directory contains an empty API Platform project structure. You will add your own code and configuration inside it. Then, if you do not already have Docker on your computer, [it's the right time to install it](https://www.docker.com/products/overview#/install_the_platform). Open a terminal, and navigate to the directory containing your project skeleton. Then, run the following command to start all services using [Docker Compose](https://docs.docker.com/compose/): $ docker-compose up -d # Running in detached mode If you encounter problems running Docker on Windows (especially with Docker Toolbox), see [our Troubleshooting guide](../extra/troubleshooting.md#using-docker). The first time you start the containers, Docker downloads and builds images for you. It will take some time, but don't worry, this is done only once. Starting servers will then be lightning fast. In order to see container's logs you will have to do: $ docker-compose logs -f # follow the logs Project's files are automatically shared between your local host machine and the container thanks to a pre-configured [Docker volume](https://docs.docker.com/engine/tutorials/dockervolumes/). It means that you can edit files of your project locally using your IDE or code editor, they will be transparently taken into account in the container. Speaking about IDEs, our favorite software to develop API Platform apps is [PHPStorm](https://www.jetbrains.com/phpstorm/) with its awesome [Symfony](https://confluence.jetbrains.com/display/PhpStorm/Getting+Started+-+Symfony+Development+using+PhpStorm) and [PHP annotations](https://plugins.jetbrains.com/plugin/7320) plugins. Give them a try, you'll got auto-completion for almost everything. The API Platform Standard Edition comes with a dummy entity for test purpose: `src/AppBundle/Entity/Foo.php`. We will remove it later, but for now, create the related database table: $ docker-compose exec app bin/console doctrine:schema:create The `app` container is where your project stands. Prefixing a command by `docker-compose exec app` allows to execute the given command in the container. You may want [to create an alias](http://www.linfo.org/alias.html) to easily run commands inside the container. If you're used to the PHP ecosystem, you probably guessed that this test entity uses the industry-leading [Doctrine ORM](http://www.doctrine-project.org/projects/orm.html) library as persistence system. API Platform is 100% independent of the persistence system and you can use the one(s) that best suit(s) your needs (like a NoSQL database or a remote web service). API Platform even supports using several persistence systems together in the same project. However, Doctrine ORM is definitely the easiest way to persist and query data in an API Platform project thanks to a bridge included in the Standard Edition. This Doctrine ORM bridge is optimized for performance and development convenience. Doctrine ORM and its bridge supports major RDBMS including MySQL, PostgreSQL, SQLite, SQL Server and MariaDB. ### Via Composer Instead of using Docker, API Platform can also be installed on the local machine using [Composer](https://getcomposer.org/): $ composer create-project api-platform/api-platform bookshop-api Then, enter the project folder, create the database and its schema: $ cd bookshop-api $ bin/console doctrine:database:create $ bin/console doctrine:schema:create And start the server: $ bin/console server:run ## It's ready! Open `http://localhost` with your favorite web browser: ![Swagger UI integration in API Platform](images/swagger-ui-1.png) API Platform exposes a description of the API in the Swagger format. It also integrates Swagger UI, a nice interface rendering the API documentation. Click on an operation to display its details. You can also send requests to the API directly from the UI. Try to create a new *Foo* resource using the `POST` operation, then access it using the `GET` operation and, finally, delete it by executing the `DELETE` operation. If you access any API URL using a web browser, API Platform detects it (using the `Accept` HTTP header) and displays the corresponding API request in the UI. Try yourself by browsing to `http://localhost/foos`. If you want to access the raw data, you have two alternatives: * Add the correct `Accept` header (or don't set any `Accept` header at all and API Platform will default to JSON-LD) - preferred when writing API clients * Add the format you want as the extension of the resource - for debug purpose only For instance, go to `http://localhost/foos.jsonld` to retrieve the list of `Foo` resources in JSON-LD or `http://localhost/foos.json` to retrieve data in raw JSON. Of course, you can also use your favorite HTTP client to query the API. We strongly recommend to use [Postman](https://www.getpostman.com/). It works perfectly well with API Platform, also has native Swagger support, allows to easily write functional tests and has good team collaboration features. ## Creating the model API Platform is now 100% functional. Let's create our own data model. Our bookshop API will start simple. It will be composed of a `Book` resource type and a `Review` one. Books have an id, an ISBN, a title, a description, an author, a publication date and are related to a list of reviews. Reviews have an id, a rating (between 0 and 5), a body, an author, a publication date and are related to one book. Let's describe this data model as a set of Plain Old PHP Objects (POPO) and map it to database's tables using annotations provided by the Doctrine ORM: ```php