Server-side flow

The server-side flow works by sending your user to Podio to authorize. It's a four step process:

  1. You redirect your user to Podio for authorization
  2. Podio redirects back to your web app with an authorization code
  3. You use the authorization code to obtain an access token
  4. You use the access token for all API requests

The first step is to redirect your user to Podio's authorization endpoint, providing your client_id and a redirect_uri. The redirect_uri must be on the same domain as the domain you specified when you applied for your API Key. The endpoint you must redirect to is:

Note: Repeated Request and Response parameters will be discarded and only the value of last Request and Response parameter is considered

If the user is not logged in to Podio he will be asked to login. Then we will present a screen showing what the user is granting access to:

If the user for some reason denies access, the application is not authorized, and the OAuth flow will redirect the user back to the URL, passed in the redirect_uri parameter with these parameters:


After granting access the user will be redirected to the URL you passed in the redirect_uri parameter with an authorization code appended:


You must then use the authorization code to obtain an access token. To authenticate your app, you must pass the authorization code and your client_secret to our endpoint. In return you will receive an access token. Make a POST like this:

      HEADER:  "Content-Type: application/json"
        "grant_type": "authorization_code",
        "client_id": YOUR_APP_ID,
        "redirect_uri": YOUR_URL,
        "client_secret": YOUR_APP_SECRET,

If your app is successfully authenticated and the authorization code from the user is valid, the API will return the access token:

  "access_token": ACCESS_TOKEN,
  "token_type": "bearer",
  "expires_in": EXPIRES_IN,
  "refresh_token": REFRESH_TOKEN,
    "type": "user",
    "id": USER_ID

See Scopes & Permissions for details about the value of GRANTED_SCOPE_STRING

Example: Ruby Sinatra

The following code example is written in Ruby, using Sinatra and the OAuth2 gem:

require 'rubygems'
require 'sinatra'
require 'oauth2'
require 'json'

def podio_client
  client_id = 'YOUR_CLIENT_ID'
  client_secret = 'YOUR_CLIENT_SECRET', client_secret,
    :site => '',
    :authorize_path => '/oauth/authorize',
    :access_token_path => '/oauth/token/v2')

def redirect_uri(path = '/auth/podio/callback', query = nil)
  uri = URI.parse(request.url)
  uri.path  = path
  uri.query = query

get "/" do
  %(<h1>Podio OAuth2 sample</h1> <p><a href="/auth/podio">Try to authorize</a>.</p>)

# access this to request a token from Podio.
get '/auth/podio' do
  url = podio_client.web_server.authorize_url(:redirect_uri => redirect_uri)
  puts "Redirecting to URL: #{url.inspect}"
  redirect url

# If the user authorizes it, this request gets your access token
# and makes a successful api call.
get '/auth/podio/callback' do
    access_token = podio_client.web_server.get_access_token(params[:code], :redirect_uri => redirect_uri)
    "<p>Your OAuth access token: #{access_token.token}</p>"
  rescue OAuth2::HTTPError
    %(<p>Outdated ?code=#{params[:code]}:</p><p>#{$!}</p><p><a href="/auth/podio">Retry</a></p>)

Example: PHP Limonade

The following code example is written in PHP, using Limonade (see full source code):

require_once 'vendor/limonade.php';
require_once 'vendor/podio-php/PodioAPI.php';

function configure() {
  option('CLIENT_ID', 'YOUR_CLIENT_ID'); // Replace with your client ID
  option('CLIENT_SECRET', 'YOUR_CLIENT_SECRET'); // Replace with your client secret

  option('REDIRECT_URI', 'http://'.$_SERVER['HTTP_HOST'].url_for('authorize/callback'));

dispatch('/', 'root');
function root() {
  return render('<h1>Podio Authentication sample</h1><p><a href="'.option('CLIENT_ID').'&redirect_uri='.rawurlencode(option('REDIRECT_URI')).'">Try to authorize</a>.</p>');

dispatch('/authorize/callback', 'authorize');
function authorize() {
  try {
    Podio::setup(option('CLIENT_ID'), option('CLIENT_SECRET'));
    Podio::authenticate('authorization_code', array('code' => $_GET['code'], 'redirect_uri' => option('REDIRECT_URI')));
    $access_token = Podio::$oauth->access_token;
    return render("<p>Your access token is {$access_token}</p>");
  catch(PodioError $e) {
    return render("<p>There was an error. The API responded with the error type <b>{$e->body['error']}</b> and the message <b>{$e->body['error_description']}. <a href='".url_for('/')."'>Retry</a></p>");


Example: Ruby on Rails with Omniauth

The Rails sample application on Github demonstrates how to authenticate and read/write items to Podio.