> ## Documentation Index
> Fetch the complete documentation index at: https://bundleup.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Rails Quickstart

> Connect your first integration with a Ruby on Rails app using BundleUp.

This guide builds the [Quickstart](/docs/quickstart) flow into a Rails app with the BundleUp Ruby SDK. A user clicks **Connect GitHub**, authorizes on GitHub, and lands back in your app, which exchanges the one-time `code` for a `connection_id` and lists their repositories through the [Unified API](/docs/guides/unified/overview).

```mermaid theme={null}
sequenceDiagram
    participant U as End user
    participant App as Your Rails app
    participant BA as BundleUp Auth
    participant GH as GitHub

    U->>App: Click "Connect GitHub"
    App-->>U: Redirect to auth.bundleup.io/authorize
    U->>BA: client_id, integration_id, redirect_uri
    BA-->>U: Redirect to GitHub consent
    U->>GH: Approve
    GH-->>BA: Authorization code
    BA-->>U: Redirect to /callback?code=...
    U->>App: GET /callback?code=...
    App->>BA: POST /connection (API key, code)
    BA-->>App: connection_id
    App->>App: List repos via the Unified API
```

## Prerequisites

* Ruby 2.7+ and Rails installed.
* In the BundleUp dashboard, complete steps 1 to 3 of the [Quickstart](/docs/quickstart):
  * a **GitHub integration** with the identifier `github`,
  * `http://localhost:3000/callback` registered under **Auth → Redirect URIs**,
  * an **API key**, and your **Client ID** from the **Auth** page.

## Step 1: Create a new Rails app

Create a fresh Rails project:

```shellscript theme={null}
# using Rails CLI
rails new bundleup_rails
cd bundleup_rails

# ensure the app’s database is ready
rails db:create
```

This scaffolds a Rails app you can run locally.

## Step 2: Install the BundleUp Ruby SDK

Add the `bundleup-sdk` gem to your Gemfile:

```ruby theme={null}
# Gemfile
gem 'bundleup-sdk', require: 'bundleup'
```

Then install dependencies:

```shellscript theme={null}
bundle install
```

This makes the BundleUp client available to your Rails app.

## Step 3: Configure environment variables

Create a `.env` file (or use your preferred secrets manager) with:

```shellscript .env lines theme={null}
# server-side only
BUNDLEUP_API_KEY=your_api_key_here

# used for redirect
BUNDLEUP_CLIENT_ID=your_client_id_here
BUNDLEUP_INTEGRATION_ID=github

# Must exactly match a redirect URI registered in your BundleUp dashboard
BUNDLEUP_REDIRECT_URI=http://localhost:3000/callback
```

Make sure your Rails app loads these variables (for example via [dotenv-rails](https://rubygems.org/gems/dotenv-rails) or [Rails credentials](https://edgeguides.rubyonrails.org/security.html#environmental-security)).

## Step 4: Add routes

In `config/routes.rb`, define the home and callback endpoints:

```ruby config/routes.rb lines theme={null}
Rails.application.routes.draw do
  root "home#index"
  get "/callback", to: "home#callback"
end
```

## Step 5: Create the authorization link

In `app/controllers/home_controller.rb`, add:

```ruby app/controllers/home_controller.rb lines theme={null}
class HomeController < ApplicationController
  def index
    @auth_url = bundleup.auth.build_authorization_url(
      client_id: ENV["BUNDLEUP_CLIENT_ID"],
      integration_id: ENV["BUNDLEUP_INTEGRATION_ID"],
      redirect_uri: ENV["BUNDLEUP_REDIRECT_URI"]
    )
  end

  private

  def bundleup
    @bundleup ||= BundleUp::Client.new(ENV["BUNDLEUP_API_KEY"])
  end
end
```

Then create a simple view.

```ruby app/views/home/index.html.erb lines theme={null}
<%= link_to "Connect GitHub", @auth_url %>
```

This link sends the user to BundleUp’s auth server to authorize the integration.

## Step 6: Handle the callback and fetch data

After authorization, BundleUp redirects back to `/callback` with a one-time `code`. Your server exchanges it, using your API key, for a `connection_id`. The code expires after 5 minutes and can only be used once.

Add a `callback` action to `HomeController`:

```ruby app/controllers/home_controller.rb lines theme={null}
class HomeController < ApplicationController
  def index
    @auth_url = bundleup.auth.build_authorization_url(
      client_id: ENV["BUNDLEUP_CLIENT_ID"],
      integration_id: ENV["BUNDLEUP_INTEGRATION_ID"],
      redirect_uri: ENV["BUNDLEUP_REDIRECT_URI"]
    )
  end

  def callback
    if params[:error] || params[:code].blank?
      @error = params[:error_description] || "Missing code"
      return
    end

    # Exchange the one-time code for the connection (server-side only)
    connection = bundleup.auth.get_connection_from_code(
      code: params[:code],
      redirect_uri: ENV["BUNDLEUP_REDIRECT_URI"]
    )

    # example: fetch GitHub repos
    @repos = bundleup.unify(connection["connection_id"]).git.repos["data"]
  end

  private

  def bundleup
    @bundleup ||= BundleUp::Client.new(ENV["BUNDLEUP_API_KEY"])
  end
end
```

<Note>
  `redirect_uri` must be exactly the same value you used to start the flow. BundleUp rejects the exchange otherwise.
</Note>

Then create `app/views/home/callback.html.erb`:

```ruby app/views/home/callback.html.erb lines theme={null}
<% if @error %>
  <p>Error: <%= @error %></p>
<% else %>
  <h2>Repositories</h2>
  <ul>
    <% @repos.each do |repo| %>
      <li><%= repo["full_name"] %></li>
    <% end %>
  </ul>
<% end %>
```

Now, after a successful authorization redirect, you exchange the code for a `connection_id` and use it to fetch a Unified API resource with the Ruby SDK.

## Step 7: Run your application

Start the Rails server:

```shellscript theme={null}
rails server
```

Visit [http://localhost:3000](http://localhost:3000), click **Connect GitHub**, authorize the app, and then you’ll see data fetched through BundleUp.

## Next steps

* **Store the `connection_id`** against the signed-in user in your database, and reuse it. Don’t send the user through the flow again.
* **Pass a `state` value** when you build the authorization URL and check it in the callback, to protect against CSRF. See [Connecting user accounts](/docs/guides/auth/authorization-flow#protect-the-flow-with-state).
* **Pass an `external_id`** (your user ID) so you can find connections by user later.
* **Call the provider directly** through the [Proxy](/docs/guides/proxy/overview) when you need something the Unified API doesn’t cover.
* See the full [Ruby SDK reference](/docs/sdks/ruby).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.