Skip to main content
RapidDev - Software Development Agency

How to Automate Etsy Order Fulfillment Using the API

Use the Etsy v3 API order.paid webhook to trigger fulfillment. Fetch order details with getShopReceipts, ship via your 3PL, then call POST /shops/{shop_id}/receipts/{receipt_id}/tracking to add a tracking number. Etsy notifies the buyer automatically once tracking is attached.

Need help automating? Talk to an expert
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate6 min read45–60 minutesEtsyLast updated May 2026RapidDev Engineering Team
TL;DR

Use the Etsy v3 API order.paid webhook to trigger fulfillment. Fetch order details with getShopReceipts, ship via your 3PL, then call POST /shops/{shop_id}/receipts/{receipt_id}/tracking to add a tracking number. Etsy notifies the buyer automatically once tracking is attached.

Quick facts about this guide
FactValue
PlatformEtsy
Auth methodOAuth 2.0 with mandatory PKCE
Rate limits10 req/sec, 10,000 req/day (new apps: 5/sec, 5,000/day)
DifficultyIntermediate
Time required45–60 minutes
Last updatedMay 2026

API Quick Reference

Auth

OAuth 2.0 with mandatory PKCE

Rate limit

10 req/sec, 10,000 req/day (new apps: 5/sec, 5,000/day)

Format

JSON

SDK

REST only

API overview

Base URLhttps://openapi.etsy.com/v3/application

Authentication

Etsy mandates PKCE (Proof Key for Code Exchange, RFC 7636) for all OAuth flows. Every API request must include both the Authorization: Bearer header and the x-api-key header. Access tokens expire after 1 hour; use the refresh token (valid 90 days) to get a new one without user re-authentication.

Key endpoints

GET/shops/{shop_id}/receipts

Retrieves a paginated list of shop receipts. Filter by was_paid=true and was_shipped=false to get orders awaiting fulfillment.

ParameterTypeRequiredDescription
optional
optional
optional
optional
optional
GET/shops/{shop_id}/receipts/{receipt_id}

Fetches full details for one order including line items, shipping address, and buyer contact info.

ParameterTypeRequiredDescription
optional
optional
POST/shops/{shop_id}/receipts/{receipt_id}/tracking

Attaches a tracking number to an order and marks it as shipped. Triggers Etsy's automated buyer notification email.

ParameterTypeRequiredDescription
optional
optional
optional
optional
optional
PUT/shops/{shop_id}/receipts/{receipt_id}

Updates order status fields. Use was_shipped=true to mark as fulfilled when tracking is added externally or when no tracking is available.

ParameterTypeRequiredDescription
optional
optional
optional
optional

Step-by-step automation

1

Set Up Webhook for order.paid Events

Register a webhook on the order.paid event so your server is notified the moment a buyer's payment clears. Verify the webhook signature on every incoming request using your shared secret (whsec_ prefix).

request.sh
1# Register the webhook
2curl -X POST https://openapi.etsy.com/v3/application/webhooks \
3 -H "Authorization: Bearer $ETSY_ACCESS_TOKEN" \
4 -H "x-api-key: $ETSY_KEYSTRING" \
5 -H "Content-Type: application/json" \
6 -d '{
7 "url": "https://yourapp.com/webhooks/etsy",
8 "events": ["order.paid"]
9 }'
2

Fetch Order Details with getShopReceipts

After receiving the order.paid event, fetch full receipt details to get the shipping address, line items, and buyer contact. Implement automatic token refresh — access tokens expire after 1 hour.

request.sh
1# Fetch a single receipt by ID
2curl -X GET "https://openapi.etsy.com/v3/application/shops/$SHOP_ID/receipts/$RECEIPT_ID" \
3 -H "Authorization: Bearer $ETSY_ACCESS_TOKEN" \
4 -H "x-api-key: $ETSY_KEYSTRING"
5
6# Or fetch all unfulfilled paid orders
7curl -X GET "https://openapi.etsy.com/v3/application/shops/$SHOP_ID/receipts?was_paid=true&was_shipped=false&limit=50" \
8 -H "Authorization: Bearer $ETSY_ACCESS_TOKEN" \
9 -H "x-api-key: $ETSY_KEYSTRING"
3

Submit Tracking Number to Etsy

After your 3PL or warehouse provides a tracking number, POST it to Etsy. This marks the order as shipped and triggers Etsy's automated buyer notification email. Always pass send_bcc=true to get a copy of the notification.

request.sh
1curl -X POST "https://openapi.etsy.com/v3/application/shops/$SHOP_ID/receipts/$RECEIPT_ID/tracking" \
2 -H "Authorization: Bearer $ETSY_ACCESS_TOKEN" \
3 -H "x-api-key: $ETSY_KEYSTRING" \
4 -H "Content-Type: application/json" \
5 -d '{
6 "tracking_code": "9400111899223408865834",
7 "carrier_name": "usps",
8 "send_bcc": true
9 }'
4

Process Order Backlog with Rate-Limit-Safe Batching

High-volume shops during sales events can hit the 10 req/sec limit when processing a backlog of orders. Use a queue with a token bucket or simple throttle (100ms minimum between requests) to stay under the limit. Implement exponential backoff for 429 responses.

request.sh
1# Paginate through all unfulfilled orders, page by page
2OFFSET=0
3LIMIT=50
4while true; do
5 RESPONSE=$(curl -s -X GET \
6 "https://openapi.etsy.com/v3/application/shops/$SHOP_ID/receipts?was_paid=true&was_shipped=false&limit=$LIMIT&offset=$OFFSET" \
7 -H "Authorization: Bearer $ETSY_ACCESS_TOKEN" \
8 -H "x-api-key: $ETSY_KEYSTRING")
9 COUNT=$(echo $RESPONSE | python3 -c "import sys,json; print(json.load(sys.stdin)['count'])")
10 echo "Processing offset $OFFSET, found $COUNT total"
11 # process results...
12 OFFSET=$((OFFSET + LIMIT))
13 sleep 0.5 # rate limit safety: 2 req/sec max during batch
14 [ $OFFSET -ge $COUNT ] && break
15done

Complete working code

Full webhook-driven Etsy fulfillment automation. Receives order.paid events, fetches order details, and submits tracking after 3PL ships.

Error handling

Cause

Access token expired (1-hour TTL) or missing x-api-key header on the request.

Fix

Always include both Authorization: Bearer {token} and x-api-key: {keystring} headers. Implement automatic token refresh using the refresh token before the 1-hour expiry. Use the /oauth/token endpoint with grant_type=refresh_token.

Cause

A tracking number was already submitted for this receipt ID. Etsy does not allow updating tracking once set.

Fix

Catch 409 responses and treat them as success. Add idempotency tracking in your database (store receipt_id + tracking status) to avoid duplicate submission attempts.

Cause

Exceeded 10 req/sec or 10,000 req/day limits. New apps have lower limits (5/sec, 5,000/day) and won't be promoted until first production review.

Fix

Add a minimum 100ms delay between requests. Use Retry-After header value from the 429 response for backoff. During backlog processing, set delay_between_requests to 150ms or higher to stay safely under the limit.

Cause

The receipt_id or shop_id is incorrect, or the receipt belongs to a different shop than the authenticated user.

Fix

Verify shop_id from GET /shops/me. Confirm the receipt_id matches an actual order. Log the full URL and both IDs when debugging 404s.

Cause

Carrier name string doesn't match Etsy's internal codes. 'USPS', 'United States Postal Service', or 'US Postal Service' all fail — only 'usps' (lowercase) is valid.

Fix

Use Etsy's exact carrier codes: usps, fedex, ups, dhl, canada_post, royal_mail, australia_post, deutsche_post, japan_post. Implement a carrier_map dictionary to normalize 3PL carrier strings to Etsy codes.

Cause

Using JSON-parsed body instead of the raw request body for HMAC computation, or incorrect webhook secret.

Fix

Use express.raw() (not express.json()) for the webhook endpoint so the raw bytes are available. Compute HMAC-SHA256 over the raw body bytes, not the parsed JSON object.

Rate limits & throttling

Security checklist

  • Store ETSY_KEYSTRING and tokens in environment variables or a secrets manager — never in source code
  • Always verify webhook signatures using HMAC-SHA256 and constant-time comparison (timingSafeEqual)
  • Use express.raw() for webhook endpoints so raw bytes are preserved for signature verification
  • Refresh tokens expire in 90 days — implement a reminder or auto-refresh flow to prevent customer-facing outages
  • Scope tokens to minimum required: transactions_r, shops_r, shops_w — never request write scopes you don't need
  • Log receipt IDs and tracking submissions to your database to detect and prevent duplicate submissions
  • Use HTTPS for your webhook endpoint — Etsy will not send webhooks to plain HTTP URLs
  • Implement a circuit breaker: if 3 consecutive tracking submissions fail, pause the queue and alert

Automation use cases

3PL Integration — Auto-fulfill on Ship Confirmation

Connect order.paid webhook → your 3PL's API to push pick-and-pack jobs, then receive a tracking callback from the 3PL to auto-post tracking to Etsy.

Multi-Carrier Fulfillment

Route different product types to different carriers (e.g., small items via USPS First Class, large items via UPS Ground) and automatically submit the correct tracking code for each.

Backlog Recovery After Peak Sales Events

During Black Friday or Etsy sales promotions, process hundreds of pending orders safely using paginated getShopReceipts with rate-limit-safe batching.

Custom Buyer Notification Emails

Intercept the order.paid event to send a personalized 'your order is being packed' email via SendGrid before Etsy sends the standard shipped notification.

No-code alternatives

Don't want to write code? These platforms can automate the same workflows visually.

Zapier

Etsy + Zapier integration supports new order triggers and can send tracking numbers back via the Etsy app. Limited to Zapier's available actions — custom carrier mapping requires code steps.

Pros
    Cons

      Make (Integromat)

      More flexible than Zapier for multi-step fulfillment flows. HTTP module can call any Etsy v3 endpoint with custom headers. Supports branching logic for multi-carrier routing.

      Pros
        Cons

          n8n

          Self-hosted option with Etsy OAuth node. Can trigger on order.paid, fetch receipts, call 3PL APIs, and post tracking. Ideal for shops that need full control without SaaS limits.

          Pros
            Cons

              Best practices

              • Always respond 200 OK to the webhook immediately, then process the order asynchronously in a background job
              • Store each processed receipt_id with its tracking status in your database to make the flow idempotent
              • Use Etsy's carrier code list exactly — lowercase strings only (usps, fedex, ups)
              • Implement automatic token refresh before the 1-hour access token expiry to prevent mid-processing failures
              • Add 150ms between requests during batch backlog processing to avoid hitting the 10 req/sec limit
              • Test webhook signature verification with Etsy's test webhook feature in the developer portal before going live
              • Monitor the Etsy developer portal for webhook delivery failures — failed webhooks are retried for 48 hours then silently dropped
              • For high-volume shops, queue webhook events in Redis or SQS rather than processing them synchronously in the HTTP handler

              Ask AI to help

              Copy one of these prompts to get a personalized, working implementation.

              ChatGPT / Claude Prompt

              I need to automate Etsy order fulfillment using the Etsy v3 API. Help me build a Node.js webhook handler that: (1) verifies the order.paid event signature using HMAC-SHA256 on the raw request body, (2) fetches the receipt details using GET /shops/{shop_id}/receipts/{receipt_id} with both Authorization: Bearer and x-api-key headers, (3) sends the order to a 3PL API, (4) accepts a callback with tracking info and posts it to POST /shops/{shop_id}/receipts/{receipt_id}/tracking. Include automatic OAuth token refresh (1-hour expiry) and 429 rate limit handling.

              Lovable / V0 Prompt

              Build me an Etsy order fulfillment dashboard that: (1) shows all paid, unshipped orders fetched from GET /shops/{shop_id}/receipts?was_paid=true&was_shipped=false, (2) has a form to manually enter a tracking number and carrier for each order, (3) submits tracking via POST /shops/{shop_id}/receipts/{receipt_id}/tracking with the required dual headers (Authorization: Bearer + x-api-key), and (4) marks orders as fulfilled in the UI. Use Supabase to store the OAuth tokens and track fulfillment status.

              Frequently asked questions

              Does Etsy send the buyer a shipping notification automatically when I add tracking?

              Yes. When you POST to /receipts/{receipt_id}/tracking, Etsy automatically sends the buyer an email with the tracking link. Set send_bcc=true to receive a copy. You do not need to send a separate notification unless you want a custom-branded email before Etsy's standard notification.

              What carrier names does Etsy accept for the carrier_name field?

              Etsy uses lowercase internal codes: usps, fedex, ups, dhl, canada_post, royal_mail, australia_post, deutsche_post, japan_post. Do not use display names like 'United States Postal Service' — they will return a 400 error. Build a mapping dictionary to normalize carrier strings from your 3PL.

              Can I update a tracking number after it's been submitted?

              No. Once a tracking number is submitted via the API, Etsy returns 409 Conflict on subsequent attempts for the same receipt. If you submitted the wrong tracking number, you need to contact Etsy support to have it removed. This is why idempotency tracking (storing which orders have been submitted) is critical.

              The order.paid webhook is listed as added 'late 2025' — what if it doesn't fire?

              Implement a polling fallback. Run a scheduled job every 15-30 minutes that calls GET /shops/{shop_id}/receipts?was_paid=true&was_shipped=false and processes any orders not already in your fulfillment database. This ensures no orders are missed if webhook delivery fails.

              My shop has 500+ orders from a sale event. How do I process them without getting rate limited?

              Use the getShopReceipts endpoint with pagination (limit=50, offset incremented each page) and add a 150ms delay between each API call. At 150ms intervals you'll make ~6 req/sec — well under the 10/sec limit. For very large backlogs, run the processing job overnight in off-peak hours.

              Can RapidDev help me connect Etsy fulfillment to my existing 3PL or warehouse system?

              Yes. If you need help integrating the Etsy v3 API with a specific 3PL (ShipStation, EasyPost, ShipBob, etc.) or building a custom tracking callback system, RapidDev can build the full integration for you.

              Why do I need both Authorization: Bearer and x-api-key headers?

              Etsy v3 requires both on every request: Authorization: Bearer {access_token} authenticates the user (your OAuth token), and x-api-key: {keystring} identifies your application. Missing either header returns a 401 error. This is different from most APIs that require only one authentication header.

              RapidDev

              Need this automated?

              Our team has built 600+ apps with API automations. We can build this for you.

              Book a free consultation
              Matt Graham

              Written by

              Matt Graham · CEO & Founder, RapidDev

              1,000+ client projects delivered. Columbia University & Harvard Business School alumnus, U.S. Navy veteran. About the author →

              Want this built for you?

              We ship production apps at a fixed price — $13K–$25K, 6–10 weeks, source code yours. You've seen what it takes; we do it every week.

              Get a fixed-price quote

              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.