Your First Versioned API with Phoenix Framework

John Ezekiel
6 min readDec 4, 2017

Phoenix is a framework written in Elixir, a functional programming language with ruby-like syntax that uses the Erlang VM. There are many reasons to use Elixir and Phoenix, which are pretty well explained here.

I haven’t gotten to the more powerful features of the language. My first desire is actually to implement a RESTful API so I can begin to play around and learn the framework. There are many tutorials detailing how to do this in 1.2, but as 1.3 introduces contexts, most resources I’ve found are not particularly helpful.

We will be setting up API routes for CRUD operations on a user resource. For example, GET and Post methods for /api/v1/users . We will be relying on the Phoenix Generators to get us there.

Create Your App

First, make sure you’ve installed all your dependencies. Installation instructions are here

Now, let’s create our new test application. We can do this easily by invoking mix phx.new app in the directory you want the app to live. When it asks if you want to fetch and install dependencies, say yes. Voila! You have an app in phoenix framework made for you.

Next, navigate to config/dev.exs and update your database settings

My development password is ‘mysecretpassword’, change yours accordingly

Quick Tip: If you have docker installed. You can run the following command…

docker run --name app -e POSTGRES_PASSWORD=mysecretpassword -p 5432:5432 -d postgres

… and you will have a running instance of Postgres ready to go. Very cool!

Now you can run mix ecto.create in your terminal, and you should see the database migrated for you.

Woohoo!

Great! Now we can move on to the meat of this tutorial, making our API!

Generating the user resource

Phoenix comes with some incredibly useful resources for automatically generating resources. Not only does it come with the migration for your database, but it will also generate the structure of the resource, to give you an idea of how you should be thinking about your resources in the future.

Before we run our generator, let’s first talk about what we’re doing. Here is the snippet, to be run in the root directory of your app.

mix phx.gen.json Accounts User users first_name:string last_name:string email:string:unique username:string:unique password:string

In this snippet, we are using the generator for JSON responses. Accounts is the context of the resource. I highly encourage you to read the link, but in summary, contexts are ways to organize your resources according to their role in your application. Our User resource will help us perform CRUD operations for our users, which exists in our blanket context Accounts. If we wanted to do authentication later, that would also fall under the Accounts context. This will give us a really nice foundation for organizing our code, which will make it much easier to use and extend in the future.

In addition to that, we’re passing the singular and plural names of the generated resource, and ending with our desired attributes.

Now let’s run this!

As you can see, it has generated many files for our new resource. You will also see that it has additional steps for you to perform. Specifically, it wants you to add your new resource to your router. Let’s go ahead and do that now.

Make your lib/app_web/router.ex file matches the following block

defmodule AppWeb.Router do
use AppWeb, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
end
pipeline :api do
plug :accepts, ["json"]
end
scope "/api", AppWeb, as: :api do
pipe_through :api
scope "/v1", Api.V1, as: :v1 do
resources "/users", UserController
end
end
scope "/", AppWeb do
pipe_through :browser
get "/", PageController, :index
resources "/users", UserController, only: [:show]
end
end

Now, our router has a nested scope, with our user resource defined in the innermost one. This way, Phoenix knows where to go when someone navigates to /api/v1/users ! It is immediately obvious how easy this will be to begin adding more and more routes with this nested scope structure, as well as adding new versions later on.

Quick Addendum: Why do we need the browser pipe?

You may be wondering why we need the "/" scope at all, since we are creating an API. Well, if you try to run the server without this resource defined, you will receive any error about a user_path not defined.

This is because Phoenix comes with Path Helpers. Path Helpers are functions that are dynamically defined on the Router.Helpers module for your app (You can read more about Path Helpers here)

In user_controller.ex, you’ll see the user_path function the compiler is complaining about. This particular path helper resolves to /users. Try running phx.routes with and without that resource defined in the "/" scope, and you will see how the path will no longer be available.

Putting the files in their correct place

We are almost ready to run our server, but first we need to copy the generated user controller, since our app is now expecting it at api/v1/users. Right now, user_controller.ex lives at app_web/controllers/ . Let’s copy that bad boy to app_web/controllers/api/v1/user_controller.ex . You will need to create these folders yourself. Change the namespace of this controller as well from AppWeb.UserController to AppWeb.Api.V1.UserController .

Note the new namespace

We need to do the same thing for user_view.ex. Copy user_view.ex from app_web/views/user_view.ex to app_web/views/api/v1/user_view.ex. Also change it’s namespace from AppWeb.UserView to AppWeb.Api.V1.UserView.

Your app structure should now look like this.

Now let’s run phx.server ! Once you run that command, navigate to localhost:4000/api/v1/users

Quick Note: I am using Postman to interact with my API

Hurrah! Our API is working as expected! There is nothing in our database yet, so this route returns nothing for the moment.

Creating a user through the API

Now we have one more thing we need to do before we can consider this complete, we need to test and make sure that we can create new users through this API. Let’s take a look at the create method in user_controller.ex

It is expecting a parameter called ‘user’. For those who might be confused, it is expecting a JSON object with a key called ‘user’, and a JSON object associated with that key with all of the values we need to make a user. The structure will look like this…

{
"user": {
"first_name": "John",
"last_name": "Ezekiel",
"email_address": "test@email.com",
"username": "zeke8402",
"password": "test"
}
}

Let’s go ahead and try to post this to our API! In Postman, change the request type to POST and add the JSON to the body of the request, like so.

Now let’s submit……

:-)

Hooray! Now if we submit a GET request, we should get our new user back.

Excellent! You should be in a good spot now to begin branching off and making your own API!

Final Notes

This is what I have come up with after reading the Phoenix documentation, as well as the very excellent videos from Elixir Casts. My motivation was to use the new 1.3 phx.gen generators, and use the resulting output for my RESTful API. If I missed anything, or if you think there is a better way to do this, please let me know! I would very much like to hear it. I am by no means an expert in Phoenix, but I am incredibly impressed with the framework, and I hope this helps someone get off the ground more quickly than I did.

--

--