> ## 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.

# Django Quickstart

> Connect your first integration with a Django app using the BundleUp Python SDK.

This guide builds the [Quickstart](/docs/quickstart) flow into a Django app with the BundleUp Python 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 Django 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

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

## Step 1: Create a Django project

If you don't already have a Django project:

```shellscript theme={null}
# create and activate a virtual environment
python -m venv .venv
source .venv/bin/activate

# install Django
pip install Django

# create a new project
django-admin startproject bundleup_django
cd bundleup_django

# create an app
python manage.py startapp core
```

## Step 2: Install the BundleUp Python SDK

Install the official BundleUp SDK from PyPI:

```shellscript theme={null}
pip install bundleup-sdk
```

This package lets your Django server use the BundleUp Unified API to fetch data after a user has authorized an integration.

## Step 3: Configure Django settings

Add Django view URLs and your environment configuration:

1. Create a `.env` file in your project root 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:8000/callback
```

2. Load these environment variables in `settings.py` (you can use [python-dotenv](https://pypi.org/project/python-dotenv/) or your own loader).
3. In `bundleup_django/urls.py`, add routes:

```shellscript bundleup_django/urls.py lines theme={null}
from django.urls import path
from core import views

urlpatterns = [
    path("", views.home, name="home"),
    path("callback", views.callback, name="callback"),
]
```

## Step 4: Create the authorization link

In `core/views.py`, add a view that builds the BundleUp authorization URL:

```python core/views.py lines theme={null}
import os

from django.shortcuts import render
from bundleup import BundleUp

client = BundleUp(os.getenv("BUNDLEUP_API_KEY"))


def home(request):
    url = client.auth.build_authorization_url(
        client_id=os.getenv("BUNDLEUP_CLIENT_ID"),
        integration_id=os.getenv("BUNDLEUP_INTEGRATION_ID"),
        redirect_uri=os.getenv("BUNDLEUP_REDIRECT_URI"),
    )

    return render(request, "home.html", {"auth_url": url})
```

Create a simple template `core/templates/home.html` with:

```html core/templates/home.html lines theme={null}
<a href="{{ auth_url }}">Connect GitHub</a>
```

Clicking this link sends users to authorize GitHub, and then they're redirected back to `/callback`.

## Step 5: Handle the callback and fetch data

When BundleUp redirects back to `/callback`, it includes a one-time `code` query parameter. 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 the callback view to `core/views.py`:

```python core/views.py lines theme={null}
def callback(request):
    code = request.GET.get("code")
    if request.GET.get("error") or not code:
        error = request.GET.get("error_description", "Missing code")
        return render(request, "callback.html", {"error": error})

    # Exchange the one-time code for the connection (server-side only)
    connection = client.auth.get_connection_from_code(
        code=code,
        redirect_uri=os.getenv("BUNDLEUP_REDIRECT_URI"),
    )

    # Example: fetch GitHub repos via the Unified API
    repos = client.unify(connection["connection_id"]).git.repos()

    return render(request, "callback.html", {"repos": repos["data"]})
```

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

And in `core/templates/callback.html`:

```python core/templates/callback.html lines theme={null}
{% if error %}
<p>Error: {{ error }}</p>
{% else %}
<h2>Your Repositories</h2>
<ul>
  {% for repo in repos %}
    <li>{{ repo.full_name }}</li>
  {% endfor %}
</ul>
{% endif %}
```

**What’s happening here**

* The `code` proves the redirect came from a flow you started. On its own it is useless without your API key
* `connection_id` ties a user + integration together
* The Python SDK then makes authenticated calls using that connection
* You can fetch repositories, calendar events, files, contacts, etc., depending on the integration

## Step 6: Run your development server

Start the Django server:

```shellscript theme={null}
python manage.py runserver
```

Visit [http://localhost:8000](http://localhost:8000), click **Connect GitHub**, authorize, and you’ll see a list of repositories.

## 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 [Python SDK reference](/docs/sdks/python).


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