# eBay API

- Tool: FlutterFlow
- Difficulty: Advanced
- Time required: 75 minutes
- Last updated: July 2026

## TL;DR

Connect FlutterFlow to the eBay API using OAuth 2.0, handled through a Firebase Cloud Function. A Cloud Function mints short-lived application tokens (for Browse API product searches) and manages the user authorization-code flow for Sell and Fulfillment APIs. FlutterFlow only ever holds the resulting short-lived access token — the eBay Client Secret never touches the compiled Flutter app.

## Build an eBay-Connected App in FlutterFlow with OAuth 2.0

eBay's developer APIs open up one of the world's largest product marketplaces — billions of active listings covering nearly every product category. With the Browse API, your FlutterFlow app can search eBay's inventory for product research, price comparison, or catalog sourcing apps. The Sell and Fulfillment APIs let sellers view their eBay orders, track shipments, and manage listings from a native mobile app.

eBay's developer program is free to join. The Browse API provides a default allocation for searches — verify your specific app's rate limit at developer.ebay.com after registering, as limits vary by API and approval tier. The sandbox environment (api.sandbox.ebay.com) mirrors production behavior for testing without real listings.

The defining complexity of this integration is OAuth 2.0 with two distinct token types. Application tokens (client credentials grant) are server-minted for public Browse searches — no user action needed. User tokens (authorization code grant) require the user to log in to eBay, consent to your app's requested scopes, and have eBay redirect back with an authorization code that your server exchanges for a token. Both require your Client Secret. Mixing up sandbox and production tokens, using the wrong base URL, or requesting the wrong scopes are the most common failure points. This guide walks you through each scenario clearly.

## Before you start

- An eBay developer account at developer.ebay.com (free to create)
- A production application registered in the eBay developer portal — note the App ID (Client ID), Cert ID (Client Secret), and Dev ID
- An eBay sandbox account for testing (created separately in the developer portal)
- A Firebase project for the Cloud Function that will handle token exchange
- A FlutterFlow project on any plan — API Calls and WebView are available on all plans

## Step-by-step guide

### 1. Register an eBay application and collect credentials

Navigate to developer.ebay.com and log in with your eBay account. Click My Account in the top navigation and select Application Keysets. If this is your first time, click Register a New Application and follow the registration wizard — you will need to provide an application name, a brief description, and the primary use case. Once registered, eBay generates three credential sets: Dev ID (identifies your developer account), App ID / Client ID (identifies your specific application — starts with YourName-AppName-PRD-... for production), and Cert ID / Client Secret (the secret used for token exchange). The App ID can be shared; the Cert ID must never be shared or placed in client code. Also note the Redirect URL (RuName) if you plan to implement the user authorization-code flow for the Sell/Fulfillment API — you configure this in the eBay developer portal under User Tokens → Get a Token from eBay via Your Application, where you register the redirect URL that eBay will send the authorization code to (this will be your Firebase Cloud Function's HTTPS trigger URL). For testing, also collect your Sandbox App ID and Sandbox Cert ID (separate credentials from production). Store all credentials securely — Cert IDs go into Firebase environment variables only.

**Expected result:** You have your eBay App ID, Cert ID, Dev ID, and Redirect URI stored securely. You know whether you need an application token only (Browse API) or a user token (Sell/Fulfillment API).

### 2. Deploy a Firebase Cloud Function to mint eBay tokens

Because the eBay OAuth token exchange requires your Cert ID (Client Secret), all token requests must run on the server. Create a Firebase Cloud Function named getEbayAppToken that implements the client credentials grant: it base64-encodes your AppID:CertID, POSTs to eBay's OAuth endpoint with grant_type=client_credentials and the required scopes, and returns the access token to FlutterFlow. Create a second function named startEbayUserAuth that generates the eBay authorization URL with your App ID, redirect URI, and requested scopes, then returns it to FlutterFlow — the app will open this URL in a WebView for the user to log in. Create a third function named exchangeEbayCode that receives the authorization code eBay sends after user consent, exchanges it for an access token and refresh token using the authorization_code grant, stores the refresh token securely (in Firestore under the user's document), and returns the access token to FlutterFlow. Create a fourth function named refreshEbayToken that reads the stored refresh token and mints a fresh access token when the current one expires (eBay user tokens typically last 2 hours). Set EBAY_APP_ID, EBAY_CERT_ID, and EBAY_REDIRECT_URI as Firebase environment variables before deploying.

```
// Firebase Cloud Function: index.js (simplified)
const functions = require('firebase-functions');
const fetch = require('node-fetch');
const admin = require('firebase-admin');
admin.initializeApp();

const EBAY_OAUTH_URL = 'https://api.ebay.com/identity/v1/oauth2/token';
// Use https://api.sandbox.ebay.com/identity/v1/oauth2/token for sandbox

// 1. Application token (Browse API - no user login needed)
exports.getEbayAppToken = functions.https.onCall(async (data, context) => {
  const appId = process.env.EBAY_APP_ID;
  const certId = process.env.EBAY_CERT_ID;
  const credentials = Buffer.from(`${appId}:${certId}`).toString('base64');

  const response = await fetch(EBAY_OAUTH_URL, {
    method: 'POST',
    headers: {
      'Authorization': `Basic ${credentials}`,
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: 'grant_type=client_credentials&scope=https%3A%2F%2Fapi.ebay.com%2Foauth%2Fapi_scope',
  });
  const token = await response.json();
  return { accessToken: token.access_token, expiresIn: token.expires_in };
});

// 2. Exchange authorization code for user token
exports.exchangeEbayCode = functions.https.onCall(async (data, context) => {
  if (!context.auth) throw new functions.https.HttpsError('unauthenticated', 'Login required');

  const { code } = data;
  const appId = process.env.EBAY_APP_ID;
  const certId = process.env.EBAY_CERT_ID;
  const redirectUri = process.env.EBAY_REDIRECT_URI;
  const credentials = Buffer.from(`${appId}:${certId}`).toString('base64');

  const response = await fetch(EBAY_OAUTH_URL, {
    method: 'POST',
    headers: {
      'Authorization': `Basic ${credentials}`,
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: `grant_type=authorization_code&code=${encodeURIComponent(code)}&redirect_uri=${encodeURIComponent(redirectUri)}`,
  });
  const token = await response.json();

  // Store refresh token securely in Firestore
  await admin.firestore().collection('ebay_tokens').doc(context.auth.uid).set({
    refreshToken: token.refresh_token,
    updatedAt: admin.firestore.FieldValue.serverTimestamp(),
  });

  return { accessToken: token.access_token, expiresIn: token.expires_in };
});
```

**Expected result:** The Cloud Functions deploy successfully. Testing getEbayAppToken in the Firebase Console returns a valid eBay access token JSON object with an access_token and expires_in field.

### 3. Build the eBay Browse API search in FlutterFlow

With application token handling in place, build the product search flow in FlutterFlow. First, add an On App Load action on your home page that calls the getEbayAppToken Cloud Function and stores the returned accessToken in an App State variable named ebayAppToken. Create an API Group named eBayBrowse with base URL https://api.ebay.com. Add a header Authorization with the value Bearer {{accessToken}} and a variable ebayAccessToken — at runtime, set this to FFAppState().ebayAppToken. Create an API Call named SearchItems with Method GET and URL Path /buy/browse/v1/item_summary/search. Add query variables: q (search keyword), limit (integer, default 20), offset (integer, default 0), and filter (string, optional — e.g., conditions:{NEW} for new items only). The full URL path becomes /buy/browse/v1/item_summary/search?q={{q}}&limit={{limit}}&offset={{offset}}. In the Response & Test tab, click Test after entering a sample keyword (e.g., 'laptop'). Generate JSON Paths from the response. Look for $.itemSummaries[*].itemId, $.itemSummaries[*].title, $.itemSummaries[*].price.value, $.itemSummaries[*].image.imageUrl, $.itemSummaries[*].condition, and $.total. In your FlutterFlow canvas, add a SearchBar widget and a ListView. Bind the SearchBar's on-submit action to call SearchItems with the search text and display results in the ListView.

```
// eBay Browse API JSON paths
// For GET /buy/browse/v1/item_summary/search response

$.total                              → totalResults
$.itemSummaries[*].itemId            → itemId
$.itemSummaries[*].title             → itemTitle
$.itemSummaries[*].price.value       → itemPrice
$.itemSummaries[*].price.currency    → currency
$.itemSummaries[*].image.imageUrl    → imageUrl
$.itemSummaries[*].condition         → condition
$.itemSummaries[*].itemWebUrl        → ebayListingUrl
$.itemSummaries[*].seller.username   → sellerName
$.itemSummaries[*].shippingOptions[0].shippingCost.value → shippingCost
```

**Expected result:** Typing a keyword in the SearchBar and submitting populates the ListView with eBay product listings including titles, prices, and images fetched from the Browse API.

### 4. Implement the eBay user authorization-code flow for Sell/Fulfillment APIs

Seller features (viewing orders, updating listings, tracking fulfillment) require a user token obtained through the full OAuth authorization-code flow. This involves the user seeing an eBay login page, approving your app's requested permissions, and eBay redirecting back to your Cloud Function with an authorization code. In FlutterFlow, on the seller dashboard screen, add a Connect eBay Account button. Its action should call a Firebase Cloud Function (or construct the URL directly in FlutterFlow) that returns the eBay authorization URL — it looks like https://auth.ebay.com/oauth2/authorize?client_id={your_app_id}&redirect_uri={your_redirect_uri}&response_type=code&scope={scopes}. Open this URL in FlutterFlow's in-app WebView widget (navigate to it via the Launch URL action or an embedded WebView widget on the page). The user logs in to eBay and approves the permissions. eBay redirects to your configured Redirect URI, which should be your exchangeEbayCode Cloud Function's HTTPS trigger URL. The Cloud Function extracts the code parameter from the redirect, exchanges it for an access token and refresh token, stores the refresh token in Firestore, and redirects the browser to a success page (or you can detect the redirect URL change in the WebView and close it). Store the returned access token in App State as ebayUserToken. All Sell/Fulfillment API calls use this token.

```
// eBay Authorization URL construction
// Build this in your Cloud Function or FlutterFlow and open in WebView

const authUrl = [
  'https://auth.ebay.com/oauth2/authorize',
  '?client_id=', encodeURIComponent(process.env.EBAY_APP_ID),
  '&redirect_uri=', encodeURIComponent(process.env.EBAY_REDIRECT_URI),
  '&response_type=code',
  // Scopes: sell.fulfillment = order management, sell.inventory = listings
  '&scope=', encodeURIComponent(
    'https://api.ebay.com/oauth/api_scope ' +
    'https://api.ebay.com/oauth/api_scope/sell.fulfillment ' +
    'https://api.ebay.com/oauth/api_scope/sell.inventory'
  ),
  '&state=flutterflow-auth-request', // pass-through to verify callback
].join('');

// For sandbox testing, use:
// https://auth.sandbox.ebay.com/oauth2/authorize
// and sandbox App ID/redirect URI
```

**Expected result:** Tapping Connect eBay Account opens a WebView showing the eBay login and consent screen. After the user approves, the WebView redirects to your Cloud Function, the token exchange succeeds, and the FlutterFlow app receives a user access token stored in App State.

### 5. Call Sell and Fulfillment APIs and handle token refresh

With the user access token stored in App State, create a second API Group named eBaySell with base URL https://api.ebay.com and the same Bearer authorization header pattern, this time using FFAppState().ebayUserToken. Add an API Call named GetOrders with Method GET and URL Path /sell/fulfillment/v1/order. This endpoint returns the seller's eBay orders including buyer details, items, payment status, and fulfillment state. Map JSON paths like $.orders[*].orderId, $.orders[*].buyer.username, $.orders[*].totalFeeBasisAmount.value, $.orders[*].orderPaymentStatus, and $.orders[*].lineItems[0].title to display in a ListView. eBay user tokens expire after approximately 2 hours. To handle token refresh gracefully, store the token expiry timestamp in App State alongside the token. At the top of any action that calls the Sell API, add a Conditional Check: if the current time is within 5 minutes of the expiry time, call the refreshEbayToken Cloud Function first, update the App State token and expiry, then proceed with the API call. This prevents mid-session 401 errors from surprising the user.

```
// eBay Sell Fulfillment API JSON paths
// For GET /sell/fulfillment/v1/order response

$.orders[*].orderId                       → orderId
$.orders[*].buyer.username                → buyerUsername
$.orders[*].creationDate                  → orderDate
$.orders[*].orderPaymentStatus            → paymentStatus
$.orders[*].fulfillmentStartInstructions[0].shippingStep.shipTo.fullName → shipToName
$.orders[*].lineItems[0].title            → itemTitle
$.orders[*].lineItems[0].quantity         → quantity
$.orders[*].totalFeeBasisAmount.value     → orderTotal
$.orders[*].totalFeeBasisAmount.currency  → currency

// Token expiry check pseudocode for Action Flow Editor:
// IF DateTime.now() >= FFAppState().ebayTokenExpiry - 5 minutes
//   THEN call refreshEbayToken Cloud Function
//   UPDATE ebayUserToken and ebayTokenExpiry in App State
// THEN call GetOrders API
```

**Expected result:** The FlutterFlow app displays the logged-in seller's eBay orders with buyer names, item titles, and payment status. Refreshing the page after 2 hours correctly triggers a token refresh instead of returning a 401 error.

## Best practices

- Never put the eBay Cert ID (Client Secret) in FlutterFlow — all token exchange operations must happen in a Firebase Cloud Function that holds credentials in environment variables.
- Keep sandbox and production eBay credentials completely separate in Firebase environment config — use separate Cloud Function deployments or environment-specific config keys.
- Request only the OAuth scopes your app actually needs at initial authorization — over-requesting scopes makes users less likely to approve your app and widens the attack surface.
- Store the user token's expiry timestamp alongside the token in App State, and check it before each Sell/Fulfillment API call to trigger a token refresh before it expires mid-session.
- Store eBay refresh tokens in Firestore (server-side), never in FlutterFlow App State — refresh tokens are long-lived and must be protected like passwords.
- Use the eBay sandbox environment for all development and testing to avoid accidentally modifying real listings or triggering real orders during QA.
- Implement a maximum retry with back-off for rate-limited requests — check developer.ebay.com for your app's current rate limits, as they vary by API and approval tier.
- Surface clear error messages when eBay authorization fails or token refresh fails — a generic 'something went wrong' is frustrating for users who need to re-authorize the app.

## Use cases

### eBay product research and price comparison tool

Build a FlutterFlow app that lets sellers or buyers search eBay listings by keyword, filter by condition (new/used) and price range, and see the current lowest price for a product. The app uses the Browse API with an application token — no user login required. Results are displayed in a ListView with product image, title, current price, and a link to the eBay listing.

Prompt example:

```
Let me search for a product on eBay by typing a keyword. Show a list of matching listings with the product title, photo, price, condition (new or used), and a button to open the full eBay listing.
```

### eBay seller order management app

Create a FlutterFlow app for eBay sellers to view their open orders, track shipment status, and mark orders as shipped. The app uses the Fulfillment API with a user token obtained through the eBay authorization-code flow. Orders are displayed with buyer name, item purchased, order amount, and current fulfillment status.

Prompt example:

```
After I log in with my eBay account, show all my open orders with the buyer's name, item title, sale price, and shipping status. Let me tap an order to see the full details and mark it as shipped.
```

### eBay listing sourcing app for resellers

Build a FlutterFlow app that helps resellers identify underpriced eBay listings in specific categories. The app searches the Browse API for items in a category, filters by sold history (using eBay's getItemSummariesByCategory), and calculates the spread between current listing price and market average. Application token is sufficient — no user login required.

Prompt example:

```
Search for eBay listings in a specific category I choose, sorted by price low to high. Show me each item's title, current price, number of bids, and time remaining, so I can spot potential resale opportunities.
```

## Troubleshooting

### 401 Unauthorized on eBay API calls even though the access token looks correct

Cause: The most common causes are: (1) mixing sandbox tokens with the production base URL or vice versa; (2) the access token has expired (app tokens last about 2 hours); (3) the required OAuth scope was not included when the token was minted.

Solution: Verify you are using the correct base URL (api.ebay.com for production, api.sandbox.ebay.com for sandbox) and matching credentials. Check the token expiry timestamp in App State and refresh if needed. Confirm the scope requested when minting the token includes the permission required by the endpoint you are calling.

### "insufficient permissions" error from Sell or Fulfillment API despite having a valid user token

Cause: The user authorized your app but the OAuth scope requested did not include the specific Sell or Fulfillment scope the endpoint requires. eBay OAuth is scope-gated: having a token is not enough — the token must contain the right scope.

Solution: Review the specific scope required for the endpoint in eBay's API documentation. Update the startEbayUserAuth Cloud Function to include the missing scope in the authorization URL, and re-trigger the user authorization flow to get a new token that includes the correct scopes.

### The eBay login WebView redirects but FlutterFlow does not detect the authorization code

Cause: The Redirect URI is not configured correctly in the eBay developer portal, or the Cloud Function URL handling the redirect did not extract the code parameter and return the token to FlutterFlow.

Solution: In the eBay developer portal, navigate to your application's settings and verify the Redirect URI (RuName) exactly matches the HTTPS trigger URL of your exchangeEbayCode Cloud Function. The code parameter appears as a query string parameter in the redirect — confirm your Cloud Function extracts it with req.query.code or context.rawRequest.query.code depending on the function type.

### XMLHttpRequest error when calling eBay APIs from FlutterFlow's web Run Mode

Cause: eBay's API endpoints may not send CORS headers allowing requests from the FlutterFlow preview origin. Native iOS/Android builds are unaffected because they do not enforce CORS.

Solution: Test your eBay API calls on a physical device or simulator rather than in the FlutterFlow web Run Mode browser preview. Alternatively, route all eBay API calls through your Firebase Cloud Function proxy, which does not have browser CORS restrictions.

## Frequently asked questions

### Do I need a user token or an application token to search eBay products?

For searching public eBay listings using the Browse API (e.g., keyword search, category browse, item details), you only need an application token, which is obtained via the client credentials grant with no user login required. User tokens are only necessary for seller-specific features like viewing your own orders, managing listings, or accessing buyer information through the Sell and Fulfillment APIs.

### Can I use the eBay API for free?

Yes, joining eBay's developer program is free. The Browse API has a default call quota that allows a meaningful number of searches per day — check developer.ebay.com for your specific application's current limits, as they vary by app tier and can be increased by applying for higher access. Standard selling fees still apply to actual eBay transactions, but API access itself has no cost.

### How do I test without affecting real eBay listings?

Use the eBay sandbox environment — a separate system with its own credentials, test listings, and test buyer/seller accounts. Register at developer.ebay.com, create a sandbox user account, and use the sandbox base URL (api.sandbox.ebay.com) with your sandbox App ID and Cert ID. Sandbox behavior mirrors production, so your app logic transfers directly when you switch to production credentials.

### Why does my eBay user token expire so quickly?

eBay user access tokens have a short lifespan (approximately 2 hours) by design for security. The token exchange also issues a long-lived refresh token (typically 18 months) that your Cloud Function can use to mint a new access token silently when the current one expires. Store the refresh token in Firestore — never in the FlutterFlow app — and trigger a refresh check before each API call. If you'd rather have a team handle the OAuth plumbing, RapidDev builds FlutterFlow integrations like this weekly — free scoping call at rapidevelopers.com/contact.

### Can I receive eBay order notifications in real time in FlutterFlow?

eBay supports webhooks through its Notifications API and Event Notification platform, but FlutterFlow apps do not have a public inbound URL. Configure eBay notifications to POST to a Firebase Cloud Function, which writes the event to Firestore. Your FlutterFlow app then uses FlutterFlow's native Firebase real-time listener to update the UI when a new order or notification document appears in the Firestore collection.

---

Source: https://www.rapidevelopers.com/flutterflow-integrations/ebay-api
© RapidDev — https://www.rapidevelopers.com/flutterflow-integrations/ebay-api
