Skip to main content
RapidDev - Software Development Agency
bubble-integrationsBubble API Connector

FedEx API

Connect Bubble to FedEx's REST API using a two-step OAuth 2.0 client credentials flow: first POST to `/oauth/token` to exchange your API key and secret for a 1-hour Bearer token, then use that token in subsequent tracking and shipping calls. Store the token in Bubble custom state and re-fetch before it expires. FedEx sandbox and production are completely separate environments — credentials from one will not work in the other.

What you'll learn

  • How to set up a two-step OAuth 2.0 client credentials flow in Bubble's API Connector
  • How to store and manage the FedEx Bearer token in Bubble custom state with expiry checking
  • How to build a workflow that auto-refreshes the token before it expires
  • How to navigate FedEx's deeply nested tracking response using Bubble's :get operator chain
  • How to configure FedEx sandbox vs. production environments with separate base URLs
  • How to batch up to 30 tracking numbers in a single FedEx API call to minimize WU usage
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Advanced19 min read2–3 hoursProductivityLast updated July 2026RapidDev Engineering Team
TL;DR

Connect Bubble to FedEx's REST API using a two-step OAuth 2.0 client credentials flow: first POST to `/oauth/token` to exchange your API key and secret for a 1-hour Bearer token, then use that token in subsequent tracking and shipping calls. Store the token in Bubble custom state and re-fetch before it expires. FedEx sandbox and production are completely separate environments — credentials from one will not work in the other.

Quick facts about this guide
FactValue
ToolFedEx API
CategoryProductivity
MethodBubble API Connector
DifficultyAdvanced
Time required2–3 hours
Last updatedJuly 2026

FedEx REST API + Bubble: direct carrier access with two-step OAuth

FedEx's modern REST API is the direct integration path for businesses that need FedEx-native features — Express international routing, FedEx Freight for large cargo, detailed scan events, and customs documentation — or that already have a FedEx contract with negotiated rates they want to apply programmatically.

The main complexity compared to simpler carrier APIs is FedEx's OAuth 2.0 client credentials flow. You don't simply add an API key to a header — you first exchange your API key and secret for a Bearer access token, then use that token in all subsequent calls. The token expires after exactly 1 hour, so your Bubble app must know when to request a fresh one.

In Bubble, this two-step flow becomes two API Connector calls: 'Fetch Token' and the operational call (tracking, rate quote, shipment creation). Between them, Bubble workflow logic stores the token in a custom state and checks its age before each use. The entire pattern runs server-side — Bubble's API Connector never exposes your API key, secret, or Bearer token to users' browsers.

FedEx also maintains completely isolated sandbox and production environments. Sandbox testing uses a different base URL (`apis-sandbox.fedex.com`) and separate credentials from developer.fedex.com. Live production uses `apis.fedex.com` and credentials tied to your FedEx account. A single character difference in the base URL means all calls fail silently with a 401 — the most common configuration mistake in FedEx integrations on Bubble.

Integration method

Bubble API Connector

Uses Bubble's API Connector with two separate calls: one to fetch a short-lived OAuth 2.0 Bearer token from FedEx, and a second for operational calls (tracking, rates, shipment creation) using that token dynamically.

Prerequisites

  • A FedEx developer account at developer.fedex.com — registration is free, but for production shipment creation you also need an active FedEx customer account number
  • A FedEx API project created in the developer portal with Tracking API and/or Ship API access — credentials (API Key and Secret Key) are generated per project
  • The API Connector plugin installed in your Bubble app (Plugins tab → Add plugins → search 'API Connector' by Bubble)
  • Understanding that FedEx sandbox and production are completely separate systems with different base URLs and different credentials — sandbox credentials will not work on production endpoints

Step-by-step guide

1

Register at developer.fedex.com and create an API project

Go to developer.fedex.com and click 'Log In' or 'Join FedEx Developer' to register. You'll need a FedEx account for registration — if you don't have a FedEx customer account, you can register for one during this process. Once logged in, go to 'My Projects' and click 'Create a Project.' Give the project a name (for example, 'Bubble App Integration'). Under 'APIs,' select the API products you need. For tracking: select 'Track API.' For rate quoting and label generation: also select 'Ship API' and 'Rates and Transit Times.' After creating the project, go to the project's settings. In the 'Production Credentials' section, you'll find your **API Key** and **Secret Key**. Copy both. In the 'Testing Credentials' section, copy your **Sandbox API Key** and **Sandbox Secret Key** — these are separate credentials for the sandbox environment. Important: FedEx sandbox tracking uses simulated tracking numbers documented in the developer portal. Real FedEx tracking numbers from live packages will NOT work in the sandbox — use the specific test tracking numbers provided in FedEx's developer documentation to test different status scenarios (in transit, exception, delivered). Plan for a potential 24–48 hour approval delay for full production API access. Sandbox access is typically instant.

Pro tip: Create two separate Bubble apps or use a Bubble development environment for sandbox testing and a production environment for live credentials. Never mix sandbox credentials with the production base URL or vice versa — calls will silently fail with 401.

Expected result: You have sandbox API Key and Secret Key from developer.fedex.com ready to configure in Bubble's API Connector. Your FedEx project has Track API access enabled.

2

Set up the token-fetch API Connector call

In your Bubble editor, click 'Plugins' → 'Add plugins' → search 'API Connector' (by Bubble) → Install. Click 'API Connector' in your plugins list, then 'Add another API.' Name it 'FedEx.' For the base URL, start with the sandbox: `https://apis-sandbox.fedex.com`. You'll change this to `https://apis.fedex.com` for production. Add your first call: click 'Add a call,' name it 'Fetch Token.' Set the method to POST and the path to `/oauth/token`. Set the body type to 'URL encoded form' (this is critical — FedEx's token endpoint requires `application/x-www-form-urlencoded`, not JSON). In the body fields, add: - `grant_type`: value `client_credentials` (static — no dynamic marker needed) - `client_id`: value `<your_sandbox_api_key>` — check the **'Private'** checkbox on this field - `client_secret`: value `<your_sandbox_secret_key>` — check the **'Private'** checkbox on this field Under 'Use as,' select 'Action.' Click 'Initialize call.' A successful response returns `access_token` (a long JWT string), `token_type` (bearer), `expires_in` (3600), and `scope`. Bubble will auto-detect these fields. If you see an error, verify the body type is URL-encoded form, not JSON — FedEx's token endpoint rejects JSON-encoded credentials.

fedex_fetch_token.json
1{
2 "api_name": "FedEx",
3 "base_url_sandbox": "https://apis-sandbox.fedex.com",
4 "base_url_production": "https://apis.fedex.com",
5 "calls": [
6 {
7 "name": "Fetch Token",
8 "method": "POST",
9 "path": "/oauth/token",
10 "body_type": "x-www-form-urlencoded",
11 "body": {
12 "grant_type": "client_credentials",
13 "client_id": "<private: sandbox_api_key>",
14 "client_secret": "<private: sandbox_secret_key>"
15 },
16 "use_as": "Action",
17 "response_fields": [
18 "access_token",
19 "token_type",
20 "expires_in",
21 "scope"
22 ]
23 }
24 ]
25}

Pro tip: The FedEx OAuth token endpoint specifically requires `application/x-www-form-urlencoded` encoding, not JSON. In Bubble's API Connector body type dropdown, select 'URL encoded form' — not 'JSON body.' Using JSON returns a 400 error with a generic bad request message.

Expected result: The 'Fetch Token' call initializes successfully and Bubble detects the access_token, token_type, and expires_in (3600) response fields. Your sandbox API credentials are stored as Private fields in the API Connector.

3

Add the tracking API call with a dynamic Bearer token

Now add the operational call. Click 'Add a call,' name it 'Track Shipment.' Set the method to POST and the path to `/track/v1/trackingnumbers`. Set the body type to 'JSON body.' The FedEx tracking request body structure is: Add a call-level header (not a shared header): key `Authorization`, value `Bearer <token>`. Mark this as a **dynamic** parameter — it will be filled in at workflow runtime with the stored access token. This is different from the Private static header pattern used for API keys — here the value changes with each token fetch. In Bubble's API Connector, you can make a header value dynamic by using the `<` and `>` markers: enter `Bearer <token>` where `token` is a named dynamic parameter. Set 'Use as' to 'Data.' The response structure is deeply nested: `output.completeTrackResults[0].trackResults[0].latestStatusDetail.description` for the current status, and `output.completeTrackResults[0].trackResults[0].dateAndTimes` (array) for scan timestamps. Click 'Initialize call' and provide a sandbox test tracking number from FedEx's documentation as the test value (and a placeholder Bearer token for the `token` parameter). Bubble will detect the deeply nested response fields. IMPORTANT after Initialize: the deeply nested structure means Bubble will detect the outer wrapper fields. Use the `:get` operator in workflows to navigate to inner fields: `result's output's completeTrackResults first item's trackResults first item's latestStatusDetail's description`.

fedex_track_shipment.json
1{
2 "call_name": "Track Shipment",
3 "method": "POST",
4 "path": "/track/v1/trackingnumbers",
5 "headers": [
6 {
7 "key": "Authorization",
8 "value": "Bearer <dynamic: access_token>",
9 "note": "Dynamic — filled from stored token at workflow runtime"
10 },
11 {
12 "key": "Content-Type",
13 "value": "application/json"
14 }
15 ],
16 "body": {
17 "trackingInfo": [
18 {
19 "trackingNumberInfo": {
20 "trackingNumber": "<dynamic: tracking_number>"
21 }
22 }
23 ],
24 "includeDetailedScans": true
25 },
26 "response_path_to_status": "output.completeTrackResults[0].trackResults[0].latestStatusDetail.description",
27 "response_path_to_events": "output.completeTrackResults[0].trackResults[0].scanEvents"
28}

Pro tip: For bulk tracking (up to 30 numbers in one call), add multiple objects to the `trackingInfo` array. This is far more efficient than 30 separate API calls and avoids rate limits. In Bubble, build the array by passing a comma-separated list of tracking numbers and splitting them in the workflow.

Expected result: The 'Track Shipment' call initializes successfully with a sandbox tracking number. Bubble detects the deeply nested response fields. The call accepts a dynamic `token` parameter for the Authorization header.

4

Build the token management workflow

The core complexity of the FedEx integration is managing the 1-hour token lifecycle. Here's how to implement it cleanly in Bubble. First, add two custom states to your main page (or to a reusable element if you need the token across multiple pages): name the first `fedex_token` (Text type) and the second `fedex_token_fetched_at` (Date type). Create a Bubble workflow named 'Ensure FedEx Token.' This workflow uses a conditional action: - Condition: `(Current date/time - Page's fedex_token_fetched_at) > 50 minutes` OR `Page's fedex_token is empty` - If true: Run API call 'FedEx — Fetch Token' → Set state `fedex_token` to `result's access_token` → Set state `fedex_token_fetched_at` to `Current date/time` - If false: do nothing (the cached token is still valid) Now create the 'Track Package' workflow triggered by your tracking button: 1. Run workflow 'Ensure FedEx Token' (this runs the conditional check and re-fetches only if needed) 2. Run API call 'FedEx — Track Shipment' with `token` parameter set to `Page's fedex_token` and `tracking_number` set to the Input field's value 3. Display the result This pattern ensures the token is always fresh without making unnecessary token-fetch calls on every button click. The 50-minute threshold (rather than 60) provides a safety buffer — a token fetched at 55 minutes remaining will still be valid for the operational call that follows.

fedex_token_workflow.json
1{
2 "custom_states": [
3 { "name": "fedex_token", "type": "text" },
4 { "name": "fedex_token_fetched_at", "type": "date" }
5 ],
6 "ensure_token_workflow": {
7 "condition": "(Current datetime - fedex_token_fetched_at) > 50 minutes OR fedex_token is empty",
8 "if_true": [
9 "Run API: FedEx Fetch Token",
10 "Set state fedex_token = result's access_token",
11 "Set state fedex_token_fetched_at = Current datetime"
12 ],
13 "if_false": "skip — cached token still valid"
14 },
15 "track_package_workflow": [
16 "Step 1: Run 'Ensure FedEx Token' workflow",
17 "Step 2: Run API: FedEx Track Shipment — token: Page's fedex_token, tracking_number: Input's value",
18 "Step 3: Display result fields in UI elements"
19 ]
20}

Pro tip: If your Bubble app has multiple pages that make FedEx calls, store the token and timestamp in App Data (a single-record data type) rather than page-level custom states. This way the token persists across page navigations within the same session.

Expected result: The 'Track Package' button click workflow correctly fetches a token if missing or expired, stores it in page state, then uses it for the tracking call. On subsequent clicks within 50 minutes, no redundant token fetch is made.

5

Parse the deeply nested FedEx tracking response

FedEx's tracking response is among the most deeply nested API responses you'll encounter — 5 to 6 levels of nesting to reach the data you need. Here's how to navigate it in Bubble's workflow editor. After the Track Shipment call, the result structure is: - `result's output` → tracking output object - `result's output's completeTrackResults` → array of tracking results (one per tracking number in bulk calls) - `result's output's completeTrackResults's first item` → the result for your tracking number - `result's output's completeTrackResults's first item's trackResults` → array (usually one item) - `result's output's completeTrackResults's first item's trackResults's first item's latestStatusDetail` → current status - `...latestStatusDetail's description` → human-readable status string (e.g., 'Delivered') - `...latestStatusDetail's statusByLocale` → localized status - `...trackResults's first item's dateAndTimes` → array of dates (actual delivery, scheduled delivery) - `...trackResults's first item's scanEvents` → array of scan events, each with `date`, `eventDescription`, and `scanLocation` For display: create a Repeating Group with data source as the `scanEvents` array from the API result (set data type to 'API result's scan event' — Bubble detects custom types from Initialize call). Inside the cell, bind Text elements to `Current cell's date`, `Current cell's eventDescription`, and `Current cell's scanLocation's city`. For the status badge: bind a Text element to the first item in the chain: `Get data from external API — Track Shipment's result's output's completeTrackResults's first item's trackResults's first item's latestStatusDetail's description`. Test each level of the chain individually in Bubble's expression editor — clicking through the chain step by step is much easier than typing the full path.

fedex_response_structure.json
1{
2 "response_navigation": {
3 "root": "result",
4 "level_1": "output",
5 "level_2": "completeTrackResults (array)",
6 "level_3": "[0] = first tracking number's result",
7 "level_4": "trackResults (array)",
8 "level_5": "[0]",
9 "current_status": "latestStatusDetail.description",
10 "delivery_dates": "dateAndTimes (array — filter by type 'ACTUAL_DELIVERY')",
11 "scan_history": "scanEvents (array)",
12 "scan_event_fields": [
13 "date",
14 "eventDescription",
15 "scanLocation.city",
16 "scanLocation.stateOrProvinceCode",
17 "scanLocation.countryCode"
18 ]
19 },
20 "bubble_expression_example": "result's output's completeTrackResults first item's trackResults first item's latestStatusDetail's description"
21}

Pro tip: RapidDev's team has built multiple FedEx tracking integrations in Bubble — the nested response parsing is the most time-consuming part. If you get stuck navigating the response chain, a free scoping call at rapidevelopers.com/contact can walk you through the exact Bubble expression for your specific use case.

Expected result: A Text element on the page shows the current FedEx shipment status (e.g., 'In FedEx possession'), and a Repeating Group shows the scan event timeline with dates, locations, and event descriptions from the FedEx API.

6

Switch from sandbox to production and set up Privacy rules

When your integration is working correctly in sandbox mode, switching to production requires two changes in Bubble's API Connector: 1. Change the base URL from `https://apis-sandbox.fedex.com` to `https://apis.fedex.com` 2. Update the `client_id` and `client_secret` in the 'Fetch Token' call from your sandbox credentials to your production API Key and Secret Key from developer.fedex.com After switching, always re-initialize the Fetch Token call with production credentials to confirm the connection. Click 'Initialize call' on the Fetch Token call — a successful response confirms your production credentials are working. IMPORTANT: after changing the base URL, you must also re-initialize the Track Shipment call (and any other operational calls) because the Initialize call configuration is tied to the base URL environment. Click through each call's 'Initialize call' with valid production test data. For Privacy rules on any FedEx tracking data saved to Bubble's database: go to Data tab → Privacy → click on your tracking data type (e.g., 'Shipment'). Add a rule: 'Current User' can view 'when this Shipment's customer = Current User.' Set 'Everyone else' to no permissions. Tracking data with customer names, addresses, and delivery status is personal data — Bubble's default open access must be restricted.

fedex_production_checklist.json
1{
2 "environment_switch_checklist": [
3 "1. Update base URL: apis-sandbox.fedex.com → apis.fedex.com",
4 "2. Update client_id in Fetch Token call to production API Key",
5 "3. Update client_secret in Fetch Token call to production Secret Key",
6 "4. Re-initialize Fetch Token call to confirm production credentials work",
7 "5. Re-initialize Track Shipment call with a real production tracking number",
8 "6. Clear any cached sandbox tokens from custom states",
9 "7. Test end-to-end with a real FedEx tracking number"
10 ]
11}

Pro tip: After switching to production, clear the `fedex_token` and `fedex_token_fetched_at` custom states by setting them to empty. This forces a fresh production token fetch on the next call, preventing any sandbox token from being used against the production endpoint.

Expected result: All FedEx API calls work against the production endpoint with live credentials. The token-fetch and tracking calls complete successfully with real FedEx data. Privacy rules restrict tracking record access to the relevant customer.

Common use cases

Shipment Tracking Dashboard for Customers

Build a Bubble portal where customers enter their FedEx tracking number and see a detailed timeline of scan events — from pickup through delivery — pulled live from the FedEx Tracking API. Each event shows the timestamp, location, and status description. This is more detailed and faster than directing customers to fedex.com to check their own packages.

Bubble Prompt

Build a Bubble page with a tracking number input field and a 'Track Package' button. When clicked, the workflow fetches a FedEx Bearer token (or uses the cached one if still valid), calls the FedEx tracking endpoint with the entered number, and displays each scan event in a timeline repeating group showing time, location city, and status description in chronological order.

Copy this prompt to try it in Bubble

Order Fulfillment Tracking Status Sync

Add automatic tracking status updates to your Bubble order management system. A scheduled Backend Workflow runs daily, loops through all unfulfilled orders with FedEx tracking numbers, calls the FedEx tracking API for each, and updates the order's delivery status field. When status changes to 'Delivered,' trigger a customer notification workflow.

Bubble Prompt

Create a Bubble scheduled workflow that runs every morning, searches for all orders where shipping_carrier = 'FedEx' and delivery_status is not 'Delivered,' calls the FedEx tracking API for each order's tracking number, updates the order's delivery_status field, and sends an in-app notification when an order's status becomes 'Delivered.'

Copy this prompt to try it in Bubble

Bulk Tracking Update for High-Volume Sellers

For e-commerce apps with many daily shipments, use FedEx's batch tracking capability to check up to 30 tracking numbers in a single API call. Build a Bubble 'Sync All Tracking' workflow that chunks unfulfilled orders into groups of 30, calls FedEx once per group, and updates all order statuses in bulk — minimizing API calls and WU consumption.

Bubble Prompt

Build a Bubble admin workflow triggered by a 'Sync Tracking' button that fetches all unfulfilled FedEx orders, groups their tracking numbers in batches of 30, calls the FedEx batch tracking endpoint once per group, and bulk-updates all order delivery statuses and latest scan descriptions in Bubble's database.

Copy this prompt to try it in Bubble

Troubleshooting

Fetch Token call returns a 401 or 'Invalid credentials' error

Cause: The most common cause is using sandbox credentials against the production base URL or vice versa. FedEx sandbox credentials are entirely separate from production credentials — they will not authenticate against the wrong environment. A secondary cause is submitting the body as JSON rather than URL-encoded form.

Solution: Verify the base URL matches the credentials: sandbox credentials (`apis-sandbox.fedex.com`) and production credentials (`apis.fedex.com`). Check the body type in Bubble's API Connector — it must be 'URL encoded form,' not 'JSON body.' Re-copy the API Key and Secret Key directly from developer.fedex.com for the correct environment (Testing vs. Production tabs) to rule out copy-paste errors.

Track Shipment call returns a 401 'The given access token is missing or invalid'

Cause: The Bearer token passed in the Authorization header is expired (tokens last 3,600 seconds / 1 hour), is empty because the token-fetch workflow hasn't run yet, or the token value was stored incorrectly in the custom state.

Solution: Add a console check: display the `fedex_token` custom state value in a temporary text element on the page to verify it's populated and recent. If empty, trigger the Fetch Token workflow manually. If populated but calls still fail, check whether more than 60 minutes have passed since the token was fetched — add the expiry-check logic described in Step 4 to ensure the token is refreshed before use.

Initialize call returns 'There was an issue setting up your call' on the Track Shipment call

Cause: The Initialize call requires a valid Bearer token AND a valid FedEx tracking number (sandbox test numbers for sandbox, real numbers for production). Providing a placeholder token or an invalid tracking number format causes the initialization to fail.

Solution: Run the Fetch Token Initialize call first to get a valid access_token. Copy this token value. Then use it as the test value for the `token` parameter in the Track Shipment Initialize call, along with a valid sandbox tracking number from developer.fedex.com's test documentation. The Initialize call needs real data to detect the response structure — it cannot succeed with placeholder values.

Tracking response fields show as 'arbitrary text' or are not navigable using :get

Cause: The Initialize call was run with an empty or error response, so Bubble didn't detect the nested field structure. Bubble stores the detected field schema from the Initialize call — if the initialization failed silently, the schema is empty.

Solution: Re-initialize the Track Shipment call with a valid token and tracking number that returns a full success response (including scan events). After a successful initialization with real tracking data, Bubble will correctly detect the nested response hierarchy including scanEvents, latestStatusDetail, and completeTrackResults arrays.

The integration worked for 1 hour then all tracking calls started returning 401

Cause: The FedEx Bearer token expired after 3,600 seconds. If the token-expiry-check workflow was not implemented, the app used the same initial token until it expired, then all calls failed.

Solution: Implement the token expiry check described in Step 4: before every operational API call, check whether `(Current datetime - fedex_token_fetched_at) > 50 minutes`. If true, run the Fetch Token call and update the stored token. This ensures the token is always refreshed before operational calls need it.

Best practices

  • Always check token age before making FedEx API calls. Use a 50-minute threshold (not 60) to give the operational call enough time to complete before the token actually expires. Store the fetch timestamp alongside the token.
  • Mark both `client_id` (API Key) and `client_secret` (Secret Key) as Private in Bubble's API Connector Fetch Token call. These credentials can generate tokens that authorize shipping charges to your FedEx account — treat them with the same care as payment credentials.
  • Keep sandbox and production entirely separate. Never use sandbox credentials in production or vice versa. Consider labeling your API Connector entry clearly ('FedEx Sandbox' vs. 'FedEx Production') and using Bubble's development vs. live environments to separate them.
  • For bulk tracking (multiple orders), use FedEx's ability to accept up to 30 tracking numbers in a single POST /track/v1/trackingnumbers call. Send a JSON array in `trackingInfo` rather than making individual calls per order — this reduces WU consumption by up to 30x for batch updates.
  • Store FedEx tracking data in Bubble's database with proper Privacy rules restricting access to the customer whose order it belongs to. Tracking data includes delivery addresses and customer names — Bubble's default 'anyone can view' setting exposes this data unnecessarily.
  • Add a loading state to your tracking UI. FedEx's token fetch + tracking call may take 2–4 seconds combined. Show a spinner or disabled button state between the button click and the result display to prevent double-clicks that would trigger multiple API calls.
  • For Backend Workflow-based FedEx webhook notifications (real-time delivery alerts), a paid Bubble plan is required. Free-plan apps can achieve similar results with a daily scheduled tracking sync — less real-time but sufficient for most use cases.

Alternatives

Frequently asked questions

Why does the FedEx integration require two API calls instead of one?

FedEx uses OAuth 2.0 client credentials authentication. You cannot include your API credentials directly in operational calls — you must first exchange them for a Bearer token via POST /oauth/token. The token expires after 1 hour. This two-step model is a security design: if a Bearer token is ever intercepted, it expires in an hour; your API Key and Secret are only used server-to-server during token fetch and never appear in tracking or shipping requests.

What is the difference between FedEx sandbox and production environments?

FedEx sandbox (apis-sandbox.fedex.com) and production (apis.fedex.com) are completely separate systems with separate credentials, separate test tracking numbers, and simulated carrier behavior. Sandbox tokens won't work on production endpoints and vice versa. Always develop against sandbox first, and explicitly switch both the base URL and credentials when moving to production. There is no shortcut — they are entirely different environments.

Do I need a paid Bubble plan for the FedEx API integration?

The core tracking and rate-quoting integration — API Connector with token management via custom states — works on Bubble's free plan. A paid Bubble plan is required only if you want to receive real-time FedEx webhook notifications for shipment status changes, which requires Backend Workflows (API Workflows). Free-plan apps can poll the tracking endpoint on demand or on a fixed schedule using page-level workflows.

Can I get FedEx rates and create shipment labels from Bubble?

Yes, but it requires a FedEx account number and Ship API access in your developer project, plus activating your FedEx account for API-based shipping. Once configured, use POST /rate/v1/rates/quotes for rate queries and POST /ship/v1/shipments for label creation. Both calls follow the same two-step token-fetch pattern. Note that label creation charges your FedEx account — test thoroughly in sandbox mode before going live.

Why do FedEx sandbox test tracking numbers behave differently from real ones?

FedEx's sandbox uses predefined test tracking numbers from developer.fedex.com that cycle through scripted status sequences (in transit, out for delivery, delivered, exception). These are not real packages — they simulate the full lifecycle with canned data. Real tracking numbers from live shipments will not return data in the sandbox environment. When you switch to production, use real FedEx tracking numbers and the responses will reflect actual shipment scan events.

How do I handle the 1-hour token expiry in a Bubble app with multiple users?

For a single-user admin tool, storing the token in page custom state works fine — it's reset on each page load and refreshed when expired. For multi-user apps where different users make FedEx calls, store the token and fetch timestamp in a single App Data record (a custom data type with exactly one record). All users share the cached token and it's refreshed when any user's call detects it has expired. This avoids unnecessary token fetches across users.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Integrations are where projects stall

We wire Bubble integrations like this one every week — auth, webhooks, edge cases included. Fixed-price builds from $13K, delivered in 6–10 weeks.

Talk to an integration engineer

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.