# How to Integrate Retool with Etsy API

- Tool: Retool
- Difficulty: Intermediate
- Time required: 30 minutes
- Last updated: April 2026

## TL;DR

Connect Retool to the Etsy API using a REST API Resource with OAuth 2.0 PKCE authentication. Etsy's Open API v3 uses PKCE for secure user-level access. Once connected, you can build seller dashboards that manage shop listings, track orders and receipts, view shop statistics, and monitor inventory — providing operations visibility that Etsy's native Seller Hub cannot match.

## Build an Etsy Seller Operations Dashboard with Retool

Etsy's Seller Hub provides strong tools for individual sellers managing a small number of listings, but as shops scale — hundreds of active listings, dozens of daily orders, complex shipping configurations, and inventory tracking across variations — the native interface becomes a bottleneck. Operations teams managing large Etsy shops or agencies managing multiple seller accounts need a custom admin layer that Retool provides through Etsy's Open API v3.

The Etsy API covers the core seller data model comprehensively: shop listings with full variation and inventory data, receipts (Etsy's term for orders), transaction-level detail, shop statistics, shipping profiles, and coupon management. The API uses OAuth 2.0 with PKCE for authentication — a slightly more involved setup than a simple API key, but providing per-shop access control with granular scopes.

For sellers who combine Etsy with other sales channels (Shopify, WooCommerce, Amazon Handmade), Retool's multi-resource architecture is particularly valuable: a single Retool app can display unified order data across all channels in one view, with a JavaScript transformer joining orders from each platform by date or product. Retool's write-back capabilities also enable bulk listing updates — changing prices, quantities, or shipping profiles across many listings at once — operations that require tedious one-by-one clicks in Etsy's native interface.

## Before you start

- An Etsy seller account with an active shop you want to connect to Retool
- An Etsy developer account and a registered application at developers.etsy.com
- A Retool account (Cloud or self-hosted) with permission to create Resources
- An Etsy OAuth 2.0 access token and refresh token obtained by completing the PKCE flow
- Your Etsy shop ID or shop name, used in API endpoint paths

## Step-by-step guide

### 1. Create an Etsy developer application and complete OAuth 2.0 PKCE

To access Etsy's API, you must register a developer application and complete the OAuth 2.0 authorization flow. Go to developers.etsy.com and sign in with your Etsy account. Navigate to 'Your Apps' and click 'Create a new app'. Fill in the application name (e.g., 'Retool Shop Manager'), describe the intended use, and set the redirect URI to your Retool instance URL or a local redirect URL you control for the one-time authorization step. After creating the app, Etsy displays your Application Key (also called client_id). Etsy's Open API v3 uses OAuth 2.0 with PKCE for the authorization flow — you need to generate a code_verifier (a random 43-128 character string), compute its SHA-256 hash, base64url-encode it as the code_challenge, and direct the user to Etsy's authorization URL with the appropriate scopes. Required scopes for a seller dashboard: listings_r (read listings), listings_w (write listings), transactions_r (read orders/receipts), billing_r (read financial data). Complete the authorization by directing your browser to: https://www.etsy.com/oauth/connect?response_type=code&redirect_uri={your_redirect}&scope={scopes}&client_id={app_key}&state={random_state}&code_challenge={code_challenge}&code_challenge_method=S256. After authorizing, Etsy redirects to your redirect URI with a code parameter. Exchange this code for tokens by POSTing to https://api.etsy.com/v3/public/oauth/token with your client_id, redirect_uri, code, code_verifier, and grant_type=authorization_code. The response contains an access_token (valid for 1 hour) and a refresh_token (valid for 90 days). Store both tokens securely in Retool configuration variables.

```
{
  "token_endpoint": "https://api.etsy.com/v3/public/oauth/token",
  "grant_type": "authorization_code",
  "required_fields": {
    "client_id": "your_etsy_app_key",
    "redirect_uri": "your_redirect_uri",
    "code": "authorization_code_from_redirect",
    "code_verifier": "your_pkce_code_verifier"
  },
  "note": "Response includes access_token (1hr) and refresh_token (90 days)"
}
```

**Expected result:** You have an Etsy OAuth 2.0 access token and refresh token stored securely, ready to configure in Retool.

### 2. Create a REST API Resource in Retool

In Retool, navigate to the Resources tab and click '+ Create new'. Select 'REST API'. In the Name field, enter 'Etsy API' or include your shop name if managing multiple shops. For the Base URL, enter https://openapi.etsy.com/v3. For Authentication, select 'Bearer token' and paste your Etsy OAuth 2.0 access token into the token field. Add default headers: Content-Type set to application/json and x-api-key set to your Etsy Application Key (client_id) — this header is required on all Etsy API requests in addition to the Bearer token. Click 'Save resource'. All requests through this resource are proxied server-side by Retool, so neither the Bearer token nor the API key is visible to browser clients. Note that Etsy access tokens expire after 1 hour. For a production Retool app, implement token refresh automation: create a Retool Workflow on a 50-minute schedule that POSTs to Etsy's token endpoint with grant_type=refresh_token and your stored refresh_token, receives a new access_token, and updates the Retool configuration variable. Reference this configuration variable in the resource's Bearer token field using {{ retoolContext.configVars.ETSY_ACCESS_TOKEN }}. Refresh tokens themselves expire after 90 days of inactivity — if your app is used regularly, the chain of refresh operations will keep the tokens active indefinitely.

**Expected result:** A saved REST API Resource named 'Etsy API' with the correct base URL, Bearer token, and x-api-key header is available in Retool's Resources list.

### 3. Write queries to fetch listings and receipts

Open your Retool app or create a new one. In the Code panel, click '+ New query' and select your Etsy API resource. First, find your shop ID or shop name: create a getShop query with Method GET, path /application/shops and param shop_name set to your Etsy shop name. The response includes your shop_id, which is required in subsequent endpoint paths. Alternatively, if you know your shop_id, skip this query. Create a getListings query: Method GET, path /application/shops/{shop_id}/listings/active (replace {shop_id} with your actual shop ID or reference it from a config variable). Add params: limit set to 100, offset set to {{ listingsTable.paginationOffset || 0 }}, sort_on set to 'created', sort_order set to 'desc'. Name this query getListings. Create a getReceipts query: Method GET, path /application/shops/{shop_id}/receipts. Add params: limit set to 100, offset set to {{ receiptsTable.paginationOffset || 0 }}, was_shipped set to false (to show unshipped orders only), and was_paid set to true (to show paid orders). Name this query getReceipts. Run each query to inspect the response — Etsy wraps all list responses in a { count, results: [...] } envelope where count is the total number and results is the current page's data array.

```
{
  "method": "GET",
  "path": "/application/shops/YOUR_SHOP_ID/listings/active",
  "params": {
    "limit": "100",
    "offset": "{{ listingsTable.paginationOffset || 0 }}",
    "sort_on": "created",
    "sort_order": "desc",
    "includes": "[\"MainImage\",\"Images\"]"
  }
}
```

**Expected result:** The getListings query returns a JSON object with 'count' (total) and 'results' (current page) arrays. The getReceipts query returns unpaid orders in the same envelope format.

### 4. Transform responses and build the seller dashboard

Etsy's API returns listings and receipts in nested formats that require flattening before binding to Retool components. In the getListings query editor, click 'Advanced' → toggle 'Transform results'. Write a transformer that maps each listing in data.results to a flat row. Key fields include listing_id, title, price.amount/price.divisor (price is returned as amount and divisor, so actual price = amount/divisor), quantity, views, num_favorers, state ('active', 'inactive', 'draft'), and images[0].url_570xN for a thumbnail. After writing the transformer, drag a Table component onto the canvas. Set its Data source to {{ getListings.data }}. Enable server-side pagination and set total row count to {{ getListings.rawData.count }}. For receipts, write a transformer on getReceipts that maps each receipt to a flat row with receipt_id, buyer name (name field), create_timestamp (Unix to date), total_price, shipping address details, and the first transaction's title as a summary. Drag a second Table, bind it to {{ getReceipts.data }}, and configure the same pagination pattern. Add a search TextInput above the listings table wired to a keyword search parameter. Add a detail Container for receipts that shows when a receipt row is selected, displaying all transaction items and a form to add tracking via POST /application/shops/{shop_id}/receipts/{receipt_id}/tracking. For complex multi-channel inventory management combining Etsy with Shopify or WooCommerce, RapidDev's team can help architect the unified Retool seller operations solution.

```
// Transformer: flatten Etsy listing list
const listings = data.results || [];
return listings.map(listing => ({
  listing_id: listing.listing_id,
  title: listing.title,
  price: listing.price
    ? `$${(listing.price.amount / listing.price.divisor).toFixed(2)} ${listing.price.currency_code}`
    : 'N/A',
  quantity: listing.quantity,
  views: listing.views,
  favorites: listing.num_favorers,
  state: listing.state,
  shop_section_id: listing.shop_section_id || 'None',
  tags: (listing.tags || []).slice(0, 3).join(', '),
  image_url: listing.images && listing.images[0]
    ? listing.images[0].url_570xN
    : '',
  created: listing.creation_timestamp
    ? new Date(listing.creation_timestamp * 1000).toLocaleDateString()
    : 'N/A',
  last_modified: listing.last_modified_tsz
    ? new Date(listing.last_modified_tsz * 1000).toLocaleDateString()
    : 'N/A'
}));
```

**Expected result:** The listings Table shows all active Etsy listings with title, price, quantity, and view count. The receipts Table shows unshipped paid orders. Both tables are paginated and searchable.

### 5. Add listing update and shipment tracking capabilities

Complete the seller dashboard by adding write operations for listing updates and order shipping. For updating a listing's price or quantity, create a PUT query: Method PUT, path /application/listings/{{ listingsTable.selectedRow.listing_id }}, Body type JSON with fields { "price": {{ priceInput.value }}, "quantity": {{ quantityInput.value }}, "state": "active" }. Note that Etsy's price field in PUT requests expects a decimal number (not amount/divisor format), so use the input value directly. Create a shipping tracking query: Method POST, path /application/shops/{shop_id}/receipts/{{ receiptsTable.selectedRow.receipt_id }}/tracking, Body type JSON with { "tracking_code": "{{ trackingInput.value }}", "carrier_name": "{{ carrierSelect.value }}", "send_bcc": true }. The send_bcc option emails the buyer with their tracking information. Wire these queries to Button components in the detail panels. On the listing update query's Success event handler, trigger getListings to refresh the table and show a success notification. On the tracking POST Success handler, trigger getReceipts and show 'Shipment tracked successfully'. Implement a confirmation Modal before submitting price changes — accidental price updates on a live Etsy listing are visible to buyers immediately. Wire the Modal's Confirm button to the actual PUT query and the Cancel button to the Modal's close method.

```
{
  "method": "POST",
  "path": "/application/shops/YOUR_SHOP_ID/receipts/{{ receiptsTable.selectedRow.receipt_id }}/tracking",
  "body": {
    "tracking_code": "{{ trackingInput.value }}",
    "carrier_name": "{{ carrierSelect.value }}",
    "send_bcc": true,
    "note_to_buyer": "{{ noteInput.value || '' }}"
  }
}
```

**Expected result:** The listing update PUT request successfully modifies prices and quantities, with immediate confirmation in the table. The tracking POST marks the order as shipped and triggers an automated buyer email from Etsy.

## Best practices

- Store your Etsy OAuth access token and refresh token as secret configuration variables in Retool and reference them in the resource and token refresh workflow — never hardcode tokens in query paths or bodies.
- Implement automated token refresh using a Retool Workflow that runs every 50 minutes — Etsy access tokens expire after 1 hour and a production dashboard must not silently stop working when the token expires.
- Include the x-api-key header (your Etsy Application Key) as a default header on the REST API Resource rather than adding it to every individual query — this ensures all requests are correctly identified as coming from your registered application.
- Use the 'includes' parameter in listing queries to fetch related data (images, inventory, variations) in a single request rather than making separate API calls per listing, which reduces API call volume and improves dashboard load time.
- Implement confirmation modals before PUT requests that update listing prices or states — price changes on active Etsy listings are immediately visible to buyers and cannot be undone without another API call.
- Create separate Retool REST API Resources for each Etsy shop if you manage multiple shops, with clearly labeled resource names, rather than dynamically switching shop IDs in query paths.
- For sellers with thousands of listings, use Etsy's offset-based pagination with Retool's server-side Table pagination rather than fetching all listings at once — large catalogs will time out on single unbounded API requests.

## Use cases

### Build a listing inventory and price management panel

Your shop operations team manages over 200 active Etsy listings with multiple variations (sizes, colors) per listing and needs to update prices, restock inventory quantities, and change shipping profiles across many listings efficiently. A Retool panel fetches all listings with their variation inventory data, displays them in a searchable Table with inline editing, and submits bulk updates via PUT requests.

Prompt example:

```
Build an inventory management panel that lists all active Etsy shop listings with columns for listing title, price, quantity, views last 30 days, and shipping profile. Add a search input for filtering by title, a category filter, and inline editing for price and quantity columns. Add a 'Save Changes' button that loops through edited rows and sends PUT requests to update each listing.
```

### Create an order fulfillment and shipping dashboard

Your fulfillment team needs to view open Etsy orders, mark them as shipped, add tracking numbers, and see buyer notes — without navigating through multiple Etsy Seller Hub pages per order. A Retool app queries open receipts, displays them in a Table sorted by order date, and provides a detail panel for updating shipping status and adding tracking via the Etsy API.

Prompt example:

```
Build an order fulfillment panel that displays all open Etsy receipts (status: open) with columns for receipt ID, buyer name, items ordered with quantities, total price, ship-by date, and any buyer notes. Add a detail panel that opens on row click showing full address, an input for the tracking number, and a 'Mark as Shipped' button that creates a shipment tracking record via POST request.
```

### Build a shop analytics and revenue dashboard

Your shop owner wants a consolidated view of shop performance — daily revenue, listing views to sales conversion rates, top-selling items, and repeat customer rates — presented more flexibly than Etsy's built-in statistics. A Retool app queries Etsy's shop stats and receipts endpoints over a date range and uses Chart components to visualize revenue trends and product performance.

Prompt example:

```
Build a shop analytics dashboard with date range pickers that queries Etsy receipts for completed sales. Use a JavaScript transformer to aggregate daily revenue, units sold per listing, and buyer repeat purchase rate. Display a Line Chart of daily revenue, a Table of top-selling listings ranked by units sold, and a KPI widget showing total revenue and average order value for the period.
```

## Troubleshooting

### API returns 401 Unauthorized after the access token worked initially

Cause: Etsy OAuth 2.0 access tokens expire after 1 hour. Once expired, all API calls return 401 until the token is refreshed using the refresh_token.

Solution: Use your refresh token to obtain a new access token by POSTing to https://api.etsy.com/v3/public/oauth/token with grant_type=refresh_token, client_id=your_app_key, and refresh_token=your_stored_refresh_token. Update the Bearer token in your Retool resource configuration with the new access_token. For production apps, automate this with a Retool Workflow that runs every 50 minutes to refresh the token proactively.

### Query returns 403 Forbidden with 'Missing required scope'

Cause: The OAuth 2.0 access token was authorized with insufficient scopes. Etsy scopes are set at the time of authorization and cannot be added later — a new authorization flow with the required scopes is needed.

Solution: Repeat the OAuth 2.0 PKCE authorization flow and include all necessary scopes in the authorization URL: listings_r, listings_w, transactions_r, billing_r. After re-authorizing, exchange the new code for tokens and update your Retool configuration variables and resource Bearer token.

### Price field in the transformer shows NaN or undefined

Cause: Etsy returns price as an object with 'amount' and 'divisor' fields, not as a decimal number. Accessing listing.price directly gives you the object; you must compute amount/divisor to get the numeric price.

Solution: Update your transformer to extract price correctly using the amount and divisor fields. Add a null check for the price object before computing the value.

```
price: listing.price && listing.price.divisor
  ? `$${(listing.price.amount / listing.price.divisor).toFixed(2)}`
  : 'Price unavailable',
```

### Receipts query returns empty results despite having open orders in Etsy

Cause: The was_paid and was_shipped filter combination may be excluding your orders. If you have orders that are awaiting payment or already shipped, the filter was_paid=true&was_shipped=false will exclude them.

Solution: Try removing the was_paid and was_shipped parameters to see all receipts. Then adjust filters based on the specific status combinations your team needs to manage. Alternatively, add a status filter Select component in Retool and dynamically apply was_shipped={{ shipFilter.value }} based on the user's selection.

## Frequently asked questions

### Does Etsy require OAuth 2.0 for all API access, or is there a simpler API key option?

Etsy's Open API v3 requires OAuth 2.0 with PKCE for accessing shop-specific data like listings, orders, and financials. There is no simple static API key option for seller data. However, some public read-only endpoints (like searching public listings) can be accessed with just the Application Key as a query parameter — but for building a seller management dashboard, the full OAuth flow is required.

### Can I manage multiple Etsy shops from one Retool app?

Yes, but each shop requires a separate OAuth authorization. Each shop owner must complete the PKCE flow independently, and you will have a separate access token and refresh token per shop. In Retool, create separate REST API Resources for each shop's credentials, and add a Select dropdown in your app to switch between shops dynamically in query paths.

### How do I handle Etsy's API rate limits?

Etsy's API enforces rate limits per application — check the x-ratelimit-remaining and x-ratelimit-reset headers in API responses to monitor usage. For dashboards with many concurrent users or queries that run frequently, enable query caching in Retool (Advanced tab → Cache results) for read-only queries like getListings. For batch operations, use event handler debouncing to avoid rapid successive API calls.

### Can I access listing inventory and variation data through Retool?

Yes. Include 'Inventory' in the includes parameter of your listing query to retrieve variation options and quantities per variant. The inventory response contains property structures and product offerings with per-variation pricing and quantities. This data requires a more complex transformer to flatten, but it enables building a full variant-level inventory editor in Retool.

### Is it possible to automate Etsy shipping tracking from Retool Workflows?

Yes. Create a Retool Workflow with a Webhook trigger that receives shipment notifications from your shipping carrier (UPS, FedEx, USPS). When a tracking event arrives, the Workflow queries your Etsy receipts to find the matching order, then POSTs the tracking number to Etsy's tracking endpoint. This fully automates the tracking update process without any manual data entry.

---

Source: https://www.rapidevelopers.com/retool-integrations/etsy-api
© RapidDev — https://www.rapidevelopers.com/retool-integrations/etsy-api
