Skip to main content
RapidDev - Software Development Agency
flutterflow-integrationsFlutterFlow API Call

Etsy API

Connect FlutterFlow to the Etsy Open API v3 via OAuth 2.0 PKCE, with a Firebase Cloud Function handling the code-to-token exchange and refresh. Every FlutterFlow API Call to Etsy requires two headers simultaneously: Authorization: Bearer [token] AND x-api-key: [keystring]. Missing either header returns 401 even with a valid token. Build a seller dashboard to display active listings and track orders.

What you'll learn

  • How Etsy Open API v3 requires two headers simultaneously (Bearer token AND x-api-key) and why missing either returns 401
  • How to deploy a Firebase Cloud Function that handles OAuth 2.0 PKCE code-to-token exchange and refresh
  • How to launch the Etsy consent screen from FlutterFlow and capture the authorization code
  • How to set up FlutterFlow API Calls with both required headers and map listing/order JSON to Data Types
  • How to store per-seller refresh tokens securely in Firestore and manage token expiry in your seller dashboard
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Advanced19 min read90 minutesE-commerceLast updated July 2026RapidDev Engineering Team
TL;DR

Connect FlutterFlow to the Etsy Open API v3 via OAuth 2.0 PKCE, with a Firebase Cloud Function handling the code-to-token exchange and refresh. Every FlutterFlow API Call to Etsy requires two headers simultaneously: Authorization: Bearer [token] AND x-api-key: [keystring]. Missing either header returns 401 even with a valid token. Build a seller dashboard to display active listings and track orders.

Quick facts about this guide
FactValue
ToolEtsy API
CategoryE-commerce
MethodFlutterFlow API Call
DifficultyAdvanced
Time required90 minutes
Last updatedJuly 2026

Build an Etsy Seller Dashboard in FlutterFlow

Etsy's Open API v3 (base URL https://openapi.etsy.com/v3) is the official way to access Etsy shop data — listings, orders, receipts, and transactions — on behalf of an individual seller. The most common FlutterFlow use case is a seller dashboard app: a custom mobile interface where an Etsy seller can view their active listings, track incoming orders, and monitor shop performance without switching between the Etsy mobile app and their notes.

Etsy's authentication combines two separate mechanisms that both appear on every API call. First, OAuth 2.0 PKCE provides per-seller authorization — the seller logs in through Etsy's consent screen, grants your app permission to their shop data, and your app receives an access token. Second, an x-api-key header carries your application's keystring on every single request, independent of the OAuth token. This double-header requirement is unique to Etsy v3 and is the #1 source of 401 errors for developers new to this API: adding only the Bearer token (forgetting the x-api-key) or adding only the x-api-key (without the Bearer) both return 401 with no clear error message.

The PKCE OAuth flow requires generating a code_verifier and code_challenge, redirecting the user to Etsy's consent page, capturing the returned authorization code, and exchanging it for an access token. This exchange must happen server-side — doing it in raw Flutter client code would expose the code_verifier to manipulation and makes refresh token storage insecure. A Firebase Cloud Function is the right home for this logic. Etsy's API is free for developers (register at developers.etsy.com); commercial use with higher rate limits requires approval. The typical rate limit is 10 QPS and 10,000 requests per day per app — verify current limits in Etsy's developer documentation, as they change based on your application's approval status.

Integration method

FlutterFlow API Call

FlutterFlow connects to Etsy Open API v3 using a two-header setup: a Bearer access token (obtained via PKCE OAuth through a Firebase Cloud Function) and an x-api-key keystring on every request. The Cloud Function handles the OAuth authorization code exchange and refresh token management, returning only the short-lived Bearer to FlutterFlow. Etsy listing and order data is then fetched directly via FlutterFlow API Calls using both headers.

Prerequisites

  • An Etsy developer account at developers.etsy.com with an app registered and a keystring issued
  • Your Etsy app's keystring (this is the x-api-key value — distinct from the OAuth client_id which is the same value in Etsy v3)
  • A Firebase project on the Blaze plan with Cloud Functions enabled — required for the PKCE token exchange and outbound HTTP calls
  • Firebase Authentication enabled in your Firebase project (for per-user token storage in Firestore)
  • A FlutterFlow project with Firebase connected via Settings & Integrations → Firebase

Step-by-step guide

1

Register your Etsy app and obtain a keystring

Navigate to developers.etsy.com and sign in with your Etsy account. Click Create a New App. Fill in the application name, website, and a brief description of what your FlutterFlow app will do. Under the redirect URI, enter a URI that your Cloud Function can accept — for the PKCE server-side exchange flow, you can use a Cloud Function URL that will receive the authorization code after the user consents. A common approach is to use https://us-central1-YOUR_PROJECT.cloudfunctions.net/etsyOauthCallback as the redirect URI. After creating the app, Etsy provides two values: a Keystring (also called the API key) and a Shared Secret. In Etsy Open API v3, the keystring serves double duty: it is both the x-api-key header value on every API call AND the OAuth client_id in the PKCE flow. The Shared Secret is less commonly needed for PKCE guest flows but store it securely in Firebase Functions environment variables alongside the keystring. Select the OAuth scopes your app needs. For a listing and order dashboard, you'll need at minimum: listings_r (read listings), transactions_r (read orders/receipts), shops_r (read shop info). Grant only the scopes your app actually uses — requesting unnecessary scopes reduces the chance Etsy approves your app for commercial use. Note: new Etsy developer apps start with standard rate limits (typically 10 QPS / 10,000 requests per day — verify in the current developer docs). If you plan to build a multi-seller platform or a high-volume app, apply for commercial API access through Etsy's developer program.

Pro tip: In Etsy Open API v3, your keystring and your OAuth client_id are the SAME value. When you see examples that show client_id in the OAuth URL, that's your keystring. This confuses many developers who expect a separate OAuth client ID.

Expected result: Your Etsy app is created with a keystring, your redirect URI is registered, and your required OAuth scopes are selected.

2

Deploy a Firebase Cloud Function for Etsy OAuth PKCE

The Etsy OAuth 2.0 PKCE flow requires generating a cryptographically random code_verifier, hashing it to a code_challenge, constructing the authorization URL with both values, redirecting the user to Etsy's consent screen, and then exchanging the returned authorization code for access and refresh tokens. This cannot be done safely in raw Dart client code — the code_verifier would be accessible in the app binary, and storing the refresh token in App State would lose it every time the app restarts. Deploy two Firebase Cloud Functions: one that generates a PKCE authorization URL and temporary state (/etsyAuthUrl), and one that receives the Etsy OAuth callback, performs the token exchange, and stores the refresh token securely in Firestore per user (/etsyOauthCallback). Store your Etsy keystring in Firebase Functions environment variables as ETSY_KEYSTRING and your registered redirect URI as ETSY_REDIRECT_URI. The token exchange function stores the refresh token in Firestore at users/{userId}/etsyTokens/{shopId} — this means each user of your FlutterFlow app can authorize multiple Etsy shops independently. The function returns only the short-lived access token and the token's expiry time back to FlutterFlow. FlutterFlow never sees the refresh token — only the Cloud Function reads and stores it. For the authorization URL endpoint, FlutterFlow calls /etsyAuthUrl with the user's Firebase UID, and the function generates a PKCE pair, stores the code_verifier temporarily in Firestore (for the callback to retrieve), and returns the full Etsy authorization URL including the code_challenge. FlutterFlow then launches this URL in an in-app browser or WebView.

index.js
1const functions = require('firebase-functions');
2const axios = require('axios');
3const crypto = require('crypto');
4const admin = require('firebase-admin');
5
6if (!admin.apps.length) admin.initializeApp();
7const db = admin.firestore();
8
9const KEYSTRING = process.env.ETSY_KEYSTRING;
10const REDIRECT_URI = process.env.ETSY_REDIRECT_URI;
11const TOKEN_URL = 'https://api.etsy.com/v3/public/oauth/token';
12
13function generatePKCE() {
14 const verifier = crypto.randomBytes(32).toString('base64url');
15 const challenge = crypto.createHash('sha256').update(verifier).digest('base64url');
16 return { verifier, challenge };
17}
18
19// Step 1: Generate the Etsy authorization URL
20exports.etsyAuthUrl = functions.https.onRequest(async (req, res) => {
21 res.set('Access-Control-Allow-Origin', '*');
22 if (req.method === 'OPTIONS') { res.status(204).send(''); return; }
23
24 const userId = req.query.userId;
25 if (!userId) { res.status(400).json({ error: 'userId required' }); return; }
26
27 const { verifier, challenge } = generatePKCE();
28 const state = crypto.randomBytes(16).toString('hex');
29
30 // Store verifier and state temporarily (expires in 10 min)
31 await db.collection('etsyPkceState').doc(state).set({
32 verifier, userId,
33 createdAt: admin.firestore.FieldValue.serverTimestamp(),
34 });
35
36 const scopes = 'listings_r transactions_r shops_r';
37 const authUrl = `https://www.etsy.com/oauth/connect?response_type=code` +
38 `&redirect_uri=${encodeURIComponent(REDIRECT_URI)}` +
39 `&scope=${encodeURIComponent(scopes)}` +
40 `&client_id=${KEYSTRING}` +
41 `&state=${state}` +
42 `&code_challenge=${challenge}` +
43 `&code_challenge_method=S256`;
44
45 res.status(200).json({ authUrl });
46});
47
48// Step 2: Handle the OAuth callback and exchange code for tokens
49exports.etsyOauthCallback = functions.https.onRequest(async (req, res) => {
50 const { code, state } = req.query;
51 if (!code || !state) {
52 res.status(400).send('Missing code or state');
53 return;
54 }
55
56 const stateDoc = await db.collection('etsyPkceState').doc(state).get();
57 if (!stateDoc.exists) { res.status(400).send('Invalid or expired state'); return; }
58
59 const { verifier, userId } = stateDoc.data();
60 await stateDoc.ref.delete(); // Single use
61
62 try {
63 const tokenResp = await axios.post(TOKEN_URL, new URLSearchParams({
64 grant_type: 'authorization_code',
65 client_id: KEYSTRING,
66 redirect_uri: REDIRECT_URI,
67 code,
68 code_verifier: verifier,
69 }), { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } });
70
71 const { access_token, refresh_token, expires_in } = tokenResp.data;
72
73 // Persist refresh token per user in Firestore
74 await db.collection('users').doc(userId).collection('etsyTokens').doc('primary').set({
75 refresh_token,
76 updatedAt: admin.firestore.FieldValue.serverTimestamp(),
77 });
78
79 // Return access token + expiry to FlutterFlow via deep link or redirect
80 res.redirect(
81 `your-app-scheme://etsy-callback?access_token=${access_token}&expires_in=${expires_in}`
82 );
83 } catch (error) {
84 res.status(500).send(`Token exchange failed: ${error.message}`);
85 }
86});
87
88// Step 3: Refresh the access token (called from FlutterFlow before it expires)
89exports.etsyRefreshToken = functions.https.onRequest(async (req, res) => {
90 res.set('Access-Control-Allow-Origin', '*');
91 if (req.method === 'OPTIONS') { res.status(204).send(''); return; }
92
93 const { userId } = req.body;
94 if (!userId) { res.status(400).json({ error: 'userId required' }); return; }
95
96 const tokenDoc = await db.collection('users').doc(userId).collection('etsyTokens').doc('primary').get();
97 if (!tokenDoc.exists) { res.status(404).json({ error: 'No token found for user' }); return; }
98
99 const { refresh_token } = tokenDoc.data();
100 try {
101 const tokenResp = await axios.post(TOKEN_URL, new URLSearchParams({
102 grant_type: 'refresh_token',
103 client_id: KEYSTRING,
104 refresh_token,
105 }), { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } });
106 res.status(200).json({
107 access_token: tokenResp.data.access_token,
108 expires_in: tokenResp.data.expires_in,
109 });
110 } catch (error) {
111 res.status(401).json({ error: 'Refresh failed — user must re-authorize' });
112 }
113});
114

Pro tip: The etsyOauthCallback function redirects to a custom deep-link URI (your-app-scheme://etsy-callback). Configure this URI scheme in FlutterFlow under Settings → App Details → Deep Links, and add a handler on your main page that reads the access_token from the incoming deep link and stores it in App State.

Expected result: All three Cloud Functions deploy successfully. Calling /etsyAuthUrl returns a valid Etsy authorization URL. Visiting that URL in a browser shows the Etsy consent screen.

3

Launch the Etsy consent screen and capture the access token

With the Cloud Functions deployed, wire up the Etsy login flow in FlutterFlow. Create a ConnectEtsy page with a Connect My Etsy Shop button. In the button's Action Flow, add a Backend/API Call action that calls your EtsyAuth API Group → GetAuthUrl (set up in the next step) with the logged-in user's Firebase UID. Store the returned authUrl in a page state variable. Then add a Launch URL action pointing to the authUrl variable. This opens the Etsy consent screen in the device's browser. On the consent screen, the seller approves access, Etsy redirects to your etsyOauthCallback function which exchanges the code and stores the refresh token in Firestore, then redirects the user back to your app via the deep link URI with the access token in the URL parameters. In FlutterFlow, configure deep link handling: go to Settings → App Details → Deep Links. Add your custom scheme (e.g. etsyapp://etsy-callback). On the page that receives this deep link — typically your home page or the ConnectEtsy page — add an On Deep Link action that reads the access_token and expires_in parameters from the deep link URL. Store the access_token in App State (String variable: etsyAccessToken) and calculate the expiry timestamp (current time + expires_in seconds) and store it in another App State variable (etsyTokenExpiry as an integer Unix timestamp). Also store the Firebase user ID in App State — you'll need it to call the RefreshToken function. Once the access token is stored in App State, navigate automatically to the seller dashboard. You don't need to display the token anywhere in the UI.

Pro tip: Configure your deep link custom scheme in both FlutterFlow AND your Etsy app's registered redirect URI — they must match exactly. If the redirect URI registered with Etsy doesn't match what the Cloud Function sends, the OAuth flow will fail with an invalid_redirect_uri error.

Expected result: Tapping Connect My Etsy Shop opens the Etsy consent screen, the seller approves, the app receives the deep link, and the access token is stored in App State. The app navigates to the dashboard.

4

Create the Etsy API Group with both required headers

In FlutterFlow, click API Calls in the left nav → + Add → Create API Group. Name it EtsyOpenAPI. Set the Base URL to https://openapi.etsy.com/v3. This is where the critical dual-header setup happens. In the Group Headers section, add BOTH of the following headers — both are mandatory on every Etsy v3 API call: 1. Header name: x-api-key, value: your actual Etsy keystring (the alphanumeric API key from developers.etsy.com). Unlike the Bearer token, the keystring doesn't change per user or per session — it's your app's static credential. You can store it in App Values for cleanliness. 2. Header name: Authorization, value: Bearer {{accessToken}} — make accessToken a Group-level variable so you can pass the current App State value to all calls. Add your first API Call inside the group: name it GetShopListings. Method: GET. Endpoint: /application/shops/{{shopId}}/listings/active. Variables: shopId (String), limit (Integer, default 25), offset (Integer, default 0). The shopId comes from a separate Etsy API call to get the authenticated user's shop — add a second API Call named GetMe: GET /application/users/me — this returns the seller's shop_id that you'll store in App State after the OAuth flow completes. Add a third API Call named GetShopReceipts (orders): GET /application/shops/{{shopId}}/receipts. Variables: shopId, was_paid (Boolean filter), limit (25), offset (0). Open Response & Test for each call, fill in a test shopId and your access token in the accessToken variable field, and click Test API Call. If you get 401, verify BOTH headers are present — x-api-key AND Authorization.

api_group_config.json
1{
2 "API Group": "EtsyOpenAPI",
3 "Base URL": "https://openapi.etsy.com/v3",
4 "Group Headers": {
5 "x-api-key": "YOUR_ETSY_KEYSTRING",
6 "Authorization": "Bearer {{accessToken}}"
7 },
8 "Group Variables": [
9 { "name": "accessToken", "type": "String" }
10 ],
11 "API Calls": [
12 {
13 "Name": "GetMe",
14 "Method": "GET",
15 "Endpoint": "/application/users/me"
16 },
17 {
18 "Name": "GetShopListings",
19 "Method": "GET",
20 "Endpoint": "/application/shops/{{shopId}}/listings/active",
21 "Variables": [
22 { "name": "shopId", "type": "String" },
23 { "name": "limit", "default": "25" },
24 { "name": "offset", "default": "0" }
25 ]
26 },
27 {
28 "Name": "GetShopReceipts",
29 "Method": "GET",
30 "Endpoint": "/application/shops/{{shopId}}/receipts",
31 "Variables": [
32 { "name": "shopId", "type": "String" },
33 { "name": "was_paid", "type": "Boolean", "default": "true" },
34 { "name": "limit", "default": "25" },
35 { "name": "offset", "default": "0" }
36 ]
37 }
38 ]
39}
40

Pro tip: After the OAuth flow completes, call GetMe immediately to retrieve the seller's shopId and primary email, then store the shopId in App State. You'll need it for every subsequent Etsy API call — don't ask the seller to type in their shop ID.

Expected result: All three API Calls in EtsyOpenAPI return data successfully in the Response & Test panel when both x-api-key and a valid Bearer accessToken are present.

5

Build the seller dashboard and implement token refresh

Create a SellerDashboard page as the home page after OAuth login. Add a bottom navigation bar with two tabs: Listings and Orders. On the Listings tab: add a ListView bound via Backend Query to EtsyOpenAPI → GetShopListings, passing the shopId from App State and the etsyAccessToken from App State as the accessToken variable. Inside the ListView, add a Card with: a 100x100 Image widget (bind to $.results[0].images[0].url_75x75 from the listing JSON), a Text widget for listing title ($.results[0].title), and a Text widget for price ($.results[0].price.amount formatted as currency). Map these JSON Paths in the Response & Test panel of GetShopListings using a real API response. On the Orders/Receipts tab: add a ListView bound to EtsyOpenAPI → GetShopReceipts. Create a Shift4Order-style Data Type for Etsy receipts: receiptId (Integer), buyerEmail (String), grandtotal (Double), status (String), createTimestamp (Integer). Inside the Card show receipt ID, buyer name, total, and a formatted date. Token refresh logic: Add a proactive check before firing any EtsyOpenAPI call. Create an App State variable etsyTokenExpiry (Integer). In the Action Flow before any listing or receipt query, add a condition: if current timestamp > etsyTokenExpiry - 300 (5 minutes before expiry), first call your Cloud Function's /etsyRefreshToken endpoint (via a separate API Group pointing at your Cloud Function), update etsyAccessToken and etsyTokenExpiry in App State, then proceed with the Etsy API call. Etsy's daily request limit (verify current limit at developers.etsy.com) means you should avoid polling or auto-refreshing listing data more than needed. Cache the listing array in App State between sessions using Firestore persistence, and only reload on explicit user pull-to-refresh gesture.

Pro tip: If you'd rather skip building the OAuth PKCE flow and token management infrastructure yourself, RapidDev's team builds FlutterFlow integrations with Etsy's API regularly and can handle the authentication architecture — request a free scoping call at rapidevelopers.com/contact.

Expected result: The seller dashboard shows active Etsy listings and recent orders fetched from the Etsy Open API, with proactive token refresh preventing 401 errors mid-session.

Common use cases

Etsy seller order and listing dashboard

An Etsy shop owner builds a FlutterFlow app as their primary mobile interface for managing their shop. After completing the Etsy OAuth login, the app displays active listings with view counts and favorites, incoming orders sorted by date, and receipt details for order fulfillment — all fetched from Etsy Open API v3 with both required headers.

FlutterFlow Prompt

A seller dashboard with a bottom nav: Listings tab showing active product listings with thumbnail, title, quantity, and price; Orders tab showing new and open receipts sorted by date with buyer name and order total; Shop tab showing shop stats (views, revenue, favorites).

Copy this prompt to try it in FlutterFlow

Multi-seller Etsy management platform

A social selling manager oversees multiple Etsy shops for different clients. Each seller logs in separately through the Etsy OAuth consent screen, and the app stores each seller's refresh token per-user in Firestore under their Firebase Auth UID. Switching between seller accounts is as simple as selecting a shop from a dropdown, which loads that seller's token and fetches their shop-specific data.

FlutterFlow Prompt

An app with a shop selector screen showing all connected Etsy shops (each with shop name and avatar), a connect new shop button that launches the Etsy OAuth flow, and a per-shop dashboard with listings and orders that updates when the user switches between shops.

Copy this prompt to try it in FlutterFlow

Etsy listing performance tracker

An Etsy seller wants to track which listings get the most views and favorites over time. The app uses the Etsy API to fetch listing data including view counts and favorited counts, caches results in Firestore with timestamps, and displays trend charts showing which listings are gaining or losing visibility.

FlutterFlow Prompt

A listing analytics screen with a sorted list of active listings ranked by view count, a sparkline chart per listing showing views over the last 30 days, a favorites counter, and a tap-through to the listing detail with full stats.

Copy this prompt to try it in FlutterFlow

Troubleshooting

401 Unauthorized from every Etsy API call despite having a valid access token

Cause: The x-api-key header is missing. Etsy Open API v3 requires BOTH x-api-key (your keystring) AND Authorization: Bearer [token] on every call. Missing either one returns 401 with no distinction between the two missing values.

Solution: Open the EtsyOpenAPI API Group in FlutterFlow → API Calls panel → select the group headers. Verify that BOTH headers are present: x-api-key set to your Etsy keystring value, and Authorization set to Bearer {{accessToken}}. In the Response & Test panel, manually fill in the accessToken variable with a valid token and confirm x-api-key is hard-set or passed correctly. Test the call — if you get a response, the headers are now correct.

Etsy consent screen shows an invalid_redirect_uri error

Cause: The redirect_uri in the Cloud Function's authorization URL does not exactly match the redirect URI registered in your Etsy developer app settings.

Solution: In the Etsy developer portal (developers.etsy.com), go to your app settings and verify the registered redirect URI. Copy it exactly and update the ETSY_REDIRECT_URI environment variable in your Cloud Function configuration to match. Etsy performs an exact string match — trailing slashes, http vs https, and case all matter.

Listing data loads initially but 401 errors appear after 30-60 minutes of use

Cause: The Etsy access token has expired. Tokens are short-lived and must be refreshed using the refresh token stored in Firestore via the Cloud Function.

Solution: Verify the proactive token refresh logic is in place (Step 5): before any EtsyOpenAPI call, check if the current timestamp is within 300 seconds of etsyTokenExpiry, and call the Cloud Function's /etsyRefreshToken endpoint if so. If refresh fails (the refresh token itself has expired), show the user a 'Reconnect Etsy' button that re-launches the OAuth consent flow.

Daily request quota is exhausted before end of day due to ListView scrolling

Cause: FlutterFlow ListViews with Backend Query set to auto-load fire API calls on every rebuild. If listing data is loaded per scroll position without caching, a user scrolling through many listings can exhaust the 10,000 daily request limit.

Solution: Implement caching: load the full active listings array once per session into an App State list variable. Use pagination with limit/offset and store each page in the list variable as the user scrolls, rather than firing a fresh API call for each page view. Add a refresh button for manual refresh instead of auto-reloading. Consider persisting the listing cache in Firestore with a timestamp so it survives app restarts.

Best practices

  • Always include BOTH the x-api-key header (your Etsy keystring) AND the Authorization: Bearer [token] header on every Etsy v3 API call — missing either returns 401 with no helpful error message.
  • Keep the OAuth PKCE code exchange in the Firebase Cloud Function — doing it in Dart client code exposes the code_verifier to extraction and makes secure refresh token storage impossible.
  • Store refresh tokens per Firebase user ID in Firestore, never in FlutterFlow App State — App State is cleared on app restart, which would force the seller to re-authorize every time they close the app.
  • Implement proactive token refresh (check expiry 5 minutes before it occurs) rather than reacting to 401 errors — a mid-session 401 on the orders screen creates a confusing experience for sellers.
  • Cache Etsy listing data aggressively in App State between pages and sessions — Etsy's daily request limit is easy to exhaust if every screen load fires fresh API calls.
  • Request only the OAuth scopes your app actually uses (listings_r, transactions_r, shops_r) — requesting unnecessary scopes reduces Etsy's likelihood of approving your app for commercial use.
  • Call GetMe immediately after the OAuth flow to retrieve and cache the seller's shopId — every other Etsy endpoint requires it, and making sellers type their shop ID is poor UX.
  • Test your token refresh logic explicitly by manually setting etsyTokenExpiry to a past timestamp and confirming the refresh fires and updates the token before the next API call.

Alternatives

Frequently asked questions

Why do I need both x-api-key AND Authorization headers on every Etsy v3 call?

Etsy uses a two-layer authentication model: the x-api-key identifies your application (like an app registration), while the Authorization: Bearer token identifies which seller has authorized your app to access their shop. Both layers are required because Etsy needs to know both which application is making the request and which seller granted access. This is unusual compared to most OAuth APIs that combine both into the OAuth token alone.

Can I use the Etsy API to help multiple different Etsy sellers from one FlutterFlow app?

Yes — this is the multi-seller platform use case. Each seller completes the OAuth consent flow separately, and their refresh token is stored in Firestore under their Firebase Auth user ID. Your single Etsy app keystring (x-api-key) is shared across all sellers since it identifies your application, but each seller's Bearer access token is unique. When switching between sellers in the UI, swap the accessToken and shopId values in App State to switch which seller's data is being displayed.

Does the Etsy API work for listing analytics or only for listing management?

Etsy Open API v3 provides listing data including view counts and favorite counts on individual listings, which you can trend over time by polling and caching in Firestore. However, Etsy does not provide aggregated shop analytics (like Google Analytics-style dashboards) through the API — those are only available in the Etsy seller dashboard on the web. For trend data, your app would need to periodically fetch listing stats and store them in Firestore to build a historical view.

What happens when the refresh token expires?

Etsy refresh tokens have their own expiry (verify the current duration in Etsy's developer documentation). If a refresh token expires, the /etsyRefreshToken Cloud Function call will return a 401, and you must prompt the seller to complete the full OAuth consent flow again. In your FlutterFlow app, catch the 401 from the refresh endpoint and show a 'Your Etsy connection has expired — please reconnect' screen with the Connect My Etsy Shop button.

Is Etsy API access free to use?

Yes, registering at developers.etsy.com and using the API is free. Standard rate limits apply (verify current limits in the Etsy developer documentation). If you're building a commercial product that will be used by many Etsy sellers or requires higher request volumes, Etsy requires a commercial API access application — contact Etsy's developer support to apply.

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