SDK
공식 TypeScript SDK(@fabhub/sdk)는 공개 OpenAPI 계약에 대해 생성되고 테스트되므로, 그 메서드가 공개 경로에서 절대 벗어나지 않습니다.
설치
npm install @fabhub/sdk
Node.js 22+가 필요합니다.
인증
API 키로 클라이언트를 구성합니다. OAuth로 발급된 액세스 토큰 자체가 pk_* 키이므로, 동일한 apiKey 옵션으로 전달하세요.
import { FabHubClient } from '@fabhub/sdk';
export const fabhub = new FabHubClient({
apiKey: process.env.FABHUB_API_KEY,
});
메서드
| Client method | Endpoint | Required scope |
|---|---|---|
getCapabilities | GET /v1 | authenticated |
getAuthContext | GET /v1/auth/context | authenticated |
listItems | GET /v1/items | items:read |
createItem | POST /v1/items | items:write |
getItem | GET /v1/items/{item_id} | items:read |
listItemIngredients | GET /v1/items/{item_id}/ingredients | items:read |
listItemSuppliers | GET /v1/items/{item_id}/suppliers | items:read |
createItemIngredient | POST /v1/items/{item_id}/ingredients | items:write |
updateItemIngredient | PATCH /v1/items/{item_id}/ingredients/{ingredient_id} | items:write |
createItemSupplier | POST /v1/items/{item_id}/suppliers | items:write |
updateItemSupplier | PATCH /v1/items/{item_id}/suppliers/{supplier_id} | items:write |
deleteItemIngredient | DELETE /v1/items/{item_id}/ingredients/{ingredient_id} | items:write |
deleteItemSupplier | DELETE /v1/items/{item_id}/suppliers/{supplier_id} | items:write |
getOrder | GET /v1/orders/{order_id} | orders:read |
listOrderLines | GET /v1/orders/{order_id}/lines | orders:read |
createOrder | POST /v1/orders | orders:write |
updateOrder | PATCH /v1/orders/{order_id} | orders:write |
updateItem | PATCH /v1/items/{item_id} | items:write |
deleteItem | DELETE /v1/items/{item_id} | items:write |
listOrders | GET /v1/orders | orders:read |
listContacts | GET /v1/contacts | contacts:read |
getContact | GET /v1/contacts/{contact_id} | contacts:read |
createContact | POST /v1/contacts | contacts:write |
updateContact | PATCH /v1/contacts/{contact_id} | contacts:write |
deleteContact | DELETE /v1/contacts/{contact_id} | contacts:write |
getOrganization | GET /v1/organization | organization:read |
getUsageSummary | GET /v1/usage | usage:read |
listStockLevels | GET /v1/stock-levels | inventory:read |
listStockDocuments | GET /v1/stock-documents | inventory:read |
getStockDocument | GET /v1/stock-documents/{document_id} | inventory:read |
createStockDocument | POST /v1/stock-documents | inventory:write |
listStockDocumentLines | GET /v1/stock-documents/{document_id}/lines | inventory:read |
createStockDocumentLine | POST /v1/stock-documents/{document_id}/lines | inventory:write |
updateStockDocumentLine | PATCH /v1/stock-documents/{document_id}/lines/{line_id} | inventory:write |
submitStockDocument | POST /v1/stock-documents/{document_id}/submit | inventory:write |
cancelStockDocument | POST /v1/stock-documents/{document_id}/cancel | inventory:write |
approveStockDocument | POST /v1/stock-documents/{document_id}/approve | inventory:write |
deleteStockDocument | DELETE /v1/stock-documents/{document_id} | inventory:write |
deleteStockDocumentLine | DELETE /v1/stock-documents/{document_id}/lines/{line_id} | inventory:write |
updateStockDocument | PATCH /v1/stock-documents/{document_id} | inventory:write |
listWebhooks | GET /v1/webhooks | webhooks:read |
createWebhook | POST /v1/webhooks | webhooks:write |
getWebhook | GET /v1/webhooks/{webhook_id} | webhooks:read |
updateWebhook | PATCH /v1/webhooks/{webhook_id} | webhooks:write |
deleteWebhook | DELETE /v1/webhooks/{webhook_id} | webhooks:delete |
listWebhookDeliveries | GET /v1/webhooks/{webhook_id}/deliveries | webhooks:deliveries:read |
listAuditEvents | GET /v1/audit/events | audit:read |
페이지네이션
let page = 1;
let totalPages = 1;
do {
const result = await fabhub.listItems({ page, pageSize: 100 });
// handle result.data
totalPages = result.pagination.totalPages;
page += 1;
} while (page <= totalPages);
멱등성 쓰기
const { data: item } = await fabhub.createItem(
{ name: 'Widget', itemType: 'product' },
{ idempotencyKey: crypto.randomUUID() },
);
타입이 지정된 오류
import { FabHubApiError } from '@fabhub/sdk';
try {
await fabhub.getItem('does-not-exist');
} catch (err) {
if (err instanceof FabHubApiError) {
console.error(err.status, err.code, err.message); // e.g. 404 NOT_FOUND ...
}
}
웹훅 서명 검증
import { verifyFabHubWebhookSignature } from '@fabhub/sdk';
const result = verifyFabHubWebhookSignature({
signingSecret: process.env.FABHUB_WEBHOOK_SECRET,
rawBody, // the exact raw request body string/bytes, before JSON parsing
timestamp: req.headers['x-fabhub-timestamp'],
signature: req.headers['x-fabhub-signature'],
});
if (!result.ok) {
// reject: result.reason explains why (e.g. 'invalid_signature')
}
드리프트 보호
SDK 작업 매핑은 CI에서 OpenAPI와 대조 검사되므로, 공개 SDK 메서드는 공개 경로에서 조용히 벗어나거나 내부 표면을 가리킬 수 없습니다.