SDK
타입 안전하고 프로덕션에 바로 사용할 수 있는 Headless Commerce API 클라이언트입니다.설치
- TypeScript / Node.js
- Python
npm install @headless-commerce/sdk
pnpm add @headless-commerce/sdk
yarn add @headless-commerce/sdk
pip install headless-commerce
poetry add headless-commerce
uv add headless-commerce
빠른 시작
- TypeScript
- Python
import { HeadlessCommerce } from '@headless-commerce/sdk';
// Admin 클라이언트 (서버 사이드)
const admin = new HeadlessCommerce({
secretKey: 'sk_test_your_key',
});
// Storefront 클라이언트 (클라이언트 사이드에서 안전하게 사용 가능)
const storefront = new HeadlessCommerce({
publishableKey: 'pk_test_your_key',
});
from headless_commerce import HeadlessCommerce
# 컨텍스트 매니저로 리소스를 안전하게 정리합니다
with HeadlessCommerce(api_key="sk_test_your_key") as client:
products = client.products.list({"limit": 10})
print(products["data"])
from headless_commerce import AsyncHeadlessCommerce
async with AsyncHeadlessCommerce(api_key="sk_test_your_key") as client:
products = await client.products.list({"limit": 10})
사용 예시
상품 목록 조회
- TypeScript
- Python
const { data, has_more } = await storefront.products.list({
status: 'active',
limit: 20,
});
// data: Product[] — 자동 완성이 지원되는 완전한 타입
result = client.products.list({
"q": "shirt",
"limit": 20,
})
# result["data"] — 상품 목록
# result["has_more"] — 추가 페이지 존재 여부
장바구니 플로우
- TypeScript
- Python
// 장바구니 생성
const cart = await storefront.carts.create({
session_id: 'guest-session-123',
});
// 상품 추가
await storefront.carts.addItem(cart.id, {
variant_id: 'var_001',
quantity: 2,
});
// 계산된 합계가 포함된 장바구니 조회
const updated = await storefront.carts.get(cart.id);
console.log(updated.summary.total);
// { amount: 78000, currency: "KRW" }
// 체크아웃
const order = await storefront.carts.checkout(cart.id, {
email: 'customer@example.com',
payment_provider: 'stripe',
payment_method_id: 'pm_xxx',
});
# 장바구니 생성
cart = client.carts.create()
# 상품 추가
cart = client.carts.add_item(cart["id"], {
"variant_id": "var_001",
"quantity": 2,
})
# 합계 확인
print(cart["summary"]["total"])
# {"amount": 78000, "currency": "KRW"}
# 체크아웃
order = client.checkout.create(cart["id"], {
"email": "customer@example.com",
"payment_provider": "stripe",
"payment_method_id": "pm_xxx",
})
관리자 작업
- TypeScript
- Python
// 옵션이 포함된 상품 생성
const product = await admin.products.create({
name: 'Classic T-Shirt',
type: 'physical',
status: 'draft',
options: [
{ name: 'Size', values: ['S', 'M', 'L'] },
{ name: 'Color', values: ['Black', 'White'] },
],
});
// 자동 페이지네이션
for await (const order of admin.orders.listAll({ status: 'confirmed' })) {
console.log(order.number);
}
# 상품 생성
product = client.products.admin_create({
"name": "Classic T-Shirt",
"type": "physical",
"status": "draft",
"options": [
{"name": "Size", "values": ["S", "M", "L"]},
{"name": "Color", "values": ["Black", "White"]},
],
})
# 자동 페이지네이션 (모든 페이지의 항목을 순회)
for product in client.products.admin_list_auto_paginate():
print(product["name"])
오류 처리
- TypeScript
- Python
import { HeadlessCommerceError } from '@headless-commerce/sdk';
try {
const product = await storefront.products.get('nonexistent');
} catch (error) {
if (error instanceof HeadlessCommerceError) {
console.log(`API 오류 ${error.status}: ${error.code} — ${error.message}`);
}
}
SDK는 HTTP 상태 코드에 매핑되는 타입 지정 예외를 발생시킵니다:모든 하위 클래스는
from headless_commerce import (
HeadlessCommerceError, # 기본 클래스 — 모든 오류를 포착
NotFoundError, # 404
ValidationError, # 400 / 422
AuthenticationError, # 401
RateLimitError, # 429
InternalServerError, # 500+
)
try:
product = client.products.get("nonexistent")
except NotFoundError as e:
print(f"찾을 수 없음: {e}")
except HeadlessCommerceError as e:
print(f"API 오류 {e.status}: {e.code} — {e}")
print(f"요청 ID: {e.request_id}")
HeadlessCommerceError를 상속하므로, 특정 오류를 개별적으로 처리하거나 한꺼번에 처리할 수 있습니다.웹훅 검증
- TypeScript
- Python
import crypto from 'node:crypto';
function verifyWebhook(payload: string, signature: string, secret: string): boolean {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
from headless_commerce import verify_webhook_signature
is_valid = verify_webhook_signature(
payload=request.body,
signature=request.headers["x-webhook-signature"],
secret="whsec_your_secret",
)
verify_webhook_signature(
payload=request.body,
signature=request.headers["x-webhook-signature"],
secret="whsec_your_secret",
timestamp=request.headers["x-webhook-timestamp"],
tolerance=300, # 5분 이상 경과한 요청 거부
)
설정
- TypeScript
- Python
| 옵션 | 타입 | 필수 | 설명 |
|---|---|---|---|
secretKey | string | * | 서버 사이드용 비밀 API 키 |
publishableKey | string | * | 클라이언트 사이드용 공개 키 |
baseUrl | string | 아니오 | 커스텀 API 기본 URL (기본값: https://api.headlesscommerce.io/v1) |
secretKey 또는 publishableKey 중 하나가 필수입니다.| 옵션 | 타입 | 필수 | 설명 |
|---|---|---|---|
api_key | str | 예 | API 키 (관리자용 sk_*, 스토어프론트용 pk_*) |
base_url | str | 아니오 | 커스텀 API 기본 URL (기본값: https://api.headlesscommerce.io/v1) |
max_retries | int | 아니오 | 429/5xx 오류 시 최대 재시도 횟수 (기본값: 2) |
timeout | float | 아니오 | 요청 타임아웃(초) (기본값: 30) |
http_client | httpx.Client | 아니오 | 프록시/mTLS/전송용 커스텀 httpx 클라이언트 |
재시도 동작
SDK는 다음 상황에서 자동으로 재시도합니다:- 429 Too Many Requests (
Retry-After헤더를 준수) - 5xx 서버 오류
- 네트워크 오류 및 타임아웃
리소스
총 23개의 API 리소스를 사용할 수 있습니다:| 리소스 | 스토어프론트 | 관리자 |
|---|---|---|
products | list, get, get_by_slug | CRUD, images, bundles |
categories | list, tree | CRUD |
collections | list, get | CRUD |
carts | create, get, items, discounts | — |
checkout | create | — |
orders | list, get, lookup | CRUD, confirm, cancel, complete |
customers | me, addresses | CRUD, tokens |
variants | — | CRUD |
inventory | — | get, adjust, set |
fulfillments | — | create, ship, deliver |
discounts | validate | CRUD |
shipping_methods | list | CRUD |
payments | — | record, complete |
returns | request, list, get | CRUD, approve, reject, receive |
refunds | — | create |
regions | — | CRUD, prices, currencies, locales, translations |
webhooks | — | CRUD, test |
api_keys | — | CRUD, rotate |
organization | — | get, update, members |
store | — | get, update |
logs | — | list, get, stats |
dashboard | — | stats |