Your First Versioned API with Phoenix Framework
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,
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
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.
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.
lib/app_web/router.ex file matches the following block
defmodule AppWeb.Router do
use AppWeb, :router
pipeline :browser do
plug :accepts, ["html"]
pipeline :api do
plug :accepts, ["json"]
scope "/api", AppWeb, as: :api do
scope "/v1", Api.V1, as: :v1 do
resources "/users", UserController
scope "/", AppWeb do
get "/", PageController, :index
resources "/users", UserController, only: [:show]
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)
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
We need to do the same thing for
app_web/views/api/v1/user_view.ex. Also change it’s namespace from
Your app structure should now look like this.
Now let’s run
phx.server ! Once you run that command, navigate to
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
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…
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!
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.