# Trello

- Tool: Bubble
- Difficulty: Beginner
- Time required: 1–2 hours
- Last updated: July 2026

## TL;DR

Connect Bubble to Trello using the API Connector with Trello's unique URL query-parameter auth — `?key=...&token=...` instead of an Authorization header. Mark both parameters Private in the shared API group settings so they never reach the browser. Full API access is free; no paid Trello plan required. Build Kanban boards, create cards from Bubble forms, and move cards between lists with Bubble workflows.

## Render a Live Kanban Board in Bubble — Free API, Beginner-Friendly Auth

Trello is the outlier in the productivity API landscape: while most tools use an Authorization header (Bearer token, Basic auth), Trello authenticates with `?key=...&token=...` appended to every URL. This catches first-timers off guard — adding an Authorization header to Trello calls returns 401 with no indication that the correct method is URL parameters, not headers.

The upside: Trello's API is completely free for all plan levels. There are no paid-plan gates on API access, no OAuth application approval process, and no support-contact friction. You register a Power-Up at trello.com/power-ups/admin (takes about five minutes), copy the API key, then generate a user token by visiting a pre-built consent URL. Both values go into Bubble's API Connector as Private shared query parameters — they are automatically appended to every call in the group without you having to include them per-request.

Bubble's API Connector runs all calls server-side, so Trello's key and token never appear in the browser's network panel even though they are technically URL parameters. The Private flag in Bubble's shared parameter settings ensures they are excluded from client-side exposure.

Core flows this tutorial covers: GET /boards/{boardId}/lists to render the column structure of a Kanban board in a Repeating Group, GET /lists/{listId}/cards to populate each column's cards, POST /cards to create a new card from a Bubble form, and PATCH /cards/{cardId} to update a card's name, description, or due date. Moving cards between lists — the classic Kanban drag-and-drop — uses PUT /cards/{cardId}/idList.

Rate limit awareness: Trello allows 300 requests per 10 seconds per API key, and 100 requests per 10 seconds per user token. Loading a board with many lists and immediately fetching cards for all lists in parallel can trigger the per-token limit on large boards. Stagger card-fetch calls and avoid live-updating the Repeating Group on every UI interaction to stay within limits and minimize Workload Unit (WU) consumption.

## Before you start

- A Trello account (free plan is sufficient — Trello API access is available on all plans)
- A registered Trello Power-Up — create one at trello.com/power-ups/admin to obtain your API key
- A Trello user token generated via the OAuth consent URL (instructions in Step 1)
- Your Trello board ID — visible in the board URL (https://trello.com/b/{boardId}/board-name)
- The API Connector plugin installed in your Bubble app (Plugins tab → Add plugins → search 'API Connector' by Bubble)

## Step-by-step guide

### 1. Register a Trello Power-Up and Generate API Key and User Token

Trello API credentials come in two parts: an API key (tied to a Power-Up you register) and a user token (a per-user OAuth consent that grants read/write access to that user's boards). Both are required on every API call.

To get your API key, go to https://trello.com/power-ups/admin in your browser. Click 'New Power-Up'. Fill in a name (e.g., 'My Bubble App'), choose your workspace, and accept the terms. After creating the Power-Up, click on it and navigate to the 'API Key' tab. You will see your API key — copy it. This key is associated with your Trello developer account.

To generate the user token, construct the following URL in your browser, replacing {apiKey} with the key you just copied:

https://trello.com/1/authorize?expiration=never&scope=read,write&name=BubbleApp&key={apiKey}&response_type=token

Paste this URL into your browser and press Enter. Trello shows a consent screen listing the permissions (read and write access). Click 'Allow'. The resulting page shows a long token string — copy it immediately. This is your user token.

Important: the token generated with `expiration=never` does not expire automatically, but it can be revoked by going to your Trello account settings → Applications. Keep this token secure — it grants write access to your Trello boards. For production apps where each user authenticates with their own Trello account (not a shared service account), you will need to implement the full OAuth flow via a Bubble Backend Workflow instead of a single pre-generated token. That multi-user pattern is covered in the FAQ section.

With your API key and user token in hand, you are ready to configure Bubble's API Connector.

```
// Authorization URL template — paste into browser, replace {apiKey}
https://trello.com/1/authorize?expiration=never&scope=read,write&name=BubbleApp&key={apiKey}&response_type=token

// After clicking Allow, copy the token from the resulting page
// Example token format: a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456
```

**Expected result:** You have a Trello API key (shorter string, starts with letters/numbers) and a user token (longer string, 64 characters). Both are copied and ready to paste into Bubble.

### 2. Configure the API Connector with Private Shared Query Parameters

Open your Bubble app editor and navigate to the Plugins tab in the left sidebar. If you have not installed the API Connector yet, click 'Add plugins', search for 'API Connector' (the one by Bubble), and install it. Once installed, click 'API Connector' in your plugin list to open the configuration panel.

Click 'Add another API' to create a new API group. Name it 'Trello'. This is where you will configure the shared parameters that automatically apply to every call in this group.

In the 'Shared headers' section, do NOT add an Authorization header — Trello does not use one. Instead, scroll down to 'Shared parameters' and add two entries:

1. Parameter name: key — Value: paste your Trello API key — tick the 'Private' checkbox
2. Parameter name: token — Value: paste your user token — tick the 'Private' checkbox

Making both parameters Private ensures they are excluded from client-side exposure even though they are technically URL query parameters. Bubble's server-side API Connector appends them to every outgoing request without including them in any browser-visible network call.

Leave 'Authentication' set to 'None' — Trello's auth is entirely handled by the query parameters you just added. Do not enable any built-in auth type; doing so will add an unexpected Authorization header that conflicts with Trello's auth pattern.

With the shared parameters saved, you can now add individual API calls to this group. All calls will automatically include ?key=...&token=... on the request URL.

```
{
  "api_group": "Trello",
  "base_url": "https://api.trello.com/1",
  "authentication": "None",
  "shared_parameters": [
    { "name": "key", "value": "<your API key>", "private": true },
    { "name": "token", "value": "<your user token>", "private": true }
  ],
  "note": "Do NOT add an Authorization header — Trello uses URL parameters only"
}
```

**Expected result:** The Trello API group is saved in the API Connector with 'key' and 'token' as Private shared parameters and no Authorization header. The group is ready to have individual calls added.

### 3. Add Read Calls — Boards, Lists, and Cards

Inside the Trello API group, create three 'Use as Data' calls to fetch the structure and content of a Trello board.

**Call 1: Get Lists on Board**
- Click '+ Add another call' inside the Trello group
- Name: Get Lists
- Method: GET
- URL: https://api.trello.com/1/boards/{boardId}/lists
- Add a path/query parameter: boardId = your actual board ID (from the board URL at trello.com/b/{boardId}/board-name)
- Use as: Data
- Click 'Initialize call' — Bubble will fire a real GET request using your Private key and token. You should see a response with the lists array containing id, name, and pos fields for each list.

**Call 2: Get Cards in a List**
- Name: Get Cards
- Method: GET
- URL: https://api.trello.com/1/lists/{listId}/cards
- Add a query parameter: listId = <dynamic> (leave blank for initialization, enter a real list ID for the initialize call)
- Use as: Data
- Click 'Initialize call' — enter a real listId from one of your board's lists (copy it from the Get Lists response). You should see cards with id, name, desc, due, idMembers, and idList fields.

**Call 3: Get Single Card (optional but useful)**
- Name: Get Card
- Method: GET
- URL: https://api.trello.com/1/cards/{cardId}
- Use as: Data
- Initialize with a real card ID

For the Kanban board UI, set Get Lists as the data source for an outer Repeating Group and Get Cards (with listId = outer group's current cell's 'id') as the data source for an inner Repeating Group inside each list cell. This creates the nested board/list/card structure.

Note on rate limits: loading a board with many lists and fetching cards for all lists simultaneously can approach the 100 req/10s per-token limit on large boards. For boards with more than 10 lists, consider loading cards on demand (e.g., when a list is clicked) rather than on page load.

```
{
  "Get_Lists": {
    "method": "GET",
    "url": "https://api.trello.com/1/boards/{boardId}/lists",
    "query_params": {
      "boardId": "<your board ID>"
    },
    "use_as": "Data"
  },
  "Get_Cards": {
    "method": "GET",
    "url": "https://api.trello.com/1/lists/{listId}/cards",
    "query_params": {
      "listId": "<dynamic list ID from parent Repeating Group>"
    },
    "use_as": "Data"
  }
}
```

**Expected result:** Get Lists initializes successfully and shows list id, name, and pos in detected fields. Get Cards initializes with a real listId and shows card id, name, desc, due, and idList in detected fields. Both calls return 200 with real data from your Trello board.

### 4. Add Write Calls — Create Card, Update Card, Move Card

With the read calls working, add three Action calls for write operations. Action calls are triggered by Bubble workflow events (button clicks, form submissions, condition changes) rather than bound to UI elements as data sources.

**Call 1: Create Card**
- Name: Create Card
- Method: POST
- URL: https://api.trello.com/1/cards
- Use as: Action
- Body (JSON): include idList (required — the destination list), name (required — card title), desc (optional — card description), due (optional — ISO 8601 date string for due date), idMembers (optional — array of member IDs)
- Initialize: click 'Initialize call' with a real idList and name value. Trello will create a real card during initialization — you can delete it from Trello after confirming the response.

**Call 2: Update Card**
- Name: Update Card
- Method: PATCH
- URL: https://api.trello.com/1/cards/{cardId}
- Use as: Action
- Body (JSON): any updatable fields — name, desc, due, closed (true/false for archiving)
- Initialize with a real cardId

**Call 3: Move Card to List**
- Name: Move Card
- Method: PUT
- URL: https://api.trello.com/1/cards/{cardId}/idList
- Use as: Action
- Body: value = {targetListId}
- Initialize with a real cardId and a real target listId

To wire Create Card to a Bubble form: create a workflow triggered by a button click → 'Plugins → Trello - Create Card' → map idList to a hidden field containing the target list ID, map name to the form's card-name input, map desc to the description textarea. After the action, optionally refresh the card Repeating Group.

For Move Card, trigger it from a 'Status changed' dropdown or a 'Mark as Done' button. Pass the current card's id as cardId and the destination list's id as the target. RapidDev's team has built hundreds of Bubble apps with integrations like this — if your Kanban board logic is getting complex (multiple boards, member assignments, custom fields), get a free scoping call at rapidevelopers.com/contact.

```
{
  "Create_Card": {
    "method": "POST",
    "url": "https://api.trello.com/1/cards",
    "body": {
      "idList": "<dynamic list ID>",
      "name": "<dynamic card title>",
      "desc": "<dynamic description>",
      "due": "<dynamic ISO 8601 date or empty>"
    },
    "use_as": "Action"
  },
  "Update_Card": {
    "method": "PATCH",
    "url": "https://api.trello.com/1/cards/{cardId}",
    "body": {
      "name": "<dynamic new title>",
      "desc": "<dynamic new description>"
    },
    "use_as": "Action"
  },
  "Move_Card": {
    "method": "PUT",
    "url": "https://api.trello.com/1/cards/{cardId}/idList",
    "body": {
      "value": "<dynamic target list ID>"
    },
    "use_as": "Action"
  }
}
```

**Expected result:** Create Card, Update Card, and Move Card Action calls initialize successfully and show the card object (id, name, idList, desc) in the response fields. Each call returns 200 with the updated or created card data.

### 5. Build the Kanban Board Page and Wire Up Workflows

Create a new Bubble page named 'kanban-board'. The page will render Trello board data using a horizontal outer Repeating Group for lists and a vertical inner Repeating Group for cards within each list.

Outer Repeating Group (Lists):
- Layout: Horizontal scroll
- Type of Content: 'Get Lists result'
- Data source: 'Get Lists' API Connector call with your boardId
- Inside each cell: add a Text element for the list name (current cell's 'name' field) and an inner Repeating Group for cards

Inner Repeating Group (Cards per List):
- Layout: Full list (vertical)
- Type of Content: 'Get Cards result'
- Data source: 'Get Cards' with listId = outer Repeating Group current cell's 'id'
- Inside each cell: Text elements for card name, desc, and due date; a 'Move to Done' button if applicable

'Add Card' workflow: Add a Multi-line Input and a Button labeled 'Add Card' to the page. Create a workflow triggered by the button click: Action → Plugins → Trello - Create Card → set idList to a fixed list ID (e.g., your 'To Do' list ID) and name to the Multi-line Input's value. After the action, add a 'Refresh data' step for the inner Repeating Group to show the new card.

'Move Card' workflow: Inside the inner Repeating Group card cell, add a Button labeled 'Mark as Done'. Create a workflow: Action → Plugins → Trello - Move Card → set cardId to current card's 'id' and the target list ID to your 'Done' list ID. Optionally add an 'Only when' condition: this card's idList is not already the Done list ID.

To display the board on page load, set the outer Repeating Group's data source directly to 'Get Lists' — no 'Do a search for' needed since you are pulling from the API Connector, not Bubble's database. The inner Repeating Group automatically fetches cards when each list cell renders.

For data privacy on any Bubble Data Type that stores Trello card data locally, go to Data tab → Privacy and add a rule ensuring only authenticated users (or the correct role) can view synced card records.

**Expected result:** The kanban-board page loads and renders all Trello lists as horizontal columns, each populated with the correct cards from that list. The 'Add Card' input creates a new Trello card visible in Trello and in the Repeating Group after refresh. The 'Mark as Done' button moves the card to the Done column in Trello.

### 6. Test, Debug, and Handle Rate Limits

Before sharing the board with your team, run a full test in Bubble's debugger and verify both read and write flows.

Open the Bubble debugger (Preview → 'Debug mode' toggle in the top bar). Load the kanban-board page and watch the Step-by-step panel:

1. Confirm Get Lists fires on page load and returns your board's list names. If the Repeating Group shows 'No items', check that the boardId parameter in the Get Lists call matches your actual board ID (visible in the Trello URL).
2. Confirm Get Cards fires for each list cell and returns cards. On a large board with many lists, watch for any 429 errors in the Logs tab (Settings → Logs → Workflow logs) — this indicates you are hitting the 100 requests/10s per-token limit.
3. Test the 'Add Card' workflow: type a card name, click the button, and verify the card appears in Trello immediately. The Repeating Group should refresh to show the new card.
4. Test the 'Mark as Done' workflow: click the button on a card and verify it moves to the Done list in Trello.

Rate limit management: if you have a large board (more than 10 lists with many cards), avoid fetching all cards on page load simultaneously. Instead, load cards lazily — only when the user scrolls to or clicks on a specific list. Use a Custom State to track which list is 'expanded' and only fire the Get Cards call for that list.

For production boards with real team data, consider storing card data locally in a Bubble Data Type (synced on a schedule or on demand) and only calling Trello's API for write operations and initial syncs. This reduces WU consumption and eliminates rate-limit exposure on pages with high traffic.

If the API Connector calls return 'There was an issue setting up your call' after setup, re-initialize each call by clicking 'Initialize call' in the API Connector editor — this is required whenever the response shape changes (e.g., new custom fields added to Trello cards) or after a significant gap in development.

**Expected result:** Full debugger run shows no errors. Get Lists and Get Cards calls return 200 with real data. Add Card creates a visible Trello card. Move Card successfully relocates the card in Trello. No 401, 403, or 429 errors appear in the Workflow logs during normal usage.

## Best practices

- Use Shared query parameters (marked Private) at the API group level rather than adding key and token to each individual call. This central configuration means you only need to update credentials in one place if you ever rotate the API key or token.
- Never add an Authorization header to Trello API calls — Trello's auth is URL-parameter-based only. An Authorization header causes 401 errors and is the single most common setup mistake for developers familiar with Bearer-token APIs.
- For internal tools where a single Trello account is the source of truth, a pre-generated 'never-expiring' token is acceptable. For apps where each user manages their own Trello boards, implement the full OAuth flow in a Bubble Backend Workflow so tokens are per-user and revocation of one token does not break the entire app.
- Stagger card-fetch calls for large boards to stay under the 100 requests per 10 seconds per-token rate limit. Load cards on demand (when a list is clicked or expanded) rather than fetching all cards for all lists simultaneously on page load.
- Re-initialize API Connector calls whenever the response shape changes — for example, after adding custom fields to Trello cards. Bubble caches the detected field schema from the last initialization; outdated schemas cause new fields to be invisible in the visual editor.
- Add a 'Refresh board data' button to the Kanban page rather than live-updating the Repeating Groups on every user interaction. Polling-heavy patterns consume WU and can hit rate limits; explicit refresh gives users control and keeps API calls purposeful.
- If you store Trello card data in a Bubble Data Type (for local querying or offline display), add privacy rules to that Data Type immediately — go to Data tab → Privacy → Add a rule ensuring only logged-in users (or the correct team role) can search or read card records. Never leave the default 'Everyone can see all fields' rule in place for data synced from a project management tool.
- Monitor WU consumption in Logs tab → Workflow logs during development. Each API Connector call consumes WU. A Kanban board with 10 lists × 20 cards per list loads 11 API calls per page visit — multiply by your expected daily active users to estimate monthly WU costs and plan your Bubble plan tier accordingly.

## Use cases

### Live Kanban Board View Inside Bubble

Render a Trello board directly inside a Bubble page using Repeating Groups for columns and nested Repeating Groups for cards. Team members can view real-time task status without switching to Trello, while all project management still lives in Trello as the source of truth.

Prompt example:

```
Show me how to build a Bubble page that renders a Trello board — one outer Repeating Group for lists and an inner Repeating Group for cards in each list, using the Trello API Connector calls.
```

### Bubble Form → New Trello Card

Let team members or clients submit a Bubble form that automatically creates a Trello card in a specific list. Useful for intake forms, bug reports, or feature requests where you want captured data to flow directly into your Trello workflow without manual copy-paste.

Prompt example:

```
How do I wire a Bubble form submission to a POST /cards API Connector call that creates a new card in a specific Trello list, with the form's fields mapped to the card's name, description, and due date?
```

### Status Update Automation via Card Move

Build a Bubble workflow where a button click (e.g., 'Mark as Done') moves a Trello card from one list to another using PUT /cards/{cardId}/idList. This lets your Bubble app control Trello card status as users progress through steps in your app.

Prompt example:

```
Create a Bubble workflow that triggers when a user clicks 'Approve', calls PUT /cards/{cardId}/idList to move the corresponding Trello card to the 'Approved' list, and updates a Bubble Data Type field to reflect the new status.
```

## Troubleshooting

### All Trello API calls return 401 Unauthorized even though credentials look correct

Cause: The most common cause is adding an Authorization header to the API Connector group. Trello does NOT use an Authorization header — the API key and token must be URL query parameters named exactly 'key' and 'token'. A second cause is a typo in the parameter names (e.g., 'api_key' instead of 'key').

Solution: Open the API Connector → Trello group. Check the Shared headers section — if any Authorization header exists, delete it. Check the Shared parameters section: confirm there is a parameter named exactly 'key' (not 'api_key' or 'apiKey') and another named exactly 'token'. Verify both have Private checked. Reinitialize a call to confirm the 401 is resolved.

### 'There was an issue setting up your call' appears on API Connector initialization

Cause: The API Connector Initialize call needs a real successful response from Trello to detect field types. This error appears when the boardId or listId used during initialization is invalid, when the token has been revoked in Trello's account settings, or when there are no items in the list (empty list returns an empty array which Bubble cannot use to detect field types).

Solution: Use a board ID and list ID that definitely have data — open Trello, pick a list with at least one card, and copy the list ID from a Get Lists response or the Trello URL. For the board ID, copy the alphanumeric string from the URL segment after /b/. If the token may have been revoked, regenerate it using the authorization URL from Step 1 and update the Shared parameter value.

### Inner Repeating Group (cards) shows empty or displays the same cards in every list column

Cause: The inner Repeating Group's listId dynamic parameter is set to a static value (or to the wrong dynamic source) instead of the outer Repeating Group's current cell's 'id' field.

Solution: Click on the inner Repeating Group's data source configuration. In the 'Get Cards' call parameters, click the listId field and select 'Repeating Group Trello lists's current cell's id' (the exact name depends on how you named your outer Repeating Group). This dynamic reference changes per list cell, causing each column to fetch its own cards. A static list ID causes all columns to show the same list's cards.

### 429 Too Many Requests errors appear in the Workflow logs when loading a large board

Cause: Loading a Trello board with many lists and fetching cards for all lists simultaneously can exceed the 100 requests per 10 seconds per user token limit. Each list triggers one Get Cards call; 15+ lists loading in parallel can hit the limit instantly.

Solution: Change the card-loading strategy from 'on page load for all lists' to 'on demand per list'. Remove the inner Repeating Group's data source and instead add a button or click event on each list cell that sets a Custom State (selected_list_id) to that list's id, and only populate a single card Repeating Group with the selected list's cards. Alternatively, use Bubble's 'Schedule API Workflow' action with a 100-millisecond pause between each card-fetch call to stagger requests.

### The 'never-expiring' user token stops working and all calls return 401

Cause: The Trello user token generated with expiration=never does not expire by schedule, but it can be manually revoked by going to Trello account settings → Applications and removing the app. This can happen accidentally when cleaning up connected apps, or a team member with account access may have revoked it.

Solution: Generate a new token by visiting the authorization URL again (https://trello.com/1/authorize?expiration=never&scope=read,write&name=BubbleApp&key={apiKey}&response_type=token). Click Allow and copy the new token. Update the 'token' shared parameter value in the Trello API Connector group. For production apps used by multiple users, implement a Backend Workflow OAuth flow so each user authenticates independently — their tokens are not affected if the service-account token is revoked.

## Frequently asked questions

### Do I need a paid Trello plan to use the API?

No. Trello's REST API is fully accessible on the free plan — there are no API restrictions tied to paid plan tiers. You can create boards, manage cards, and move cards between lists using the free Trello plan. Paid plans (Premium and Enterprise) add features like advanced views, admin controls, and higher attachment limits, but none of these affect API access.

### Why does Trello use URL query parameters for auth instead of an Authorization header?

Trello's API was designed before Bearer token auth became the standard REST convention. The key+token URL parameter pattern was Trello's original OAuth 1.0-inspired authentication approach and has been maintained for backward compatibility. In Bubble, this is handled safely by adding key and token as Private shared query parameters in the API Connector group — Bubble's server-side execution means they never appear in the browser's network panel despite being URL parameters.

### How do I implement per-user Trello auth for a multi-user Bubble app?

Instead of a single pre-generated token, each user must go through Trello's OAuth consent flow. In Bubble, build a Backend Workflow that redirects the user to Trello's authorization URL with your API key, receives the token callback, stores the token in the user's Bubble record (marked Private), and uses that user-specific token on all subsequent Trello API calls. This requires a paid Bubble plan for Backend Workflows. For internal tools where all users share one Trello account, a single pre-generated token is sufficient.

### What should I do if my 'never-expiring' token stops working?

Tokens generated with expiration=never do not expire on a schedule but can be manually revoked. Go to your Trello account settings → Applications and check whether your app is still listed. If it has been removed, generate a new token by visiting the authorization URL from Step 1 and update the 'token' Shared parameter in your Bubble API Connector. To prevent token revocation from breaking your production app, consider using a dedicated Trello service account separate from any individual team member's personal account.

### Can I receive real-time updates when Trello cards change (webhooks)?

Yes, but it requires a paid Bubble plan. Trello supports webhooks — you register a Backend Workflow endpoint URL with Trello's POST /webhooks endpoint, and Trello sends a POST request to that URL whenever a card, list, or board changes. The Backend Workflow receives the payload, extracts the relevant fields, and can update Bubble Data Types or trigger other workflows. Without Backend Workflows (Bubble Free plan), you must poll GET /lists/{listId}/cards periodically to detect changes.

### How do I find a Trello board ID, list ID, or card ID for use in API calls?

Board ID: open any Trello board and look at the URL — the 8-character alphanumeric string after /b/ is the board ID (e.g., trello.com/b/aBcDeFgH/my-board → ID is aBcDeFgH). List ID and Card ID: make a GET /boards/{boardId}/lists call in Bubble's API Connector (or use the initialized data response) — each list object includes an 'id' field. Card IDs appear in GET /lists/{listId}/cards responses. You can also append .json to a Trello card URL to see its ID in the browser.

---

Source: https://www.rapidevelopers.com/bubble-integrations/trello
© RapidDev — https://www.rapidevelopers.com/bubble-integrations/trello
