Connecting Bubble to eBay requires handling two token types: Application tokens (client credentials) for public product Browse API access, and User tokens (authorization-code OAuth) for seller Sell and Fulfillment APIs. Both expire in 2 hours — without a Backend Workflow token-refresh strategy that stores access tokens in a Bubble Data Thing, your integration silently fails mid-session. All tokens live in a Private Authorization header inside the API Connector.
| Fact | Value |
|---|---|
| Tool | eBay API |
| Category | E-commerce |
| Method | Bubble API Connector |
| Difficulty | Advanced |
| Time required | 3–5 hours |
| Last updated | July 2026 |
eBay's two-token system — the mistake that breaks every beginner's integration
Most guides treat eBay as a simple API key integration. It is not. eBay has two completely separate token types that look identical in the Authorization header but grant access to entirely different API surfaces:
**Application tokens** (client credentials grant) are obtained by your eBay Developer app exchanging its App ID and Cert ID for a token — no user involvement. These work ONLY with the Browse API (`/buy/browse/v1/`), which covers public product search and item details. You cannot use an Application token to access any Sell or Fulfillment endpoint. If you try, eBay returns 403 with no clear explanation — beginners spend hours debugging assuming their credentials are wrong.
**User tokens** (authorization-code grant) require an eBay seller to visit eBay's OAuth consent screen, grant your app specific permissions, and complete the OAuth handshake. The resulting token unlocks the Sell API (`/sell/inventory/v1/`, `/sell/listing/v1/`) and Fulfillment API (`/sell/fulfillment/v1/`) for that seller's account.
Both token types expire after exactly 2 hours. In Bubble, where there is no native cron scheduler on the free plan, the solution is a 'RefreshEbayToken' Backend Workflow triggered on every page load that checks the stored expiry timestamp in a 'EbayToken' Data Thing. If the token expires within 5 minutes, the workflow exchanges the stored refresh token for a fresh access token before any API call runs.
Bubble's API Connector keeps all of this server-side — the Authorization header marked Private means no token ever reaches the browser.
Integration method
Bubble API Connector with an Authorization Bearer header marked Private, hitting eBay's REST API family; OAuth token management handled via a Backend Workflow that stores and refreshes tokens in a Bubble Data Thing.
Prerequisites
- A free eBay Developer Program account at developer.ebay.com (separate from a regular eBay account)
- An eBay Developer Application created in the developer portal — collect the App ID (Client ID) and Cert ID (Client Secret)
- The API Connector plugin installed in your Bubble app (Plugins tab → Add plugins → search 'API Connector' → Install)
- A Bubble paid plan (Starter or above) for Backend Workflows — required for the OAuth user-token flow and token refresh logic
- For Sell/Fulfillment APIs: an active eBay seller account to complete the OAuth consent flow during testing
Step-by-step guide
Register your eBay Developer application and collect credentials
Go to developer.ebay.com and sign in with your eBay account (or create a free Developer Program account). In the developer portal, navigate to 'My Account' → 'Application Access Keys.' Click 'Create a Keyset' if you don't have one, or use an existing application's keyset. eBay provides two environments: Sandbox (for testing with fake data) and Production (for real eBay data). Start with Sandbox. For each environment, eBay generates three credentials — you need two: - **App ID (Client ID)**: identifies your application - **Cert ID (Client Secret)**: used to obtain Application tokens via client credentials grant You will also need the **RuName (eBay Redirect URL name)** for the User token flow. Go to 'User Tokens' in the developer portal → 'Get a Token from eBay via Your Application' → generate a RuName and set your redirect URI to your Bubble app's page URL (e.g., `https://yourapp.bubbleapps.io/ebay-callback`). Note that the OAuth consent URL endpoint and the token exchange endpoint differ between Sandbox and Production. Sandbox uses `https://auth.sandbox.ebay.com/oauth2/authorize` and `https://api.sandbox.ebay.com/identity/v1/oauth2/token`. Production uses `https://auth.ebay.com/oauth2/authorize` and `https://api.ebay.com/identity/v1/oauth2/token`. In this guide, we use the Production endpoints; substitute Sandbox equivalents during testing.
1// eBay credentials you need:2// App ID (Client ID): AppID-abc123def456...3// Cert ID (Client Secret): CertID-abc123def456...4// RuName (for User token OAuth): YourApp-YourApp-ProductN-abc12356// API base URLs:7// Browse API: https://api.ebay.com/buy/browse/v18// Sell Inventory: https://api.ebay.com/sell/inventory/v19// Sell Fulfillment: https://api.ebay.com/sell/fulfillment/v110// Token endpoint: https://api.ebay.com/identity/v1/oauth2/token1112// OAuth consent URL (User token flow):13// https://auth.ebay.com/oauth2/authorize14// ?client_id={AppID}15// &redirect_uri={RuName}16// &response_type=code17// &scope=https://api.ebay.com/oauth/api_scope/sell.inventory18// %20https://api.ebay.com/oauth/api_scope/sell.fulfillmentPro tip: eBay's Developer Program application is separate from your eBay buyer/seller account. You can have a developer account with no eBay listings at all. Production API access is available immediately for Browse API (public data); Sell and Fulfillment API access may require completing eBay's Application Check process for higher rate limits.
Expected result: You have an eBay Developer application with App ID, Cert ID, and a RuName configured with your Bubble callback URL.
Create the EbayToken Data Thing and set up token storage
Before building API calls, set up the data structure that will hold your eBay access tokens. In Bubble's Data tab, click 'New type' and create a type called 'EbayToken' with these fields: - `access_token` (text) — the current Bearer token - `refresh_token` (text) — the long-lived refresh token (for User token flow only; 18-month TTL) - `token_expiry` (date) — when the access token expires (2 hours from issuance) - `token_type` (text) — either 'application' or 'user' - `user_id` (text) — eBay seller's user ID (for User token rows only) This design allows one row for the Application token (for Browse API) and one row per seller for User tokens (for Sell/Fulfillment APIs). Next, go to the Data tab → Privacy and add a privacy rule for 'EbayToken': set 'Everyone else' to deny all access. Only the Bubble app's Backend Workflows should read and write token records — no frontend user should ever access this data type directly. Also create a Backend Workflow called 'RefreshApplicationToken' (you'll configure it in the next step). This workflow will run on page load for any page that needs Browse API calls, check whether the stored Application token is within 5 minutes of expiry, and exchange credentials for a fresh token if needed.
1// EbayToken Data Thing fields:2// access_token (text)3// refresh_token (text)4// token_expiry (date)5// token_type (text) -- "application" or "user"6// user_id (text) -- seller's eBay user ID (user tokens only)78// Privacy rule for EbayToken:9// Everyone else: No access to all fields10// Backend Workflows: full access via server-side operations1112// Workflow logic for token check:13// If EbayToken's token_expiry is before Current date/time + 5 minutes14// → run RefreshApplicationToken (or RefreshUserToken) Backend Workflow15// Else16// → proceed with existing access_tokenPro tip: Design your EbayToken type to have exactly ONE Application token row and optionally multiple User token rows (one per seller). When refreshing the Application token, search for EbayToken where token_type is 'application' and modify that single row. For User tokens, search where user_id matches the current eBay seller.
Expected result: The EbayToken Data Thing is created with all required fields, privacy rules deny public access, and the data type is ready to store both Application and User tokens.
Obtain an Application token and configure the API Connector for Browse API
Application tokens use the OAuth 2.0 client credentials grant — your Bubble app exchanges its App ID and Cert ID for a token without any user involvement. This is the token used for all Browse API calls (public product search). In Bubble's Backend Workflows section (visible after enabling the Workflow API in Settings → API), create a workflow called 'FetchApplicationToken.' This workflow makes a POST call to eBay's token endpoint. In the workflow, add a 'Plugins → API Connector' action pointing to a call you're about to configure. In Plugins → API Connector, click 'Add another API' and name it 'eBay Auth.' Add a call named 'Get Application Token.' Set: - Method: POST - URL: `https://api.ebay.com/identity/v1/oauth2/token` - Header: `Authorization: Basic [base64(AppID:CertID)]` — mark Private - Header: `Content-Type: application/x-www-form-urlencoded` - Body: form-encoded with `grant_type=client_credentials&scope=https://api.ebay.com/oauth/api_scope` Click Initialize call — eBay returns a JSON response with `access_token`, `expires_in` (seconds), and `token_type`. Bubble auto-detects the response fields. Back in the FetchApplicationToken Backend Workflow, after the API call action, add a 'Create/modify Thing' action to upsert the EbayToken record: set access_token to the API call's `access_token` result, token_expiry to 'Current date/time + expires_in seconds' (use Bubble's ':plus seconds' operator), and token_type to 'application.' Now create the main eBay API Connector for Browse API calls. Click 'Add another API' and name it 'eBay API.' Set a shared header `Authorization: Bearer [dynamic_access_token]` — this token value will be fetched from the EbayToken Data Thing at workflow run time. Also add `X-EBAY-C-MARKETPLACE-ID: EBAY_US` as a shared header. Add a call for product search: GET `https://api.ebay.com/buy/browse/v1/item_summary/search` with parameters `q` (text, dynamic), `limit` (text, default '20'), and `offset` (text, default '0'). Initialize with a real product search query.
1// eBay Auth → Get Application Token2// Method: POST3// URL: https://api.ebay.com/identity/v1/oauth2/token4//5// Headers:6// Authorization: Basic <base64(AppID:CertID)> // mark Private7// Content-Type: application/x-www-form-urlencoded8//9// Body (form-encoded):10// grant_type=client_credentials11// &scope=https://api.ebay.com/oauth/api_scope1213// Successful response:14// {15// "access_token": "v^1.1#i^1#p^3#I^3#r^0#f^0#t^H4sI...",16// "expires_in": 7200,17// "token_type": "Application Access Token"18// }1920// eBay API → Browse Product Search21// Method: GET22// URL: https://api.ebay.com/buy/browse/v1/item_summary/search23//24// Shared Headers:25// Authorization: Bearer <dynamic: EbayToken's access_token> // mark Private26// X-EBAY-C-MARKETPLACE-ID: EBAY_US27//28// Parameters:29// q: <dynamic> -- search keyword30// limit: 20 -- results per page31// offset: 0 -- pagination offsetPro tip: The Base64 encoding for the Basic Authorization header combines App ID and Cert ID as 'AppID:CertID' and encodes the whole string. In Bubble, you cannot compute Base64 natively in a workflow — encode this string manually using a tool like base64encode.org, then paste the encoded result into the header value and mark it Private. This static value doesn't change until you rotate your credentials.
Expected result: The 'Get Application Token' call initializes successfully, returning an access_token and expires_in value. The EbayToken Data Thing stores the token. The product search call initializes with real product results from the Browse API.
Build the OAuth consent flow for User tokens (Sell and Fulfillment APIs)
Seller API access requires a User token — an eBay seller must authorize your app via eBay's OAuth consent screen. This is a multi-step flow that requires a Backend Workflow on a Bubble paid plan. The flow works as follows: your Bubble app redirects the seller's browser to eBay's authorization URL. After the seller approves, eBay redirects back to your Bubble callback page with a one-time `code` parameter in the URL. A Backend Workflow then exchanges that code for access and refresh tokens. **Step 1 — Build the redirect URL.** On the page where sellers initiate the connection, add a 'Go to external website' action that constructs this URL: ``` https://auth.ebay.com/oauth2/authorize ?client_id={YourAppID} &redirect_uri={YourRuName} &response_type=code &scope=https://api.ebay.com/oauth/api_scope/sell.inventory https://api.ebay.com/oauth/api_scope/sell.fulfillment https://api.ebay.com/oauth/api_scope/sell.account ``` Note: scope values must be space-separated and URL-encoded (%20) in the final URL. **Step 2 — Create the callback page.** Create a Bubble page at the URL path you registered as your RuName redirect (e.g., `/ebay-callback`). On page load, read the `code` URL parameter using Bubble's 'Get data from page URL' operator. **Step 3 — Exchange code for tokens.** In the API Connector, create a 'Get User Token' call: POST to `https://api.ebay.com/identity/v1/oauth2/token` with the same Basic Auth header as the Application token call, body: `grant_type=authorization_code&code={code_from_url}&redirect_uri={RuName}`. On the callback page load, trigger a Backend Workflow that runs this API call and saves the resulting `access_token` and `refresh_token` to a new EbayToken row with token_type='user' and user_id set from eBay's response or a subsequent API call to `/sell/account/v1/privilege`.
1// Step 1: Redirect URL (build as dynamic text in Bubble's 'Go to external website' action):2https://auth.ebay.com/oauth2/authorize3 ?client_id=YourAppID-abc1234 &redirect_uri=YourApp-YourApp-ProductN-abc1235 &response_type=code6 &scope=https%3A%2F%2Fapi.ebay.com%2Foauth%2Fapi_scope%2Fsell.inventory7 %20https%3A%2F%2Fapi.ebay.com%2Foauth%2Fapi_scope%2Fsell.fulfillment89// Step 3: eBay Auth → Get User Token10// Method: POST11// URL: https://api.ebay.com/identity/v1/oauth2/token12//13// Headers:14// Authorization: Basic <base64(AppID:CertID)> // mark Private15// Content-Type: application/x-www-form-urlencoded16//17// Body (form-encoded):18// grant_type=authorization_code19// &code=<dynamic: code from URL parameter>20// &redirect_uri=YourApp-YourApp-ProductN-abc1232122// Successful response:23// {24// "access_token": "v^1.1#i^1#r^1#I^3...",25// "expires_in": 7200,26// "refresh_token": "v^1.1#i^1#r^1#I^3...",27// "refresh_token_expires_in": 4730400028// }Pro tip: eBay's refresh token lasts 18 months (47,304,000 seconds). Store it securely in the EbayToken Data Thing with the refresh_token field. When an access token expires, exchange the refresh token for a new access token using the 'refresh_token' grant_type — you do NOT need to re-run the full OAuth consent flow unless the refresh token itself expires or the seller revokes access.
Expected result: After a seller completes the eBay OAuth consent screen and is redirected back to your Bubble app, the callback page triggers the token exchange, and a new EbayToken row appears in the Bubble Data tab with a valid access_token and refresh_token for that seller.
Build the token refresh Backend Workflow and add it to page loads
Because eBay tokens expire every 2 hours, every page that makes eBay API calls needs to verify the stored token is valid before using it. In Bubble, the cleanest approach is a 'RefreshEbayToken' Backend Workflow that runs on page load and refreshes the token if needed. In the Backend Workflows section, create a workflow called 'CheckAndRefreshToken.' Add a 'Only when' condition: 'EbayToken's first item's token_expiry < Current date/time + 5 minutes.' When this condition is true, the workflow runs the token refresh. For Application tokens (Browse API): add an API call action to run the 'Get Application Token' call you built in Step 3, then a 'Make changes to Thing' action to update the existing EbayToken row with the new access_token and updated token_expiry. For User tokens (Sell/Fulfillment): add an API call to a 'Refresh User Token' connector call — POST to `https://api.ebay.com/identity/v1/oauth2/token` with body `grant_type=refresh_token&refresh_token={stored_refresh_token}&scope={same scopes}`. Update the EbayToken row with the new access_token and token_expiry. On each page that needs eBay API data, add a 'Page is loaded' trigger workflow with a single action: 'Schedule API Workflow → CheckAndRefreshToken' at 'Current date/time.' This runs server-side before any Repeating Groups load their data. In your data-display workflows and elements, reference the access_token dynamically: in the API Connector call's Authorization header dynamic value, use 'Search for EbayToken where token_type is application first item's access_token.' This ensures each call uses the current token from the database, not a stale value cached at page load.
1// Backend Workflow: CheckAndRefreshToken2// Condition: EbayToken's first item (type='application') token_expiry < Current date/time + 5 minutes3//4// Action 1: API Connector → eBay Auth → Get Application Token5// Action 2: Make changes to EbayToken (where token_type='application')6// access_token: result of step 1's access_token7// token_expiry: Current date/time + 7200 seconds (2 hours)89// User token refresh call config:10// Method: POST11// URL: https://api.ebay.com/identity/v1/oauth2/token12//13// Headers:14// Authorization: Basic <base64(AppID:CertID)> // mark Private15// Content-Type: application/x-www-form-urlencoded16//17// Body:18// grant_type=refresh_token19// &refresh_token=<dynamic: EbayToken (type='user') refresh_token>20// &scope=https://api.ebay.com/oauth/api_scope/sell.inventory21// %20https://api.ebay.com/oauth/api_scope/sell.fulfillment2223// Page load workflow:24// Trigger: Page is loaded25// Action: Schedule API Workflow → CheckAndRefreshToken (at Current date/time)Pro tip: Use Bubble's 'Schedule API Workflow' for the page-load trigger, not a direct API Connector call — this runs the refresh as a server-side Backend Workflow, which means the token is already updated in the database before your Repeating Group's data source is evaluated. If you trigger it client-side, there can be a race condition where the Repeating Group loads with a stale token.
Expected result: On page load, the CheckAndRefreshToken workflow runs and updates the EbayToken Data Thing if the current token is near expiry. API calls to eBay subsequently use the fresh access_token from the database. No mid-session 401 errors from expired tokens.
Build API calls for orders and listings, and handle nested eBay response data
With token management in place, build the specific eBay API calls your app needs. The most common patterns are order retrieval (Fulfillment API) and inventory management (Sell Inventory API). **Orders call:** In the eBay API Connector, add a call named 'Get Orders.' Set method GET, URL `https://api.ebay.com/sell/fulfillment/v1/order`. Add parameters: `filter` (text, dynamic) — this uses eBay's filter syntax, for example `filter=creationdate:[2025-01-01T00:00:00.000Z..]` to get orders after a date, and `limit` (text, default '50'). Initialize with real filter values. eBay returns an `orders` array; each order has nested `lineItems` (array), `fulfillmentStartInstructions` (array with shipping address), and `pricingSummary` objects. In Bubble's Initialize call response mapping, expand nested fields carefully. To display individual line items, you may need to create a 'LineItem' Data Thing and populate it from the order response using a 'Create a list of Things' action in a Backend Workflow — Bubble's Repeating Groups cannot directly iterate over nested JSON arrays without flattening them first. **Listings call:** Add a call named 'Get Inventory Items.' Set method GET, URL `https://api.ebay.com/sell/inventory/v1/inventory_item`. Add parameters `limit` (default '25') and `offset` (dynamic). Initialize — eBay returns an `inventoryItems` array with nested `product` and `availability` objects. For bulk operations (updating prices on many listings), use Bubble's 'Schedule API Workflow on a list' pattern rather than a loop inside a single workflow. Select the EbayToken (or a list of listing SKUs stored in a Data Thing) as the list, and for each item, schedule a 'UpdateListingPrice' Backend Workflow. This avoids Bubble's 30-second workflow timeout on large catalogs. RapidDev's team has built seller-management dashboards with exactly this pattern — if you need a scoping call for your specific use case, reach out at rapidevelopers.com/contact.
1// eBay API → Get Orders2// Method: GET3// URL: https://api.ebay.com/sell/fulfillment/v1/order4//5// Shared Headers (on eBay API group):6// Authorization: Bearer <dynamic: EbayToken's access_token> // mark Private7// X-EBAY-C-MARKETPLACE-ID: EBAY_US8//9// Parameters:10// filter: creationdate:[2025-01-01T00:00:00.000Z..] // dynamic date filter11// limit: 5012// offset: 0 // for pagination1314// Sample response structure:15// {16// "orders": [17// {18// "orderId": "12-34567-89012",19// "creationDate": "2026-01-15T14:32:00.000Z",20// "orderFulfillmentStatus": "NOT_STARTED",21// "buyer": { "username": "buyer123", "taxAddress": {...} },22// "lineItems": [23// { "title": "Product Name", "quantity": 2, "lineItemCost": { "value": "29.99", "currency": "USD" } }24// ],25// "pricingSummary": { "priceSubtotal": { "value": "59.98", "currency": "USD" } },26// "fulfillmentStartInstructions": [27// { "shippingStep": { "shipTo": { "fullName": "John Doe", "contactAddress": {...} } } }28// ]29// }30// ],31// "total": 4732// }Pro tip: eBay's order filter parameter uses a proprietary syntax with square brackets: `filter=creationdate:[2025-01-01T00:00:00.000Z..]`. When adding this as a URL parameter in Bubble's API Connector, add it as a single parameter named `filter` with the bracket-syntax value. Bubble URL-encodes the brackets automatically when making the call — do not pre-encode them in the Bubble parameter value field, or they will be double-encoded.
Expected result: The Get Orders call initializes successfully and returns an orders array. In a Repeating Group bound to this call, each cell displays order ID, buyer username, and total amount. The Initialize call response shows all nested fields that Bubble has auto-detected for mapping.
Common use cases
eBay product search and catalog import
Build a Bubble app that lets users search eBay's product catalog using the Browse API, displaying results in a Repeating Group with item titles, prices, images, and seller ratings. No seller account needed — Application tokens cover this entirely. Import selected products into a Bubble Data Thing to build a curated storefront or price comparison tool.
Using the eBay Browse API call configured in Bubble's API Connector, when a user clicks Search, run the GET /buy/browse/v1/item_summary/search call with the user's search term in the q parameter and display the itemSummaries array in a Repeating Group showing title, price.value, image.imageUrl, and seller.feedbackScore.
Copy this prompt to try it in Bubble
Seller order management dashboard
Build a custom operations dashboard for eBay sellers that pulls open orders from the Fulfillment API, displays shipping deadlines, and marks orders as shipped with tracking numbers — all from a Bubble interface more flexible than eBay's own seller hub. Requires User token OAuth flow.
After the OAuth consent flow stores the seller's User token in the EbayToken Data Thing, load orders via GET /sell/fulfillment/v1/order with filter=orderfulfillmentstatus:{NOT_STARTED|IN_PROGRESS} and display each order's orderId, buyer.username, lineItems, and pricingSummary in a sortable Repeating Group.
Copy this prompt to try it in Bubble
Automated listing management for sellers
Allow sellers to create, update, and publish eBay listings through a Bubble-built interface. Pull existing inventory from the Sell Inventory API, let sellers update prices or quantities, and push changes back to eBay — without requiring eBay Seller Hub access.
Use GET /sell/inventory/v1/inventory_item to load the seller's current listings into a Bubble Repeating Group. When a seller updates a price in the group, trigger a POST to /sell/inventory/v1/inventory_item/{sku}/offer with the updated price object and display the response status.
Copy this prompt to try it in Bubble
Troubleshooting
eBay API returns 403 'Insufficient permissions' when calling /sell/... or /sell/fulfillment/... endpoints
Cause: You are using an Application token (client credentials grant) on a Sell or Fulfillment API endpoint. Application tokens only have access to the Browse API (public product data). Sell and Fulfillment APIs require a User token obtained via the authorization-code OAuth flow with a seller's consent.
Solution: Check which token is stored in your EbayToken Data Thing — look at the token_type field. If it says 'application,' you need to complete the full OAuth seller consent flow (Step 4 in this guide) to obtain a User token with the correct sell.inventory and sell.fulfillment scopes. Verify your token has the required scopes by decoding it at jwt.io and checking the 'scp' claim.
API Connector Initialize call returns 'There was an issue setting up your call' — no response detected
Cause: The Initialize call needs a real successful response to detect the response schema. If eBay returns an error (401, 400, or 403), Bubble cannot detect any fields. Common causes: the Application token in the Authorization header has expired (tokens last 2 hours), or the Basic Auth encoding for the token endpoint is incorrect.
Solution: First, manually fetch a fresh Application token: run the 'Get Application Token' Backend Workflow and check that it stores a new access_token in the EbayToken Data Thing. Then use that fresh token in the Initialize call. For the token endpoint call, verify the Basic Auth header is Base64('AppID:CertID') — make sure you are encoding the combined string 'AppID:CertID' not just the App ID alone.
eBay API calls work at first but silently fail mid-session — Bubble workflows run but return empty data
Cause: The access token has expired (2-hour TTL) and no refresh logic is running. Bubble treats an expired-token 401 response as a soft error and may not surface it visually — the workflow completes but with no data.
Solution: Implement the CheckAndRefreshToken Backend Workflow from Step 5 and verify it runs on every page load. Check Bubble's Logs tab → Workflow logs to see if the token refresh is triggering. Also verify that the API Connector's Authorization header references the EbayToken Data Thing's access_token dynamically, not a hardcoded token value pasted during setup.
Token exchange returns 'invalid_grant' when exchanging the authorization code for a User token
Cause: eBay authorization codes expire after a few minutes and are single-use. If the callback page takes too long to load, or if you try to reuse the code, the exchange fails. Also common: the redirect_uri in the exchange request does not exactly match the RuName registered in the developer portal.
Solution: Ensure your Bubble callback page triggers the token exchange workflow immediately on page load with no delay. Verify the redirect_uri parameter in the token exchange POST exactly matches your RuName value from the eBay developer portal — even a trailing slash difference causes a mismatch. If the code has expired, restart the OAuth flow by redirecting the seller to the authorization URL again.
Best practices
- Never hardcode eBay access tokens in API Connector header fields — they expire every 2 hours. Always reference the token dynamically from your EbayToken Data Thing so the most recently refreshed token is used for every API call.
- Apply strict Privacy rules to your EbayToken Data Thing: deny all access to 'Everyone else.' Token records should only be readable and modifiable by Backend Workflows, never directly by page-level search expressions.
- Always store token_expiry as a Date field (not a text field) so Bubble can compare it against 'Current date/time + 5 minutes' in the token refresh condition. A text timestamp comparison will produce incorrect results.
- Use 'Schedule API Workflow on a list' for bulk eBay operations (price updates, inventory syncs across many SKUs) to avoid Bubble's 30-second single-workflow timeout. Each item in the list triggers a separate Backend Workflow execution.
- Add `X-EBAY-C-MARKETPLACE-ID` as a shared header on your eBay API Connector group. Without it, many Sell API endpoints return 400 errors. EBAY_US is the US marketplace; adjust to EBAY_GB, EBAY_DE, etc. for other regional eBays.
- Track WU consumption in Bubble's Logs tab. Token refresh workflows and API polling consume WU on every page load. If you poll eBay for new orders frequently, consider using eBay Notifications (webhook alternative) to receive push updates instead of polling — reduce per-page WU cost significantly.
- Test all OAuth flows in eBay Sandbox environment first. eBay Sandbox uses different URLs (api.sandbox.ebay.com, auth.sandbox.ebay.com) and provides test seller accounts — use these to validate your token exchange, refresh logic, and API calls before switching to Production credentials.
Alternatives
Etsy's API also uses OAuth 2.0 for seller access but has a simpler single-tier token model (no split between Application and User tokens). Etsy's marketplace is focused on handmade and vintage goods with a more defined seller demographic. Choose eBay for broader product categories and auction-style listings; choose Etsy for handmade/vintage storefronts.
Printful uses a simple Bearer token with no OAuth flow — connecting Bubble to Printful takes 30 minutes versus 3-5 hours for eBay's two-tier OAuth. Printful handles print-on-demand fulfillment for your own Bubble storefront; eBay is a third-party marketplace where products are listed and sold. Use Printful if you want to build your own store with automated fulfillment; use eBay to list and sell on eBay's marketplace.
WooCommerce uses Basic Auth (consumer key + secret) with no token expiry — far simpler than eBay's OAuth flow. WooCommerce powers your own hosted WordPress store; eBay is a marketplace with millions of existing buyers. Choose WooCommerce if you want full control over your storefront and checkout; choose eBay to reach eBay's existing customer base.
Frequently asked questions
Do I need a paid Bubble plan to connect to eBay?
For the Browse API (public product search using Application tokens), you can use a free Bubble plan — the token refresh can be triggered client-side and the calls are standard API Connector calls. However, for the Sell and Fulfillment APIs, you must use Backend Workflows to handle the OAuth authorization-code flow and token storage, and Backend Workflows require a paid Bubble plan (Starter or above). In practice, if you are building anything useful with eBay seller data, you need a paid plan.
Can I use eBay API without a seller account?
Yes — the Browse API uses Application tokens (client credentials) and requires only a developer app, not a seller account. This covers product search, item details, and category browsing. The Sell and Fulfillment APIs require an active eBay seller account to complete the OAuth consent flow and obtain User tokens. If you're building a product discovery or price comparison tool, you don't need a seller account.
My eBay app token call returns a 401 — what is wrong?
The most common cause is an incorrect Basic Auth header for the token endpoint. The Authorization header for token requests uses Base64 encoding of 'AppID:CertID' (colon-separated). If you are encoding only the App ID, or encoding them separately, the result is incorrect. Use a Base64 encoder tool with the exact string 'YourAppID:YourCertID' and paste the result into the header value. Also verify you are using Production credentials against Production endpoints and Sandbox credentials against Sandbox endpoints — mixing them causes 401 errors.
eBay's searchCriteria or filter parameters look complex — how do I pass them in Bubble?
eBay's filter parameters use a proprietary bracket-notation syntax like `filter=orderfulfillmentstatus:{NOT_STARTED|IN_PROGRESS}` or `filter=creationdate:[2025-01-01T00:00:00.000Z..]`. In Bubble's API Connector, add these as a single URL parameter named `filter` with the full bracket-syntax value as a dynamic text field. Bubble handles URL encoding automatically. Do not pre-encode the brackets or curly braces — Bubble's encoder will double-encode them if you do, causing eBay to return 400 errors.
Why do I see nested empty data when I display eBay order line items in a Repeating Group?
eBay orders return lineItems as a JSON array nested inside each order object. Bubble's Repeating Group cannot directly iterate over a nested array from an API response — it can only display one level of the response structure. To show individual line items, either create a LineItem Data Thing and populate it from a Backend Workflow that processes each order, or use a 'List of texts' state variable to hold the flattened line item display strings. The API Connector's Initialize Call shows which nested paths Bubble has detected — expand the order object to find the lineItems array path.
How do I handle eBay API rate limits in Bubble?
eBay's rate limits vary by API family and your developer account approval tier. Check the response headers `X-EBAY-C-REQUEST-ID` and any `X-RateLimit-*` headers in Bubble's Logs tab. If you hit rate limits (HTTP 429), add delays between bulk operations using Bubble's 'Pause before next action' step in Backend Workflows, or spread operations over time using 'Schedule API Workflow' with staggered timestamps. For production applications with high volume, apply for increased rate limits through your eBay developer account dashboard.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation