Skip to main content
RapidDev - Software Development Agency
lovable-integrationsEdge Function Integration

How to Integrate Lovable with Etsy API

Integrate the Etsy Open API v3 with your Lovable app using OAuth2 PKCE for user authorization and a Supabase Edge Function to proxy authenticated API calls. Store your Etsy API key and OAuth credentials in Cloud → Secrets, then build seller dashboards, listing managers, and receipt trackers that read live data from any Etsy shop. Etsy's OAuth2 PKCE flow lets your app access seller data without exposing credentials in browser code.

What you'll learn

  • How to register an Etsy app and configure OAuth2 PKCE redirect URIs
  • How to store Etsy credentials securely in Lovable's Cloud → Secrets
  • How to implement OAuth2 PKCE authorization flow from a Lovable React frontend
  • How to build an Edge Function that exchanges OAuth codes for tokens and proxies Etsy API calls
  • How to display live Etsy shop listings, receipts, and shop statistics in a seller dashboard
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate15 min read60 minutesE-commerceMarch 2026RapidDev Engineering Team
TL;DR

Integrate the Etsy Open API v3 with your Lovable app using OAuth2 PKCE for user authorization and a Supabase Edge Function to proxy authenticated API calls. Store your Etsy API key and OAuth credentials in Cloud → Secrets, then build seller dashboards, listing managers, and receipt trackers that read live data from any Etsy shop. Etsy's OAuth2 PKCE flow lets your app access seller data without exposing credentials in browser code.

Build Etsy seller tools and shop dashboards in Lovable

Etsy's Open API v3 is the only way to programmatically access a seller's listings, orders (called receipts in Etsy's terminology), shop data, and transaction records. Whether you are building a seller dashboard that shows sales analytics, a listing manager that lets sellers bulk-edit their shop, or a custom storefront that displays Etsy listings on your own branded site, the API v3 is the foundation — and it requires OAuth2 PKCE authentication because it accesses user-owned data.

Etsy's taxonomy system is one of its most distinctive features: every listing belongs to a category tree with thousands of specific nodes (for example, 'Jewelry > Necklaces > Pendant Necklaces'). The API exposes this taxonomy so you can build proper category navigation in your app. Etsy's receipt system also differs from other platforms — what other platforms call 'orders' Etsy calls 'receipts,' and each receipt can contain multiple transactions from the same or different shops in a single Etsy checkout.

This guide walks through the complete integration: registering your Etsy app, implementing the OAuth2 PKCE flow so sellers can connect their Etsy shop to your Lovable app, building the Edge Function proxy, and creating a seller dashboard that shows active listings, pending receipts, and shop statistics. The OAuth2 PKCE approach means you can build multi-seller tools where each user connects their own Etsy account, not just tools that read a single hardcoded shop.

Integration method

Edge Function Integration

Etsy's API v3 uses OAuth2 PKCE (Proof Key for Code Exchange) for user-delegated access to shop data. A Supabase Edge Function handles the OAuth2 token exchange and proxies authenticated API calls to Etsy's endpoints. Your React frontend initiates the OAuth2 flow and calls the Edge Function for all data fetching, keeping your Etsy API key server-side in Lovable's encrypted Secrets store.

Prerequisites

  • A Lovable account with an active project
  • An Etsy seller account — you must be a seller to access the full API scope, not just a buyer account
  • An application registered at developers.etsy.com to obtain a Keystring (API key)
  • Your Etsy shop ID — visible in your Etsy shop manager URL as the numeric ID or shop name
  • Understanding of OAuth2 basics — users will be redirected to Etsy to authorize your app before you can access their data

Step-by-step guide

1

Register your Etsy app and configure OAuth2 settings

Navigate to developers.etsy.com and sign in with your Etsy account. Click 'Register a new app' and fill in the application name, description, and website URL. For the website URL during development, use your Lovable project's preview URL (visible in the top bar of the Lovable editor). In the OAuth 2.0 redirect URIs section, add your Lovable app's callback URL — this will be your deployed project URL plus the path /auth/etsy/callback, for example https://yourproject.lovable.app/auth/etsy/callback. You can add multiple redirect URIs including localhost URLs for testing. After saving, Etsy shows you a Keystring — this is your API key used in all requests. Etsy's OAuth2 uses PKCE (Proof Key for Code Exchange), which is a security mechanism that prevents authorization code interception attacks. Unlike traditional OAuth2, PKCE does not require a client secret for the code exchange step — instead it uses a cryptographically random code verifier and challenge that your app generates at the start of each authorization flow. Select the OAuth scopes your app needs: email_r (read email), listings_r (read listings), listings_w (write listings), receipts_r (read receipts), shops_r (read shop data), and transactions_r (read transactions).

Pro tip: Etsy's API requires that your redirect URI matches exactly — including trailing slashes and http vs https. During development, Etsy allows localhost redirect URIs. Add both your development and production URLs when registering.

Expected result: Your Etsy app is registered and you have an Etsy Keystring (API key). Your callback URL is configured in the Etsy developer portal.

2

Store Etsy credentials in Cloud → Secrets

In Lovable, open the Cloud tab by clicking the '+' icon next to the Preview panel and navigate to Secrets. Click 'Add Secret' and add one secret: ETSY_API_KEY with your Etsy app's Keystring as the value. The Etsy Keystring is a 24-character alphanumeric string that must be included as the x-api-key header in every Etsy API request. Unlike some other APIs, Etsy's PKCE OAuth2 flow does not use a client secret for the authorization code exchange — the PKCE code verifier generated by your frontend serves as proof of identity. This means you only need to protect one credential server-side: your API key. The OAuth2 access tokens that grant access to individual users' Etsy data are obtained at runtime through the browser flow and stored in your Supabase database per user — not in Secrets. Your Edge Function will need both the API key from Secrets and the user's access token (passed from the frontend after OAuth login) to make authenticated Etsy API calls.

Pro tip: Store user OAuth tokens in your Supabase database (a 'user_integrations' table with user_id, access_token, refresh_token, expires_at columns) rather than in localStorage. This allows tokens to persist across devices and makes it easier to refresh expired tokens server-side.

Expected result: ETSY_API_KEY appears in your Cloud → Secrets panel.

3

Implement the OAuth2 PKCE authorization flow

Etsy's OAuth2 PKCE flow has two client-side steps that happen in the browser before any Edge Function is involved. First, your React app generates a random code verifier (a 32-byte random string), computes a code challenge (the SHA-256 hash of the code verifier, base64url-encoded), and stores the code verifier in sessionStorage. Then it redirects the user to Etsy's authorization URL with the code challenge, your Keystring, the requested scopes, and a state parameter for CSRF protection. The user logs in to Etsy, approves your app's access, and Etsy redirects them back to your callback URL with an authorization code. Your callback page extracts the code from the URL, retrieves the code verifier from sessionStorage, then calls your Edge Function to exchange the code and code verifier for an access token. The Edge Function makes the POST request to Etsy's token endpoint — this step requires the x-api-key header and the code verifier, but no client secret. The access token and refresh token are then stored in your Supabase database for that user.

Lovable Prompt

Add Etsy OAuth2 PKCE login to my app. Create a 'Connect Etsy Shop' button that: 1) Generates a random 32-byte code verifier using crypto.getRandomValues, stores it in sessionStorage as 'etsy_code_verifier'. 2) Computes a code challenge as the base64url-encoded SHA-256 hash of the code verifier using the Web Crypto API. 3) Redirects to 'https://www.etsy.com/oauth/connect?response_type=code&redirect_uri={callbackUrl}&scope=listings_r%20shops_r%20receipts_r%20transactions_r&client_id={etsyKeystring}&state={randomState}&code_challenge={codeChallenge}&code_challenge_method=S256'. Create a /auth/etsy/callback page that extracts the code and state from the URL, retrieves the code verifier from sessionStorage, then POST to /functions/v1/etsy-auth with { code, code_verifier, redirect_uri }. On success, save the returned user_id and access_token to Supabase user_integrations table.

Paste this in Lovable chat

src/lib/etsy-pkce.ts
1// PKCE helper functions for the frontend
2export async function generateCodeVerifier(): Promise<string> {
3 const array = new Uint8Array(32);
4 crypto.getRandomValues(array);
5 return base64urlEncode(array);
6}
7
8export async function generateCodeChallenge(verifier: string): Promise<string> {
9 const encoder = new TextEncoder();
10 const data = encoder.encode(verifier);
11 const digest = await crypto.subtle.digest('SHA-256', data);
12 return base64urlEncode(new Uint8Array(digest));
13}
14
15function base64urlEncode(buffer: Uint8Array): string {
16 return btoa(String.fromCharCode(...buffer))
17 .replace(/\+/g, '-')
18 .replace(/\//g, '_')
19 .replace(/=/g, '');
20}

Pro tip: The state parameter in the OAuth2 redirect protects against CSRF attacks. Generate a random string, store it in sessionStorage alongside the code verifier, and verify that the state returned by Etsy's callback matches what you stored before proceeding with the token exchange.

Expected result: Clicking 'Connect Etsy Shop' redirects to Etsy's authorization page. After approving, the user is redirected back to your callback URL and the OAuth tokens are saved to Supabase.

4

Deploy the Etsy auth and proxy Edge Functions

You need two Edge Functions: one to handle the OAuth2 token exchange (etsy-auth) and one to proxy authenticated API calls to Etsy (etsy-proxy). The auth function accepts the authorization code and code verifier from your callback page, exchanges them for tokens at Etsy's token endpoint using POST to https://api.etsy.com/v3/public/oauth/token, and returns the access token and Etsy user ID to the frontend to save in Supabase. The proxy function accepts the Etsy API endpoint path and the user's access token, then makes the authenticated request to Etsy with both the x-api-key header and the Authorization: Bearer header. The proxy must forward both headers — Etsy requires the API key on every request regardless of OAuth state. Any Etsy API endpoint that returns user-specific data (listings, receipts, shop data) requires both headers. Public endpoints like taxonomy and some listing lookups require only the API key.

Lovable Prompt

Create two Supabase Edge Functions. Function 1 at supabase/functions/etsy-auth/index.ts: Accept POST with { code, code_verifier, redirect_uri }, exchange for tokens at 'https://api.etsy.com/v3/public/oauth/token' with POST body { grant_type: 'authorization_code', client_id: ETSY_API_KEY, redirect_uri, code, code_verifier }. Return { access_token, refresh_token, token_type, expires_in, userId }. Function 2 at supabase/functions/etsy-proxy/index.ts: Accept POST with { endpoint, method, access_token, body }. Call 'https://openapi.etsy.com/v3' + endpoint with headers { 'x-api-key': ETSY_API_KEY, 'Authorization': 'Bearer ' + access_token }. Return the Etsy API response. Both functions need CORS headers.

Paste this in Lovable chat

supabase/functions/etsy-proxy/index.ts
1// supabase/functions/etsy-proxy/index.ts
2import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
3
4const corsHeaders = {
5 "Access-Control-Allow-Origin": "*",
6 "Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
7};
8
9serve(async (req) => {
10 if (req.method === "OPTIONS") {
11 return new Response("ok", { headers: corsHeaders });
12 }
13
14 try {
15 const apiKey = Deno.env.get("ETSY_API_KEY");
16 if (!apiKey) throw new Error("ETSY_API_KEY not configured");
17
18 const { endpoint, method = "GET", access_token, body } = await req.json();
19 if (!endpoint) throw new Error("'endpoint' is required");
20 if (!access_token) throw new Error("'access_token' is required");
21
22 const url = `https://openapi.etsy.com/v3${endpoint}`;
23
24 const fetchOptions: RequestInit = {
25 method,
26 headers: {
27 "x-api-key": apiKey,
28 Authorization: `Bearer ${access_token}`,
29 "Content-Type": "application/json",
30 },
31 };
32
33 if (body && method !== "GET") {
34 fetchOptions.body = JSON.stringify(body);
35 }
36
37 const response = await fetch(url, fetchOptions);
38 const data = await response.json();
39
40 return new Response(JSON.stringify(data), {
41 headers: { ...corsHeaders, "Content-Type": "application/json" },
42 status: response.ok ? 200 : response.status,
43 });
44 } catch (error) {
45 return new Response(
46 JSON.stringify({ error: error.message }),
47 { headers: { ...corsHeaders, "Content-Type": "application/json" }, status: 500 }
48 );
49 }
50});

Pro tip: Etsy access tokens expire after 3600 seconds (1 hour). Store the expires_at timestamp alongside the access token in Supabase and check it before making API calls. If expired, use the refresh token to get a new access token via the etsy-auth Edge Function with grant_type=refresh_token.

Expected result: Both etsy-auth and etsy-proxy Edge Functions are deployed. Your app can exchange OAuth codes for tokens and proxy authenticated Etsy API calls.

5

Build the seller dashboard with listings and receipts

With OAuth and the proxy in place, prompt Lovable to build the seller dashboard. The Etsy API uses path parameters extensively — the shop ID is required for most seller-specific endpoints. After OAuth login, fetch the seller's shop ID from the API endpoint /v3/application/users/{userId}/shops, which returns their shop details including the numeric shop ID. Store this in your app state for use in subsequent API calls. The Listings API returns active, inactive, draft, and sold-out listings, each with images, pricing, tags, materials, and taxonomy category data. Etsy's taxonomy paths use period-separated IDs (for example, 68887422.1 represents a specific category) — for display purposes, you can fetch taxonomy labels from the /v3/application/seller-taxonomy/nodes endpoint and build a lookup table. For receipts, the Etsy API supports filtering by paid status, shipped status, and date range, making it easy to build a focused view of open orders that need fulfillment attention.

Lovable Prompt

Build a seller dashboard for Etsy. The dashboard requires a connected Etsy account (access token stored in Supabase). On load: 1) Fetch the seller's shop by calling /functions/v1/etsy-proxy with endpoint '/v3/application/users/{etsyUserId}/shops' to get shopId and shop name. 2) Fetch active listings at '/v3/application/shops/{shopId}/listings/active?includes=Images&limit=25'. 3) Fetch recent receipts at '/v3/application/shops/{shopId}/receipts?was_paid=true&limit=10'. Display three sections: a stats row (total active listings, open orders count, last 30 days receipts), a listings table with thumbnail, title, price, quantity, views, and status, and a receipts table with receipt ID, buyer name, items count, total, paid date, and shipment status.

Paste this in Lovable chat

Pro tip: Etsy rate limits the v3 API to 10 requests per second per API key. If you are fetching multiple data sources on dashboard load, use Promise.all to parallelize the requests rather than sequential awaits, staying under the per-second limit.

Expected result: The seller dashboard displays the connected Etsy shop's active listings and recent receipts with live data, refreshing on page load.

Common use cases

Seller dashboard with sales and listing analytics

Build a dashboard where Etsy sellers connect their shop via OAuth2 and see their active listings, recent receipts, revenue totals, and top-selling items — all in a cleaner interface than Etsy's native seller dashboard.

Lovable Prompt

Build an Etsy seller dashboard. After OAuth2 login, call /functions/v1/etsy-proxy with endpoint '/v3/application/shops/{shopId}/listings/active' to show active listings in a table with title, price, quantity, and views. Also call '/v3/application/shops/{shopId}/receipts?was_paid=true&limit=25' to show recent paid orders. Display a summary card at the top with total active listings count and last 30 days revenue calculated from receipt totals.

Copy this prompt to try it in Lovable

Custom shop page with Etsy listing data

Display your Etsy shop's listings on your own branded website built in Lovable. Visitors browse products with custom filtering and search, but all products are live from Etsy with real pricing and availability, and the 'Buy' button links to the actual Etsy listing for checkout.

Lovable Prompt

Create a custom shop page that calls /functions/v1/etsy-proxy with endpoint '/v3/application/shops/{shopId}/listings/active?includes=Images,MainImage&limit=100' to display my Etsy listings on a custom-branded page. Show listings in a grid with the main product image, title, price, and a 'Shop on Etsy' button that links to listing.url. Add a search bar that filters listings client-side by title. Group listings by their taxonomy_path category.

Copy this prompt to try it in Lovable

Order fulfillment and receipt tracker

Build an order management tool for Etsy sellers to track unshipped receipts, mark orders as shipped with tracking numbers, and view buyer messages — helping sellers stay on top of fulfillment without switching between Etsy tabs.

Lovable Prompt

Build an order tracker that calls /functions/v1/etsy-proxy to fetch receipts from '/v3/application/shops/{shopId}/receipts?was_shipped=false&was_paid=true'. Display unshipped paid orders in a list with buyer name, items ordered, total, and ship-by date. For each order add a 'Mark as Shipped' button that opens a form to enter a tracking number and carrier, then submits a PUT request via the proxy to '/v3/application/shops/{shopId}/receipts/{receiptId}/tracking'.

Copy this prompt to try it in Lovable

Troubleshooting

OAuth2 callback page shows 'invalid_grant' error after code exchange

Cause: The authorization code has already been used (each code is single-use), the code verifier does not match the challenge sent during authorization, or the redirect URI in the token exchange request does not exactly match the one registered in the Etsy developer portal.

Solution: Ensure you are retrieving the code verifier from sessionStorage using the exact same key used to store it before the redirect. Verify that the redirect_uri in your token exchange POST request is character-for-character identical to the one in your Etsy app registration. If the user navigated back and triggered the callback twice, the second attempt will fail — redirect them to start the OAuth flow again.

API calls return 403 with 'Missing or invalid access key' even after successful OAuth

Cause: The x-api-key header with your Etsy Keystring is missing from the request. Etsy requires this header on every API call in addition to the Bearer token — it identifies your application even when making user-authenticated requests.

Solution: Verify that your Edge Function is setting both the x-api-key header (with the ETSY_API_KEY secret value) and the Authorization: Bearer header (with the user's access token) on every request. Check Cloud → Logs for the exact headers being sent. The API key and the access token serve different purposes — the API key identifies your app, the access token identifies the user.

Access token works initially then stops working with 'invalid_token' error

Cause: Etsy access tokens expire after 3,600 seconds (1 hour). Your app is using a token that has expired.

Solution: Store the token expiry time (current timestamp + expires_in seconds) when you save the access token. Before each API call, check if the token is within 5 minutes of expiry, and if so, call your etsy-auth Edge Function with grant_type=refresh_token and the stored refresh token to get a new access token. Etsy refresh tokens are long-lived but can only be used once — each refresh call returns a new refresh token that replaces the old one.

typescript
1// Token refresh check in frontend
2const isTokenExpired = (expiresAt: number) => {
3 return Date.now() > expiresAt - 5 * 60 * 1000; // 5 min buffer
4};
5
6// If expired, refresh before API call
7if (isTokenExpired(integration.expires_at)) {
8 const result = await refreshEtsyToken(integration.refresh_token);
9 await updateIntegrationTokens(userId, result);
10}

Listing images not loading in the dashboard — img src shows as undefined

Cause: Etsy listing images are not included in the default listings response. You must explicitly request them using the includes=Images query parameter.

Solution: Add includes=Images to your listing fetch endpoint, for example /v3/application/shops/{shopId}/listings/active?includes=Images. Each listing then has an images array. Access the primary image with listing.images[0].url_570xN for a medium-sized image, or url_fullxfull for the original. The MainImage include parameter adds a single primary_image shortcut: /v3/application/shops/{shopId}/listings/active?includes=Images,MainImage.

Best practices

  • Always request only the OAuth2 scopes your app actually needs — requesting excessive scopes makes users less likely to approve your app and may violate Etsy's developer policies.
  • Store OAuth tokens in Supabase rather than localStorage so they persist across devices for logged-in users and can be refreshed server-side before expiry.
  • Handle the token refresh flow proactively — check token expiry before making API calls rather than waiting for 401 errors, which provide a worse user experience.
  • Respect Etsy's rate limit of 10 requests per second by parallelizing dashboard data fetches with Promise.all rather than sequential awaits, and adding exponential backoff for 429 responses.
  • Cache listing and shop data in your Supabase database with a short TTL (5-15 minutes) to reduce API calls and improve dashboard load times for users who refresh frequently.
  • Display Etsy taxonomy categories using their human-readable names from the /v3/application/seller-taxonomy/nodes endpoint rather than raw taxonomy IDs, which are meaningless to end users.
  • When displaying Etsy listing prices, use the price.amount and price.divisor fields to compute the actual price (amount / divisor) rather than assuming the amount is in full currency units.
  • Link directly to Etsy listing URLs (listing.url) for any 'Buy' or 'View on Etsy' actions — never attempt to replicate Etsy's checkout in your app, as their Terms of Service require purchases to complete on Etsy.

Alternatives

Frequently asked questions

Do I need an Etsy seller account or can I use a buyer account?

To access seller-specific API endpoints like listings management, shop data, and receipts, the OAuth2 user must have an active Etsy shop. A buyer-only account can authorize your app but will not have access to shop management endpoints — those will return 403 errors. If you are building a tool for other sellers, they each need to connect their own Etsy seller account through your app's OAuth2 flow.

Can I create and edit Etsy listings through the API?

Yes, Etsy's API v3 supports creating, updating, and deleting listings with the listings_w scope. Creating a listing requires the shop ID, title, description, price, quantity, shipping profile ID, and a taxonomy ID from Etsy's seller taxonomy tree. Uploading listing images requires separate API calls to the listings/{listingId}/images endpoint. This makes it possible to build bulk listing management tools in Lovable, though you still need to follow Etsy's listing policies regarding handmade items.

How does Etsy's taxonomy system work and why does it matter?

Etsy's taxonomy is a hierarchical category tree with over 6,000 specific nodes for products. Every listing must be assigned a taxonomy node ID, which determines which attributes (materials, techniques, primary color, etc.) are available for that listing type. The Etsy API provides a /v3/application/seller-taxonomy/nodes endpoint to retrieve the full taxonomy tree. For your app, you would use this to let sellers browse and select the correct category when creating listings through your interface.

Can my app access multiple Etsy shops from different sellers?

Yes — that is exactly what OAuth2 PKCE enables. Each seller who uses your app goes through the authorization flow and connects their own Etsy shop. Their access token is stored in your Supabase database associated with their user ID. When they use your app, you retrieve their access token from Supabase and use it in the etsy-proxy Edge Function call. This allows you to build multi-tenant tools like Etsy analytics dashboards that serve many different sellers.

Is there a rate limit I need to worry about for production use?

Etsy limits the API to 10 requests per second per API key and has a daily request quota. For a dashboard that makes several parallel API calls on load, you should stay well within the per-second limit. For higher-volume use cases like syncing entire shop catalogs or running scheduled data imports, implement request queuing with delays between batches. If you hit daily quota limits with a growing user base, contact Etsy's developer support to request a higher quota for your application.

RapidDev

Talk to an Expert

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

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

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.