Etsy API nutzen: Vollständige Integrationsanleitung (2026)

Ashley Innocent

Ashley Innocent

20 March 2026

Etsy API nutzen: Vollständige Integrationsanleitung (2026)

TL;DR

Die Etsy API ermöglicht Entwicklern, Anwendungen zu erstellen, die mit dem Etsy-Marktplatz interagieren. Sie verwendet OAuth 2.0-Authentifizierung, RESTful-Endpunkte für Shops, Angebote, Bestellungen und Bestandsverwaltung, mit Ratenbegrenzungen von 10 Aufrufen pro Sekunde pro App. Dieser Leitfaden behandelt die Einrichtung der Authentifizierung, Kern-Endpunkte, Webhook-Integration und Strategien für die Bereitstellung in der Produktion.

Einleitung

Etsy wickelt jährliche Bruttowarenverkäufe von über 13 Milliarden US-Dollar in über 230 Ländern ab. Für Entwickler, die E-Commerce-Tools, Bestandsverwaltungssysteme oder Analyseplattformen erstellen, ist die Integration der Etsy API nicht optional – sie ist unerlässlich.

Hier ist die Realität: Verkäufer, die mehrere Vertriebskanäle verwalten, verlieren 15-20 Stunden pro Woche durch manuelle Dateneingabe. Eine solide Etsy API-Integration automatisiert die Angebotssynchronisierung, Auftragsabwicklung und Bestandsaktualisierungen über Plattformen hinweg.

Dieser Leitfaden führt Sie durch den gesamten Etsy API-Integrationsprozess. Sie lernen OAuth 2.0-Authentifizierung, Shop- und Angebotsverwaltung, Auftragsabwicklung, Webhook-Verwaltung und Fehlerbehebung. Am Ende verfügen Sie über eine produktionsreife Etsy-Integration.

💡
Apidog vereinfacht das Testen von API-Integrationen. Testen Sie Ihre Etsy-Endpunkte, validieren Sie OAuth-Flüsse, überprüfen Sie Webhook-Payloads und debuggen Sie Authentifizierungsprobleme in einem Arbeitsbereich. Importieren Sie API-Spezifikationen, modellieren Sie Antworten und teilen Sie Testszenarien mit Ihrem Team.

Was ist die Etsy API?

Etsy bietet eine RESTful API für den Zugriff auf Marktplatzdaten und die Verwaltung von Verkäuferoperationen. Die API übernimmt:

Hauptmerkmale

Merkmal Beschreibung
RESTful Design Standard-HTTP-Methoden mit JSON-Antworten
OAuth 2.0 Sichere Authentifizierung mit Access Token-Aktualisierung
Webhooks Echtzeitbenachrichtigungen für Bestell- und Angebotsereignisse
Ratenbegrenzung 10 Anfragen pro Sekunde pro App (mit Spitzen-Guthaben)
Sandbox-Unterstützung Testumgebung für die Entwicklung ohne Live-Daten

Übersicht über die API-Architektur

Etsy verwendet eine versionierte REST API-Struktur:

https://openapi.etsy.com/v3/application/

Version 3 (v3) ist der aktuelle Standard und bietet im Vergleich zu v2 verbesserte OAuth 2.0-Unterstützung und vereinfachte Endpunktstrukturen.

API-Versionen im Vergleich

Version Status Authentifizierung Anwendungsfall
V3 Aktuell OAuth 2.0 Alle neuen Integrationen
V2 Veraltet OAuth 1.0a Nur Legacy-Anwendungen
V1 Eingestellt N/A Nicht verwenden

Migrieren Sie alle V2-Integrationen sofort auf V3. Etsy hat die V2-Veralterung mit der vollständigen Einstellung für Ende 2026 angekündigt.

Erste Schritte: Authentifizierung einrichten

Schritt 1: Etsy-Entwicklerkonto erstellen

Bevor Sie auf die API zugreifen können, benötigen Sie ein Entwicklerkonto:

  1. Besuchen Sie das Etsy Developer Portal
  2. Melden Sie sich mit Ihrem Etsy-Konto an (oder erstellen Sie eines)
  3. Navigieren Sie in Ihrem Entwickler-Dashboard zu Ihre Apps
  4. Klicken Sie auf Neue App erstellen

Schritt 2: Ihre Anwendung registrieren

Füllen Sie das Registrierungsformular für die App aus:

Nach der Übermittlung erhalten Sie:

Sicherheitshinweis: Speichern Sie Anmeldeinformationen in Umgebungsvariablen, niemals im Code:

# .env-Datei
ETSY_KEY_STRING="ihr_key_string_hier"
ETSY_SHARED_SECRET="ihr_shared_secret_hier"
ETSY_ACCESS_TOKEN="generiert_via_oauth"
ETSY_REFRESH_TOKEN="generiert_via_oauth"

Schritt 3: OAuth 2.0-Fluss verstehen

Etsy verwendet OAuth 2.0 zur Authentifizierung. Hier ist der vollständige Ablauf:

1. Benutzer klickt in Ihrer App auf "Mit Etsy verbinden"
2. Ihre App leitet zur Etsy-Autorisierungs-URL weiter
3. Benutzer meldet sich an und erteilt Berechtigungen
4. Etsy leitet mit Autorisierungscode zurück
5. Ihre App tauscht Code gegen Access Token aus
6. Ihre App verwendet Access Token für API-Aufrufe
7. Refresh Token, wenn Access Token abläuft (1 Stunde)

Schritt 4: OAuth-Autorisierung implementieren

Generieren Sie die Autorisierungs-URL:

const generateAuthUrl = (clientId, redirectUri, state) => {
  const baseUrl = 'https://www.etsy.com/oauth/connect';
  const params = new URLSearchParams({
    client_id: clientId,
    redirect_uri: redirectUri,
    scope: 'listings_r listings_w orders_r orders_w shops_r',
    state: state, // Zufälliger String für CSRF-Schutz
    response_type: 'code'
  });

  return `${baseUrl}?${params.toString()}`;
};

// Verwendung
const authUrl = generateAuthUrl(
  process.env.ETSY_KEY_STRING,
  'https://ihre-app.com/callback',
  crypto.randomBytes(16).toString('hex')
);

console.log(`Benutzer weiterleiten zu: ${authUrl}`);

Erforderliche Scopes

Fordern Sie nur die Berechtigungen an, die Ihre App benötigt:

Scope Beschreibung Anwendungsfall
listings_r Angebote lesen Produkte anzeigen, Inventar synchronisieren
listings_w Angebote schreiben Produkte erstellen/aktualisieren
orders_r Bestellungen lesen Bestellverwaltung, Abwicklung
orders_w Bestellungen schreiben Bestellstatus aktualisieren, Sendungsverfolgung hinzufügen
shops_r Shop-Informationen lesen Shop-Profil anzeigen, Analysen
transactions_r Transaktionen lesen Finanzberichte
email Käufer-E-Mail-Adresse zugreifen Bestellkommunikation

Schritt 5: Code gegen Access Token austauschen

Verwalten Sie den OAuth-Callback und tauschen Sie den Autorisierungscode aus:

const exchangeCodeForToken = async (code, redirectUri) => {
  const response = await fetch('https://api.etsy.com/v3/public/oauth/token', {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: new URLSearchParams({
      grant_type: 'authorization_code',
      client_id: process.env.ETSY_KEY_STRING,
      client_secret: process.env.ETSY_SHARED_SECRET,
      redirect_uri: redirectUri,
      code: code
    })
  });

  const data = await response.json();

  // Speichern Sie diese sicher in Ihrer Datenbank
  return {
    access_token: data.access_token,
    refresh_token: data.refresh_token,
    expires_in: data.expires_in, // Typischerweise 3600 Sekunden (1 Stunde)
    user_id: data.user_id,
    scope: data.scope
  };
};

// Callback-Route verarbeiten
app.get('/callback', async (req, res) => {
  const { code, state } = req.query;

  // Überprüfen Sie, ob der Zustand mit dem gesendeten übereinstimmt (CSRF-Schutz)
  if (state !== req.session.oauthState) {
    return res.status(400).send('Ungültiger Zustands-Parameter');
  }

  try {
    const tokens = await exchangeCodeForToken(code, 'https://ihre-app.com/callback');

    // Token in Datenbank speichern, die mit dem Benutzer verknüpft ist
    await db.users.update(req.session.userId, {
      etsy_access_token: tokens.access_token,
      etsy_refresh_token: tokens.refresh_token,
      etsy_token_expires: Date.now() + (tokens.expires_in * 1000),
      etsy_user_id: tokens.user_id
    });

    res.redirect('/dashboard');
  } catch (error) {
    console.error('Token-Austausch fehlgeschlagen:', error);
    res.status(500).send('Authentifizierung fehlgeschlagen');
  }
});

Schritt 6: Token-Refresh implementieren

Access Tokens laufen nach 1 Stunde ab. Implementieren Sie eine automatische Aktualisierung:

const refreshAccessToken = async (refreshToken) => {
  const response = await fetch('https://api.etsy.com/v3/public/oauth/token', {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: new URLSearchParams({
      grant_type: 'refresh_token',
      client_id: process.env.ETSY_KEY_STRING,
      client_secret: process.env.ETSY_SHARED_SECRET,
      refresh_token: refreshToken
    })
  });

  const data = await response.json();

  // Gespeicherte Token aktualisieren
  return {
    access_token: data.access_token,
    refresh_token: data.refresh_token, // Immer den neuen Refresh Token speichern
    expires_in: data.expires_in
  };
};

// Middleware zur Sicherstellung eines gültigen Tokens vor API-Aufrufen
const ensureValidToken = async (userId) => {
  const user = await db.users.findById(userId);

  // Prüfen, ob das Token innerhalb von 5 Minuten abläuft
  if (user.etsy_token_expires < Date.now() + 300000) {
    const newTokens = await refreshAccessToken(user.etsy_refresh_token);

    await db.users.update(userId, {
      etsy_access_token: newTokens.access_token,
      etsy_refresh_token: newTokens.refresh_token,
      etsy_token_expires: Date.now() + (newTokens.expires_in * 1000)
    });

    return newTokens.access_token;
  }

  return user.etsy_access_token;
};

Schritt 7: Authentifizierte API-Aufrufe durchführen

Fügen Sie den Access Token in jede Anfrage ein:

const makeEtsyRequest = async (endpoint, options = {}) => {
  const accessToken = await ensureValidToken(options.userId);

  const response = await fetch(`https://openapi.etsy.com/v3/application${endpoint}`, {
    ...options,
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'x-api-key': process.env.ETSY_KEY_STRING,
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      ...options.headers
    }
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Etsy API Fehler: ${error.message}`);
  }

  return response.json();
};

Shop-Management-Endpunkte

Shop-Informationen abrufen

Shop-Details, Richtlinien und Einstellungen abrufen:

const getShopInfo = async (shopId) => {
  const response = await makeEtsyRequest(`/shops/${shopId}`, {
    method: 'GET'
  });

  return response;
};

// Verwendung
const shop = await getShopInfo(12345678);
console.log(`Shop: ${shop.title}`);
console.log(`Währung: ${shop.currency_code}`);
console.log(`Anzahl Angebote: ${shop.num_listings_active}`);

Erwartete Shop-Antwort

{
  "shop_id": 12345678,
  "shop_name": "MyHandmadeShop",
  "title": "Handgemachter Schmuck & Accessoires",
  "announcement": "Willkommen! Kostenloser Versand für Bestellungen über 50 $",
  "currency_code": "USD",
  "is_vacation": false,
  "vacation_message": null,
  "sale_message": "Vielen Dank für die Unterstützung kleiner Unternehmen!",
  "digital_sale_message": null,
  "created_timestamp": 1609459200,
  "updated_timestamp": 1710950400,
  "num_listings_active": 127,
  "num_listings_sold": 1543,
  "gaussian_alphas": {
    "overall": 4.8,
    "last_30_days": 4.9
  },
  "vacation_autoreply": null,
  "url": "https://www.etsy.com/shop/MyHandmadeShop",
  "image_url_760x100": "https://i.etsystatic.com/.../banner_760x100.jpg"
}

Shop-Kategorien abrufen

Angebote nach Kategorien organisieren:

const getShopSections = async (shopId) => {
  const response = await makeEtsyRequest(`/shops/${shopId}/sections`, {
    method: 'GET'
  });

  return response;
};

// Beispielantwort
{
  "count": 5,
  "results": [
    {
      "shop_section_id": 12345,
      "title": "Halsketten",
      "rank": 1,
      "num_listings": 23
    },
    {
      "shop_section_id": 12346,
      "title": "Ohrringe",
      "rank": 2,
      "num_listings": 45
    }
  ]
}

Angebotsverwaltung

Neues Angebot erstellen

Ein Produktangebot mit Bildern und Variationen erstellen:

const createListing = async (shopId, listingData) => {
  const payload = {
    title: listingData.title,
    description: listingData.description,
    price: listingData.price.toString(), // Muss ein String sein
    quantity: listingData.quantity,
    sku: listingData.sku || [],
    tags: listingData.tags.slice(0, 13), // Max. 13 Tags
    category_id: listingData.categoryId,
    shop_section_id: listingData.sectionId,
    state: listingData.state || 'active', // active, inactive, draft
    who_made: listingData.whoMade, // i_did, someone_else, collective
    when_made: listingData.whenMade, // 2020_2026, 2010_2019, etc.
    is_supply: listingData.isSupply, // true für Bastelmaterial
    item_weight: listingData.weight || null,
    item_weight_unit: listingData.weightUnit || 'g',
    item_length: listingData.length || null,
    item_width: listingData.width || null,
    item_height: listingData.height || null,
    item_dimensions_unit: listingData.dimensionsUnit || 'mm',
    is_private: listingData.isPrivate || false,
    recipient: listingData.recipient || null, // men, women, unisex, etc.
    occasion: listingData.occasion || null, // birthday, wedding, etc.
    style: listingData.style || [] // Max. 2 Stile
  };

  const response = await makeEtsyRequest(`/shops/${shopId}/listings`, {
    method: 'POST',
    body: JSON.stringify(payload)
  });

  return response;
};

// Verwendungsbeispiel
const listing = await createListing(12345678, {
  title: 'Halskette mit Mondphasen aus Sterlingsilber',
  description: 'Handgefertigte Halskette aus Sterlingsilber mit Mondphasen...',
  price: 89.99,
  quantity: 15,
  sku: ['MOON-NECKLACE-001'],
  tags: ['Mondkette', 'Sterlingsilber', 'Mondphase', 'himmlischer Schmuck'],
  categoryId: 10623, // Schmuck > Halsketten
  sectionId: 12345,
  state: 'active',
  whoMade: 'i_did',
  whenMade: 'made_to_order',
  isSupply: false,
  weight: 25,
  weightUnit: 'g'
});

Angebotsbilder hochladen

Bilder werden separat nach der Angebotserstellung hochgeladen:

const uploadListingImage = async (listingId, imagePath, imagePosition = 1) => {
  // Bilddatei als Base64 lesen
  const fs = require('fs');
  const imageBuffer = fs.readFileSync(imagePath);
  const base64Image = imageBuffer.toString('base64');

  const payload = {
    image: base64Image,
    listing_image_id: null,
    position: imagePosition,
    is_watermarked: false,
    alt_text: 'Handgefertigte Halskette mit Mondphasen aus Sterlingsilber' // Für Barrierefreiheit
  };

  const response = await makeEtsyRequest(`/listings/${listingId}/images`, {
    method: 'POST',
    body: JSON.stringify(payload)
  });

  return response;
};

// Mehrere Bilder hochladen
const uploadListingImages = async (listingId, imagePaths) => {
  const results = [];

  for (let i = 0; i < imagePaths.length; i++) {
    const result = await uploadListingImage(listingId, imagePaths[i], i + 1);
    results.push(result);
  }

  return results;
};

Angebotsbestand aktualisieren

Menge für bestehende Angebote aktualisieren:

const updateListingInventory = async (shopId, listingId, inventory) => {
  const payload = {
    products: inventory.products.map(product => ({
      sku: product.sku,
      quantity: product.quantity
    })),
    is_over_selling: inventory.isOverSelling || false,
    on_property: inventory.onProperty || []
  };

  const response = await makeEtsyRequest(
    `/shops/${shopId}/listings/${listingId}/inventory`,
    {
      method: 'PUT',
      body: JSON.stringify(payload)
    }
  );

  return response;
};

// Verwendung
await updateListingInventory(12345678, 987654321, {
  products: [
    { sku: 'MOON-NECKLACE-001', quantity: 10 },
    { sku: 'MOON-NECKLACE-002', quantity: 5 }
  ],
  isOverSelling: false
});

Angebote abrufen

Alle Angebote abrufen oder nach Status filtern:

const getListings = async (shopId, options = {}) => {
  const params = new URLSearchParams({
    limit: options.limit || 25, // Max. 100
    offset: options.offset || 0
  });

  if (options.state) {
    params.append('state', options.state); // active, inactive, draft, sold_out
  }

  const response = await makeEtsyRequest(
    `/shops/${shopId}/listings?${params.toString()}`,
    { method: 'GET' }
  );

  return response;
};

// Ein einzelnes Angebot abrufen
const getListing = async (listingId) => {
  const response = await makeEtsyRequest(`/listings/${listingId}`, {
    method: 'GET'
  });

  return response;
};

Angebot löschen

Ein Angebot aus Ihrem Shop entfernen:

const deleteListing = async (listingId) => {
  const response = await makeEtsyRequest(`/listings/${listingId}`, {
    method: 'DELETE'
  });

  return response;
};

Bestellverwaltung

Bestellungen abrufen

Bestellungen mit Filteroptionen abrufen:

const getOrders = async (shopId, options = {}) => {
  const params = new URLSearchParams({
    limit: options.limit || 25,
    offset: options.offset || 0
  });

  if (options.status) {
    params.append('status', options.status); // open, completed, cancelled
  }

  if (options.minLastModified) {
    params.append('min_last_modified', options.minLastModified);
  }

  const response = await makeEtsyRequest(
    `/shops/${shopId}/orders?${params.toString()}`,
    { method: 'GET' }
  );

  return response;
};

// Eine einzelne Bestellung abrufen
const getOrder = async (shopId, orderId) => {
  const response = await makeEtsyRequest(`/shops/${shopId}/orders/${orderId}`, {
    method: 'GET'
  });

  return response;
};

Bestellungsantwort-Struktur

{
  "order_id": 1234567890,
  "user_id": 98765432,
  "shop_id": 12345678,
  "buyer_user_id": 11223344,
  "creation_timestamp": 1710864000,
  "last_modified_timestamp": 1710950400,
  "completed_timestamp": 1710950400,
  "state": "complete",
  "user_id_fob": null,
  "is_guest": false,
  "name": "Jane Doe",
  "email": "jane.doe@email.com",
  "buyer_phone_number": "+1-555-0123",
  "total_price": "89.99",
  "total_shipping_cost": "5.95",
  "total_tax": "7.65",
  "grand_total": "103.59",
  "currency_code": "USD",
  "payment_method": "credit_card",
  "shipping_address": {
    "name": "Jane Doe",
    "address_line1": "123 Main Street",
    "address_line2": "Apt 4B",
    "city": "New York",
    "state": "NY",
    "zip": "10001",
    "country": "US",
    "phone": "+1-555-0123"
  },
  "listings": [
    {
      "listing_id": 987654321,
      "title": "Halskette mit Mondphasen aus Sterlingsilber",
      "sku": ["MOON-NECKLACE-001"],
      "quantity": 1,
      "price": "89.99"
    }
  ]
}

Bestellstatus aktualisieren

Bestellungen als abgeschlossen markieren und Sendungsverfolgung hinzufügen:

const updateOrderStatus = async (shopId, orderId, trackingData) => {
  const payload = {
    carrier_id: trackingData.carrierId, // usps, fedex, ups, etc.
    tracking_code: trackingData.trackingCode,
    should_send_bcc_to_buyer: trackingData.notifyBuyer || true
  };

  const response = await makeEtsyRequest(
    `/shops/${shopId}/orders/${orderId}/shipping`,
    {
      method: 'POST',
      body: JSON.stringify(payload)
    }
  );

  return response;
};

// Verwendung
await updateOrderStatus(12345678, 1234567890, {
  carrierId: 'usps',
  trackingCode: '9400111899223456789012',
  notifyBuyer: true
});

Gängige Spediteur-IDs

Spediteur Carrier ID
USPS usps
FedEx fedex
UPS ups
DHL dhl_express
Canada Post canada_post
Royal Mail royal_mail
Australia Post australia_post

Ratenbegrenzung und Quotas

Ratenbegrenzungen verstehen

Etsy erzwingt Ratenbegrenzungen, um die API-Stabilität zu schützen:

Das Überschreiten der Limits führt zu HTTP 429 (Too Many Requests) Antworten.

Umgang mit Ratenbegrenzungen implementieren

Verwenden Sie exponentielles Backoff für Wiederholungsversuche:

const makeRateLimitedRequest = async (endpoint, options = {}, maxRetries = 3) => {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await makeEtsyRequest(endpoint, options);

      // Ratenbegrenzungs-Header prüfen
      const remaining = response.headers.get('x-etsy-quota-remaining');
      const resetTime = response.headers.get('x-etsy-quota-reset');

      if (remaining < 100) {
        console.warn(`Niedriges Quota verbleibend: ${remaining}, setzt sich zurück um ${resetTime}`);
      }

      return response;
    } catch (error) {
      if (error.message.includes('429') && attempt < maxRetries) {
        // Exponentielles Backoff: 1s, 2s, 4s
        const delay = Math.pow(2, attempt) * 1000;
        console.log(`Ratenbegrenzung. Wiederholung in ${delay}ms...`);
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
};

Ratenbegrenzung-Header

Etsy enthält diese Header in jeder Antwort:

Header Beschreibung
x-etsy-quota-remaining Verbleibende Aufrufe in der aktuellen Stunde
x-etsy-quota-reset Unix-Zeitstempel, wann das Quota zurückgesetzt wird
x-etsy-limit-remaining Verbleibende Aufrufe in der aktuellen Sekunde
x-etsy-limit-reset Unix-Zeitstempel, wann das Limit pro Sekunde zurückgesetzt wird

Protokollieren Sie diese Header immer zur Überwachung und Fehlerbehebung.

Webhook-Integration

Webhooks konfigurieren

Etsy unterstützt Webhooks für Echtzeit-Ereignisbenachrichtigungen:

  1. Navigieren Sie in Ihrem Entwickler-Dashboard zu Ihre Apps
  2. Wählen Sie Ihre App aus
  3. Klicken Sie auf Webhook hinzufügen
  4. Geben Sie Ihre HTTPS-Endpunkt-URL ein
  5. Wählen Sie die Ereignisse aus, die Sie abonnieren möchten

Verfügbare Webhook-Ereignisse

Ereignistyp Auslöser Anwendungsfall
v3/shops/{shop_id}/orders/create Neue Bestellung aufgegeben Bestätigung senden, Ausführung beginnen
v3/shops/{shop_id}/orders/update Bestellstatus geändert Bestellstatus synchronisieren
v3/shops/{shop_id}/listings/create Neues Angebot erstellt Externen Bestand aktualisieren
v3/shops/{shop_id}/listings/update Angebot geändert Produktdaten synchronisieren
v3/shops/{shop_id}/listings/delete Angebot entfernt Aus externen Systemen entfernen

Webhook-Handler erstellen

const express = require('express');
const crypto = require('crypto');
const app = express();

app.post('/webhooks/etsy', express.raw({ type: 'application/json' }), async (req, res) => {
  const signature = req.headers['x-etsy-signature'];
  const payload = req.body;

  // Webhook-Signatur verifizieren
  const isValid = verifyWebhookSignature(payload, signature, process.env.ETSY_WEBHOOK_SECRET);

  if (!isValid) {
    console.error('Ungültige Webhook-Signatur');
    return res.status(401).send('Nicht autorisiert');
  }

  const event = JSON.parse(payload.toString());

  // An den entsprechenden Handler weiterleiten
  switch (event.type) {
    case 'v3/shops/*/orders/create':
      await handleNewOrder(event.data);
      break;
    case 'v3/shops/*/orders/update':
      await handleOrderUpdate(event.data);
      break;
    case 'v3/shops/*/listings/create':
      await handleListingCreated(event.data);
      break;
    case 'v3/shops/*/listings/update':
      await handleListingUpdated(event.data);
      break;
    case 'v3/shops/*/listings/delete':
      await handleListingDeleted(event.data);
      break;
    default:
      console.log('Unbehandelter Ereignistyp:', event.type);
  }

  // Empfang innerhalb von 5 Sekunden bestätigen
  res.status(200).send('OK');
});

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(expectedSignature, 'hex')
  );
}

Best Practices für Webhooks

  1. Signaturen verifizieren - Verhindert gefälschte Webhooks
  2. Schnell 200 OK zurückgeben - Etsy versucht bei Nicht-200-Antworten innerhalb von 5 Sekunden erneut
  3. Asynchron verarbeiten - Ereignisse für die Hintergrundverarbeitung in eine Warteschlange stellen
  4. Idempotenz implementieren - Doppelte Webhook-Zustellungen behandeln
  5. Alle Ereignisse protokollieren - Probleme mit einem zeitgestempelten Audit-Trail debuggen

Fehlerbehebung bei häufigen Problemen

Problem: OAuth-Token-Austausch schlägt fehl

Symptome: Erhalten von 401- oder 403-Fehlern während der Authentifizierung.

Diagnose:

// Fehlerantwort prüfen
const error = await response.json();
console.error('OAuth-Fehler:', error);

Lösungen:

  1. Stellen Sie sicher, dass die Redirect-URI exakt übereinstimmt (einschließlich https:// und nachfolgendem Schrägstrich)
  2. Bestätigen Sie, dass client_id und client_secret korrekt sind
  3. Stellen Sie sicher, dass der Autorisierungscode nicht abgelaufen ist (Codes verfallen nach 1 Verwendung oder 5 Minuten)
  4. Überprüfen Sie, ob die App im Produktionsmodus ist (Entwicklungs-Apps können nur auf Testkonten zugreifen)

Problem: Ratenbegrenzung überschritten

Symptome: Erhalten von HTTP 429-Antworten.

Lösungen:

  1. Implementieren Sie eine Anfragewarteschlange mit Ratenbegrenzung
  2. Verwenden Sie exponentielles Backoff für Wiederholungsversuche
  3. Fassen Sie Anfragen, wo möglich, zusammen (z. B. mehrere Angebote in einem Aufruf abrufen)
  4. Überwachen Sie Quota-Header und drosseln Sie proaktiv
// Einfacher Ratenbegrenzer
class RateLimiter {
  constructor(requestsPerSecond = 9) { // Unter dem 10/s Limit bleiben
    this.queue = [];
    this.interval = 1000 / requestsPerSecond;
    this.processing = false;
  }

  async add(requestFn) {
    return new Promise((resolve, reject) => {
      this.queue.push({ requestFn, resolve, reject });
      this.process();
    });
  }

  async process() {
    if (this.processing || this.queue.length === 0) return;

    this.processing = true;

    while (this.queue.length > 0) {
      const { requestFn, resolve, reject } = this.queue.shift();

      try {
        const result = await requestFn();
        resolve(result);
      } catch (error) {
        reject(error);
      }

      if (this.queue.length > 0) {
        await new Promise(r => setTimeout(r, this.interval));
      }
    }

    this.processing = false;
  }
}

// Verwendung
const etsyRateLimiter = new RateLimiter(9);
const result = await etsyRateLimiter.add(() => makeEtsyRequest('/shops/12345/listings'));

Problem: Angebotserstellung schlägt mit Validierungsfehlern fehl

Symptome: 400 Bad Request mit Validierungsfehlermeldungen.

Häufige Ursachen:

  1. Ungültige category_id: Verwenden Sie die Kategorien-API von Etsy, um gültige IDs zu erhalten
  2. Preisformat: Muss ein String sein, keine Zahl
  3. Tag-Limit: Maximal 13 Tags pro Angebot
  4. Erforderliche Felder fehlen: title, description, price, quantity, who_made, when_made

Lösung:

// Vor dem Senden validieren
const validateListing = (data) => {
  const errors = [];

  if (!data.title || data.title.length < 5) {
    errors.push('Titel muss mindestens 5 Zeichen lang sein');
  }

  if (typeof data.price !== 'string') {
    errors.push('Preis muss ein String sein');
  }

  if (data.tags && data.tags.length > 13) {
    errors.push('Maximal 13 Tags erlaubt');
  }

  if (!['i_did', 'someone_else', 'collective'].includes(data.whoMade)) {
    errors.push('Ungültiger Wert für who_made');
  }

  return errors;
};

Problem: Webhooks kommen nicht an

Symptome: Bestellungen werden verarbeitet, aber der Webhook-Endpunkt empfängt nichts.

Diagnose:

  1. Überprüfen Sie die Webhook-Zustellungsprotokolle im Entwickler-Dashboard
  2. Verifizieren Sie, dass der Endpunkt innerhalb von 5 Sekunden 200 OK zurückgibt
  3. Testen Sie den Endpunkt manuell mit curl

Lösungen:

  1. Sicherstellen, dass HTTPS mit gültigem SSL-Zertifikat verwendet wird
  2. Etsy Webhook-IPs in der Firewall zulassen
  3. Überprüfen Sie die Signaturüberprüfungslogik
  4. Verwenden Sie Webhook-Testtools während der Entwicklung

Problem: Bilder können nicht hochgeladen werden

Symptome: Angebot wird erstellt, aber Bilder geben Fehler zurück.

Lösungen:

  1. Überprüfen Sie, ob das Bild ein gültiges Format (JPEG, PNG, GIF) hat
  2. Überprüfen Sie die Dateigröße (max. 20 MB pro Bild)
  3. Stellen Sie sicher, dass die Base64-Kodierung korrekt ist
  4. Bestätigen Sie, dass das Angebot existiert, bevor Sie Bilder hochladen
  5. Laden Sie Bilder nacheinander hoch, nicht parallel

Checkliste für die Produktionsbereitstellung

Vor der Live-Schaltung:

Überwachung und Alarmierung

Verfolgen Sie diese Metriken:

// Beispielmetriken zur Verfolgung
const metrics = {
  apiCalls: {
    total: 0,
    successful: 0,
    failed: 0,
    rateLimited: 0
  },
  quotaUsage: {
    current: 0,
    limit: 10000,
    resetTime: null
  },
  oauthTokens: {
    active: 0,
    expiring_soon: 0,
    refresh_failures: 0
  },
  webhooks: {
    received: 0,
    processed: 0,
    failed: 0
  }
};

// Alarm bei hoher Fehlerquote
const failureRate = metrics.apiCalls.failed / metrics.apiCalls.total;

if (failureRate > 0.05) { // Mehr als 5% Fehlerquote
  sendAlert('Etsy API Fehlerquote über 5%');
}

// Alarm bei niedrigem Quota
if (metrics.quotaUsage.current < 500) {
  sendAlert('Etsy API Quota unter 500 Aufrufen verbleibend');
}

Praktische Anwendungsfälle

Mehrkanal-Bestandssynchronisierung

Ein Verkäufer von Wohnaccessoires nutzt die Etsy API, um den Bestand über Etsy, Shopify und Amazon hinweg zu synchronisieren:

Implementierungsfluss:

  1. Etsy-Webhook löst bei Bestellerstellung aus
  2. Zentrales System reduziert den Bestand
  3. API-Aufrufe aktualisieren Shopify- und Amazon-Mengen
  4. Bestätigung wird in der Datenbank protokolliert

Automatisierte Auftragsabwicklung

Ein Print-on-Demand-Unternehmen automatisiert die Auftragsabwicklung:

Wichtige Integrationspunkte:

Analyse-Dashboard

Ein Analysetool für Verkäufer aggregiert Daten aus mehreren Shops:

Über die API gesammelte Daten:

Fazit

Die Etsy API bietet umfassenden Zugriff auf die Marktplatzfunktionalität. Wichtige Erkenntnisse:

Schaltfläche

FAQ-Bereich

Wofür wird die Etsy API verwendet?

Die Etsy API ermöglicht es Entwicklern, Anwendungen zu erstellen, die mit dem Etsy-Marktplatz interagieren. Gängige Anwendungsfälle sind die Bestandsverwaltung über mehrere Vertriebskanäle hinweg, die automatisierte Auftragsabwicklung, Analyse-Dashboards, Tools zur Angebotserstellung und Kundenbeziehungsmanagementsysteme.

Wie erhalte ich einen Etsy API-Schlüssel?

Erstellen Sie ein Konto im Etsy Developer Portal, navigieren Sie zu Ihre Apps und klicken Sie auf Neue App erstellen. Nach der Registrierung erhalten Sie einen Key String (öffentliche Kennung) und ein Shared Secret (privater Schlüssel). Speichern Sie beides sicher mithilfe von Umgebungsvariablen.

Ist die Etsy API kostenlos nutzbar?

Ja, die Etsy API ist für Entwickler kostenlos. Es gelten jedoch Ratenbegrenzungen: 10 Anfragen pro Sekunde und 10.000 Aufrufe pro Stunde pro App. Höhere Limits erfordern die Genehmigung von Etsy für spezifische Anwendungsfälle.

Welche Authentifizierung verwendet die Etsy API?

Etsy verwendet OAuth 2.0 zur Authentifizierung. Benutzer autorisieren Ihre App über die Etsy-Autorisierungsseite, und Ihre App erhält einen Access Token (gültig für 1 Stunde) und einen Refresh Token (zum Abrufen neuer Access Tokens).

Wie gehe ich mit Etsy API-Ratenbegrenzungen um?

Implementieren Sie eine Anfragewarteschlange, um unter 10 Anfragen pro Sekunde zu bleiben. Überwachen Sie den Header x-etsy-quota-remaining, um die stündliche Nutzung zu verfolgen. Verwenden Sie exponentielles Backoff, wenn Sie HTTP 429 (Too Many Requests) Antworten erhalten.

Kann ich die Etsy API ohne einen Live-Shop testen?

Ja. Apps im Entwicklungsmodus können sich mit Test-Shops verbinden, um Integrationstests durchzuführen. Erstellen Sie ein Test-Etsy-Konto und verwenden Sie es zur Authentifizierung Ihrer Entwicklungs-App, ohne Live-Daten zu beeinflussen.

Wie funktionieren Webhooks mit der Etsy API?

Etsy-Webhooks senden POST-Anfragen an Ihren HTTPS-Endpunkt, wenn Ereignisse auftreten (neue Bestellungen, Angebotsaktualisierungen). Konfigurieren Sie Webhooks in Ihrem App-Dashboard, implementieren Sie die Signaturüberprüfung und geben Sie innerhalb von 5 Sekunden 200 OK zurück.

Was passiert, wenn ein Etsy OAuth Token abläuft?

Access Tokens verfallen nach 1 Stunde. Verwenden Sie den Refresh Token, um vor dem Ablauf einen neuen Access Token zu erhalten. Implementieren Sie eine automatische Token-Aktualisierung in Ihrer Middleware, um Authentifizierungsfehler bei API-Aufrufen zu vermeiden.

Kann ich Angebotsbilder über die API hochladen?

Ja. Bilder werden als Base64-kodierte Strings in einem separaten API-Aufruf nach der Angebotserstellung hochgeladen. Jedes Bild darf bis zu 20 MB groß sein und muss im JPEG-, PNG- oder GIF-Format vorliegen.

Wie migriere ich von Etsy API V2 zu V3?

V3 verwendet OAuth 2.0 anstelle von OAuth 1.0a und hat eine andere Endpunktstruktur. Aktualisieren Sie den Authentifizierungsfluss, ändern Sie die Endpunktpfade von /v2/ zu /v3/application/ und testen Sie gründlich vor der Einstellung von V2 Ende 2026.

Praktizieren Sie API Design-First in Apidog

Entdecken Sie eine einfachere Möglichkeit, APIs zu erstellen und zu nutzen