TL;DR
API Etsy memungkinkan pengembang untuk membangun aplikasi yang berinteraksi dengan pasar Etsy. Ini menggunakan autentikasi OAuth 2.0, endpoint RESTful untuk toko, daftar produk (listing), pesanan, dan manajemen inventaris, dengan batasan laju (rate limit) 10 panggilan per detik per aplikasi. Panduan ini mencakup pengaturan autentikasi, endpoint inti, integrasi webhook, dan strategi penerapan produksi.
Pendahuluan
Etsy memproses penjualan barang dagangan kotor tahunan lebih dari $13 miliar di 230+ negara. Bagi pengembang yang membangun alat e-commerce, sistem manajemen inventaris, atau platform analitik, integrasi API Etsy bukanlah pilihan—melainkan sebuah keharusan.
Inilah kenyataannya: penjual yang mengelola berbagai saluran penjualan kehilangan 15-20 jam setiap minggu untuk entri data manual. Integrasi API Etsy yang solid mengotomatiskan sinkronisasi daftar produk, pemrosesan pesanan, dan pembaruan inventaris di seluruh platform.
Panduan ini akan membahas seluruh proses integrasi API Etsy. Anda akan mempelajari autentikasi OAuth 2.0, manajemen toko dan daftar produk, pemrosesan pesanan, penanganan webhook, dan pemecahan masalah kesalahan. Pada akhirnya, Anda akan memiliki integrasi Etsy yang siap produksi.
Apa Itu API Etsy?
Etsy menyediakan API RESTful untuk mengakses data pasar dan mengelola operasi penjual. API ini menangani:
- Pengambilan informasi toko dan profil
- Pembuatan daftar produk (listing), pembaruan, dan manajemen inventaris
- Pemrosesan pesanan dan pelacakan pemenuhan
- Akses data pelanggan dan transaksi
- Profil pengiriman dan perhitungan pajak
- Manajemen unggahan gambar dan media
Fitur Utama
| Fitur | Deskripsi |
|---|---|
| Desain RESTful | Metode HTTP standar dengan respons JSON |
| OAuth 2.0 | Autentikasi aman dengan pembaruan token akses |
| Webhooks | Notifikasi real-time untuk peristiwa pesanan dan daftar produk |
| Pembatasan Laju (Rate Limiting) | 10 permintaan per detik per aplikasi (dengan tunjangan burst) |
| Dukungan Sandbox | Lingkungan pengujian untuk pengembangan tanpa data langsung |
Ikhtisar Arsitektur API
Etsy menggunakan struktur API REST yang terversi:
https://openapi.etsy.com/v3/application/
Versi 3 (v3) adalah standar saat ini, menawarkan dukungan OAuth 2.0 yang lebih baik dan struktur endpoint yang disederhanakan dibandingkan dengan v2.
Perbandingan Versi API
| Versi | Status | Autentikasi | Kasus Penggunaan |
|---|---|---|---|
| V3 | Saat Ini | OAuth 2.0 | Semua integrasi baru |
| V2 | Usang | OAuth 1.0a | Hanya aplikasi lama |
| V1 | Pensiun | N/A | Jangan digunakan |
Segera migrasikan integrasi V2 apa pun ke V3. Etsy mengumumkan penghentian V2 dengan pensiun penuh yang dijadwalkan pada akhir tahun 2026.
Memulai: Pengaturan Autentikasi
Langkah 1: Buat Akun Pengembang Etsy Anda
Sebelum mengakses API, Anda memerlukan akun pengembang:
- Kunjungi Portal Pengembang Etsy
- Masuk dengan akun Etsy Anda (atau buat akun baru)
- Navigasi ke Aplikasi Anda di dasbor pengembang
- Klik Buat aplikasi baru
Langkah 2: Daftarkan Aplikasi Anda
Isi formulir pendaftaran aplikasi:
- Nama Aplikasi: Nama yang jelas dan deskriptif (terlihat oleh pengguna selama OAuth)
- Deskripsi Aplikasi: Jelaskan apa yang dilakukan aplikasi Anda dan siapa yang menggunakannya
- URI Pengalihan (Redirect URI): Ke mana Etsy mengirim pengguna setelah autentikasi (harus menggunakan HTTPS)
- Produksi/Pengembangan: Mulai dengan mode pengembangan untuk pengujian
Setelah pengajuan, Anda akan menerima:
- Key String: Pengidentifikasi API publik Anda
- Shared Secret: Rahasia API pribadi Anda (jangan pernah mengungkapkannya)
Catatan keamanan: Simpan kredensial dalam variabel lingkungan, jangan pernah dalam kode:
# file .env
ETSY_KEY_STRING="your_key_string_here"
ETSY_SHARED_SECRET="your_shared_secret_here"
ETSY_ACCESS_TOKEN="generated_via_oauth"
ETSY_REFRESH_TOKEN="generated_via_oauth"
Langkah 3: Pahami Alur OAuth 2.0
Etsy menggunakan OAuth 2.0 untuk autentikasi. Berikut adalah alur lengkapnya:
1. Pengguna mengklik "Hubungkan dengan Etsy" di aplikasi Anda
2. Aplikasi Anda mengalihkan ke URL otorisasi Etsy
3. Pengguna masuk dan memberikan izin
4. Etsy mengalihkan kembali dengan kode otorisasi
5. Aplikasi Anda menukarkan kode dengan token akses
6. Aplikasi Anda menggunakan token akses untuk panggilan API
7. Perbarui token ketika token akses kedaluwarsa (1 jam)
Langkah 4: Implementasikan Otorisasi OAuth
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, // String acak untuk perlindungan CSRF
response_type: 'code'
});
return `${baseUrl}?${params.toString()}`;
};
// Penggunaan
const authUrl = generateAuthUrl(
process.env.ETSY_KEY_STRING,
'https://your-app.com/callback',
crypto.randomBytes(16).toString('hex')
);
console.log(`Alihkan pengguna ke: ${authUrl}`);
Cakupan yang Diperlukan (Required Scopes)
Minta hanya izin yang dibutuhkan aplikasi Anda:
| Cakupan | Deskripsi | Kasus Penggunaan |
|---|---|---|
listings_r |
Membaca daftar produk | Menampilkan produk, sinkronisasi inventaris |
listings_w |
Menulis daftar produk | Membuat/memperbarui produk |
orders_r |
Membaca pesanan | Manajemen pesanan, pemenuhan |
orders_w |
Menulis pesanan | Memperbarui status pesanan, menambahkan pelacakan |
shops_r |
Membaca info toko | Menampilkan profil toko, analitik |
transactions_r |
Membaca transaksi | Pelaporan keuangan |
email |
Mengakses email pembeli | Komunikasi pesanan |
Langkah 5: Tukarkan Kode dengan Token Akses
Tangani panggilan balik OAuth dan tukarkan kode otorisasi:
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();
// Simpan ini dengan aman di database Anda
return {
access_token: data.access_token,
refresh_token: data.refresh_token,
expires_in: data.expires_in, // Biasanya 3600 detik (1 jam)
user_id: data.user_id,
scope: data.scope
};
};
// Tangani rute panggilan balik
app.get('/callback', async (req, res) => {
const { code, state } = req.query;
// Verifikasi apakah state cocok dengan yang Anda kirim (perlindungan CSRF)
if (state !== req.session.oauthState) {
return res.status(400).send('Invalid state parameter');
}
try {
const tokens = await exchangeCodeForToken(code, 'https://your-app.com/callback');
// Simpan token di database yang terkait dengan pengguna
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('Pertukaran token gagal:', error);
res.status(500).send('Autentikasi gagal');
}
});
Langkah 6: Implementasikan Pembaruan Token
Token akses kedaluwarsa setelah 1 jam. Implementasikan pembaruan otomatis:
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();
// Perbarui token yang disimpan
return {
access_token: data.access_token,
refresh_token: data.refresh_token, // Selalu simpan refresh token baru
expires_in: data.expires_in
};
};
// Middleware untuk memastikan token valid sebelum panggilan API
const ensureValidToken = async (userId) => {
const user = await db.users.findById(userId);
// Periksa apakah token kedaluwarsa dalam waktu 5 menit
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;
};
Langkah 7: Melakukan Panggilan API Terautentikasi
Sertakan token akses dalam setiap permintaan:
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(`Kesalahan API Etsy: ${error.message}`);
}
return response.json();
};
Endpoint Manajemen Toko
Mengambil Informasi Toko
Ambil detail toko, kebijakan, dan pengaturan:
const getShopInfo = async (shopId) => {
const response = await makeEtsyRequest(`/shops/${shopId}`, {
method: 'GET'
});
return response;
};
// Penggunaan
const shop = await getShopInfo(12345678);
console.log(`Toko: ${shop.title}`);
console.log(`Mata Uang: ${shop.currency_code}`);
console.log(`Jumlah daftar produk: ${shop.num_listings_active}`);
Respons Toko yang Diharapkan
{
"shop_id": 12345678,
"shop_name": "MyHandmadeShop",
"title": "Perhiasan & Aksesori Buatan Tangan",
"announcement": "Selamat datang! Pengiriman gratis untuk pesanan di atas $50",
"currency_code": "USD",
"is_vacation": false,
"vacation_message": null,
"sale_message": "Terima kasih telah mendukung usaha kecil!",
"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"
}
Mengambil Bagian Toko
Atur daftar produk berdasarkan bagian:
const getShopSections = async (shopId) => {
const response = await makeEtsyRequest(`/shops/${shopId}/sections`, {
method: 'GET'
});
return response;
};
// Contoh respons
{
"count": 5,
"results": [
{
"shop_section_id": 12345,
"title": "Kalung",
"rank": 1,
"num_listings": 23
},
{
"shop_section_id": 12346,
"title": "Anting",
"rank": 2,
"num_listings": 45
}
]
}
Manajemen Daftar Produk
Membuat Daftar Produk Baru
Buat daftar produk dengan gambar dan variasi:
const createListing = async (shopId, listingData) => {
const payload = {
title: listingData.title,
description: listingData.description,
price: listingData.price.toString(), // Harus berupa string
quantity: listingData.quantity,
sku: listingData.sku || [],
tags: listingData.tags.slice(0, 13), // Maksimal 13 tag
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, dll.
is_supply: listingData.isSupply, // true untuk perlengkapan kerajinan
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, // pria, wanita, uniseks, dll.
occasion: listingData.occasion || null, // ulang tahun, pernikahan, dll.
style: listingData.style || [] // Maksimal 2 gaya
};
const response = await makeEtsyRequest(`/shops/${shopId}/listings`, {
method: 'POST',
body: JSON.stringify(payload)
});
return response;
};
// Contoh penggunaan
const listing = await createListing(12345678, {
title: 'Kalung Fase Bulan Perak Sterling',
description: 'Kalung perak sterling buatan tangan yang menampilkan fase bulan...',
price: 89.99,
quantity: 15,
sku: ['MOON-NECKLACE-001'],
tags: ['kalung bulan', 'perak sterling', 'fase bulan', 'perhiasan langit'],
categoryId: 10623, // Perhiasan > Kalung
sectionId: 12345,
state: 'active',
whoMade: 'i_did',
whenMade: 'made_to_order',
isSupply: false,
weight: 25,
weightUnit: 'g'
});
Mengunggah Gambar Daftar Produk
Gambar diunggah secara terpisah setelah pembuatan daftar produk:
const uploadListingImage = async (listingId, imagePath, imagePosition = 1) => {
// Baca file gambar sebagai base64
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: 'Kalung fase bulan perak sterling buatan tangan' // Untuk aksesibilitas
};
const response = await makeEtsyRequest(`/listings/${listingId}/images`, {
method: 'POST',
body: JSON.stringify(payload)
});
return response;
};
// Unggah beberapa gambar
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;
};
Memperbarui Inventaris Daftar Produk
Perbarui kuantitas untuk daftar produk yang sudah ada:
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;
};
// Penggunaan
await updateListingInventory(12345678, 987654321, {
products: [
{ sku: 'MOON-NECKLACE-001', quantity: 10 },
{ sku: 'MOON-NECKLACE-002', quantity: 5 }
],
isOverSelling: false
});
Mengambil Daftar Produk
Ambil semua daftar produk atau filter berdasarkan status:
const getListings = async (shopId, options = {}) => {
const params = new URLSearchParams({
limit: options.limit || 25, // Maksimal 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;
};
// Dapatkan satu daftar produk
const getListing = async (listingId) => {
const response = await makeEtsyRequest(`/listings/${listingId}`, {
method: 'GET'
});
return response;
};
Menghapus Daftar Produk
Hapus daftar produk dari toko Anda:
const deleteListing = async (listingId) => {
const response = await makeEtsyRequest(`/listings/${listingId}`, {
method: 'DELETE'
});
return response;
};
Manajemen Pesanan
Mengambil Pesanan
Ambil pesanan dengan opsi penyaringan:
const getOrders