TL;DR
API Etsy memudahkan pengembang membangun aplikasi yang terintegrasi dengan marketplace Etsy. Dengan autentikasi OAuth 2.0, endpoint RESTful untuk toko, daftar produk, pesanan, dan manajemen inventaris, serta rate limit 10 panggilan/detik/aplikasi, integrasi ini sangat cocok untuk otomatisasi e-commerce. Artikel ini membahas setup autentikasi, endpoint inti, integrasi webhook, dan panduan penerapan untuk production.
Pendahuluan
Etsy memproses penjualan barang lebih dari $13 miliar/tahun di 230+ negara. Untuk pengembang yang membangun alat e-commerce, sistem inventaris, atau platform analitik, integrasi API Etsy sangat penting.
Fakta lapangan: Penjual yang mengelola multi-channel bisa kehilangan 15-20 jam/minggu hanya untuk entri data manual. Integrasi API Etsy yang baik akan otomatisasi sinkronisasi listing, pemrosesan order, dan update inventaris lintas platform.
Panduan ini fokus pada implementasi: mulai dari autentikasi OAuth 2.0, pengelolaan toko dan listing, manajemen pesanan, webhook, sampai troubleshooting. Setelah mengikuti langkah di bawah, integrasi Etsy Anda siap produksi.
💡 Tips: Apidog mempercepat pengujian integrasi API. Uji endpoint Etsy, validasi alur OAuth, cek payload webhook, dan debug autentikasi dalam satu workspace. Import spesifikasi API, mock response, dan kolaborasi dengan tim jadi lebih mudah.
Apa Itu API Etsy?
Etsy menyediakan API RESTful untuk akses data marketplace dan pengelolaan operasional penjual. Fungsionalitas utama meliputi:
- Mendapatkan info toko dan profil
- Membuat/memperbarui listing dan inventaris
- Pengelolaan pesanan dan pelacakan pengiriman
- Akses data pelanggan dan transaksi
- Manajemen pengiriman dan perpajakan
- Upload gambar dan media
Fitur Utama
| Fitur | Deskripsi |
|---|---|
| Desain RESTful | HTTP method standar, respons JSON |
| OAuth 2.0 | Autentikasi aman, refresh token akses otomatis |
| Webhooks | Notifikasi real-time untuk order dan list event |
| Rate Limiting | 10 permintaan/detik/aplikasi (dengan burst allowance) |
| Sandbox Support | Lingkungan pengujian bebas data produksi |
Ikhtisar Arsitektur API
Struktur endpoint:
https://openapi.etsy.com/v3/application/
Gunakan versi 3 (v3) untuk fitur terbaru dan dukungan OAuth 2.0 yang optimal.
Perbandingan Versi API
| Versi | Status | Autentikasi | Use Case |
|---|---|---|---|
| V3 | Aktif | OAuth 2.0 | Semua integrasi baru |
| V2 | Usang | OAuth 1.0a | App legacy |
| V1 | Retired | N/A | Jangan digunakan |
Catatan: Segera migrasikan integrasi V2 ke V3. Etsy akan sepenuhnya menutup V2 pada akhir 2026.
Memulai: Pengaturan Autentikasi
Langkah 1: Buat Akun Pengembang Etsy
- Kunjungi Portal Pengembang Etsy
- Login dengan akun Etsy (atau daftar baru)
- Navigasi ke Aplikasi Anda di dashboard developer
- Klik Buat aplikasi baru
Langkah 2: Daftarkan Aplikasi
Isi form pendaftaran:
- Nama Aplikasi: Nama jelas & deskriptif (muncul saat OAuth)
- Deskripsi: Jelaskan fungsi dan target pengguna
- Redirect URI: Endpoint callback (wajib HTTPS)
- Mode: Mulai dengan development/testing
Setelah submit, dapatkan:
- Key String: ID publik API
- Shared Secret: Rahasia API (jangan dipublish)
Best Practice: Simpan kredensial di variabel environment, bukan dalam kode.
# .env file
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
Alur OAuth Etsy:
1. User klik "Connect with Etsy" di aplikasi Anda
2. Redirect ke otorisasi Etsy
3. User login dan grant izin
4. Etsy redirect kembali ke app Anda dengan kode otorisasi
5. Tukarkan kode dengan access token
6. Gunakan access token untuk API call
7. Refresh token saat access token expired (1 jam)
Langkah 4: Implementasi 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 (Scopes)
Request hanya scope yang diperlukan aplikasi Anda.
| Scope | Deskripsi | Use Case |
|---|---|---|
listings_r |
Baca listing | Sinkronisasi produk |
listings_w |
Tulis listing | Buat/update produk |
orders_r |
Baca pesanan | Manajemen/fulfillment order |
orders_w |
Update pesanan | Update status/order tracking |
shops_r |
Baca info toko | Profil/analitik toko |
transactions_r |
Baca transaksi | Pelaporan keuangan |
email |
Akses email pembeli | Komunikasi pesanan |
Langkah 5: Tukar Kode dengan Access Token
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 safely di database
return {
access_token: data.access_token,
refresh_token: data.refresh_token,
expires_in: data.expires_in,
user_id: data.user_id,
scope: data.scope
};
};
// Handle callback
app.get('/callback', async (req, res) => {
const { code, state } = req.query;
// Validasi state (CSRF protection)
if (state !== req.session.oauthState) {
return res.status(400).send('Invalid state parameter');
}
try {
const tokens = await exchangeCodeForToken(code, 'https://your-app.com/callback');
// Save token ke database user
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: Refresh Token Otomatis
Access token berlaku 1 jam, refresh otomatis sebelum expired.
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();
// Update token di database
return {
access_token: data.access_token,
refresh_token: data.refresh_token,
expires_in: data.expires_in
};
};
// Middleware validasi token
const ensureValidToken = async (userId) => {
const user = await db.users.findById(userId);
// Jika token expired dalam 5 menit, refresh
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: Panggilan API Terautentikasi
Setiap request API Etsy harus menyertakan token akses.
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
Mendapatkan Informasi Toko
Ambil detail toko, kebijakan, dan pengaturan:
const getShopInfo = async (shopId) => {
const response = await makeEtsyRequest(`/shops/${shopId}`, {
method: 'GET'
});
return response;
};
// Contoh penggunaan
const shop = await getShopInfo(12345678);
console.log(`Toko: ${shop.title}`);
console.log(`Mata Uang: ${shop.currency_code}`);
console.log(`Jumlah produk aktif: ${shop.num_listings_active}`);
Contoh respons:
{
"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"
}
Mendapatkan Bagian Toko
Kategorikan listing berdasarkan section toko:
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 Listing Produk Baru
Buat listing produk lengkap dengan gambar dan variasi:
const createListing = async (shopId, listingData) => {
const payload = {
title: listingData.title,
description: listingData.description,
price: listingData.price.toString(),
quantity: listingData.quantity,
sku: listingData.sku || [],
tags: listingData.tags.slice(0, 13),
category_id: listingData.categoryId,
shop_section_id: listingData.sectionId,
state: listingData.state || 'active',
who_made: listingData.whoMade,
when_made: listingData.whenMade,
is_supply: listingData.isSupply,
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,
occasion: listingData.occasion || null,
style: listingData.style || []
};
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,
sectionId: 12345,
state: 'active',
whoMade: 'i_did',
whenMade: 'made_to_order',
isSupply: false,
weight: 25,
weightUnit: 'g'
});
Upload Gambar Listing
Setelah membuat listing, upload gambar menggunakan endpoint terpisah.
const uploadListingImage = async (listingId, imagePath, imagePosition = 1) => {
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'
};
const response = await makeEtsyRequest(`/listings/${listingId}/images`, {
method: 'POST',
body: JSON.stringify(payload)
});
return response;
};
// Untuk upload 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;
};
Update Inventaris Listing
Update kuantitas produk:
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;
};
// Contoh 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 listing atau filter berdasarkan status:
const getListings = async (shopId, options = {}) => {
const params = new URLSearchParams({
limit: options.limit || 25,
offset: options.offset || 0
});
if (options.state) {
params.append('state', options.state);
}
const response = await makeEtsyRequest(
`/shops/${shopId}/listings?${params.toString()}`,
{ method: 'GET' }
);
return response;
};
// Ambil satu listing
const getListing = async (listingId) => {
const response = await makeEtsyRequest(`/listings/${listingId}`, {
method: 'GET'
});
return response;
};
Hapus Listing
Menghapus listing dari toko:
const deleteListing = async (listingId) => {
const response = await makeEtsyRequest(`/listings/${listingId}`, {
method: 'DELETE'
});
return response;
};
Manajemen Pesanan
Mengambil Pesanan
Ambil order dengan filter (lanjutkan sesuai kebutuhan):
const getOrders
Lanjutkan pengembangan dengan menambahkan endpoint pesanan, webhook, dan strategi deployment production. Gunakan Apidog untuk mempercepat pengujian dan debugging seluruh integrasi API Etsy Anda.
Top comments (0)