TypeScript SDK
The official SDK for the Hydra Commerce API. Fully typed, zero runtime dependencies, works in Node.js 18+, Bun, and Deno.
npm install @gethydra/sdk
Initialize the client
import { Hydra } from '@gethydra/sdk';
const hydra = new Hydra({ apiKey: 'sk_live_...' });
The client accepts these options:
| Option | Default | Description |
|---|---|---|
apiKey |
(required) | Your API key (sk_live_* or sk_test_*) |
baseUrl |
https://api.hydrajs.dev |
API base URL |
timeout |
80000 |
Request timeout in milliseconds |
maxNetworkRetries |
1 |
Max automatic retries on network/server errors |
appInfo |
undefined |
Integration metadata sent in User-Agent |
Both timeout and maxNetworkRetries can be overridden per-request.
Basic operations
Every resource follows the same pattern: list, get, create, update, delete.
List resources
const { data: products, pagination } = await hydra.products.list({
limit: 25,
status: 'active',
expand: ['variants', 'images'],
});
console.log(products.length, pagination.has_more);
Get a single resource
const { data: product } = await hydra.products.get('prod_abc123', {
expand: ['variants', 'images'],
});
Create a resource
const { data: product } = await hydra.products.create({
title: 'Classic T-Shirt',
status: 'active',
variants: [
{ title: 'Small', price: 2500, sku: 'TSHIRT-S' },
{ title: 'Medium', price: 2500, sku: 'TSHIRT-M' },
],
});
Update a resource
const { data: updated } = await hydra.products.update('prod_abc123', {
title: 'Premium T-Shirt',
});
Delete a resource
await hydra.products.delete('prod_abc123');
Pagination
List endpoints use cursor-based pagination. Every list resource has iterate() and toArray() methods built in.
Async iteration
for await (const product of hydra.products.iterate({ status: 'active' })) {
console.log(product.title);
}
Collect into an array
const allProducts = await hydra.products.toArray({ status: 'active' });
A safety cap of 10,000 items prevents unbounded memory growth. Pass { limit: N } to override:
const first100 = await hydra.products.toArray(
{ status: 'active' },
{ limit: 100 },
);
Low-level helpers
The paginate() and toArray() functions are also exported for advanced use cases:
import { paginate } from '@gethydra/sdk';
for await (const order of paginate((cursor) =>
hydra.orders.list({ limit: 50, cursor })
)) {
// process each order
}
Error handling
The SDK throws typed error classes for different failure modes:
import {
HydraNotFoundError,
HydraValidationError,
HydraRateLimitError,
HydraAuthenticationError,
} from '@gethydra/sdk';
try {
await hydra.products.get('prod_nonexistent');
} catch (err) {
if (err instanceof HydraNotFoundError) {
// 404 - resource doesn't exist
} else if (err instanceof HydraValidationError) {
// 400 - invalid request body
console.log(err.message);
} else if (err instanceof HydraRateLimitError) {
// 429 - too many requests
} else if (err instanceof HydraAuthenticationError) {
// 401 - invalid API key
}
}
All error classes extend HydraError, which has status, message, and code properties.
| Error class | HTTP status | When it’s thrown |
|---|---|---|
HydraAuthenticationError |
401 | Invalid or missing API key |
HydraPermissionError |
403 | Key lacks permission for this operation |
HydraNotFoundError |
404 | Resource doesn’t exist |
HydraValidationError |
400 | Request body fails validation |
HydraIdempotencyError |
409 | Conflicting idempotency key reuse |
HydraRateLimitError |
429 | Rate limit or quota exceeded |
HydraConnectionError |
- | Network failure or timeout |
Idempotency
POST requests can include an idempotency key to prevent duplicate creates:
const { data: order } = await hydra.orders.create(body, {
idempotencyKey: 'unique-key-123',
});
When maxNetworkRetries is greater than 0, the SDK auto-generates idempotency keys for POST requests to make retries safe.
Webhook verification
The SDK provides a separate entry point for verifying webhook signatures:
import { verifyWebhookSignature } from '@gethydra/sdk/webhooks';
const isValid = await verifyWebhookSignature(
rawBody,
request.headers.get('X-Hydra-Signature'),
webhookSecret,
);
if (!isValid) {
return new Response('Invalid signature', { status: 401 });
}
const event = JSON.parse(rawBody);
// handle event.type
This uses crypto.subtle for constant-time comparison and works across all runtimes (Node.js, Bun, Deno, Cloudflare Workers).
Available resources
| Resource | Property |
|---|---|
| Products | hydra.products |
| Variants | hydra.variants |
| Collections | hydra.collections |
| Cart | hydra.cart |
| Checkout | hydra.checkout |
| Search | hydra.search |
| Orders | hydra.orders |
| Fulfillments | hydra.fulfillments |
| Refunds | hydra.refunds |
| Returns | hydra.returns |
| Draft Orders | hydra.draftOrders |
| Customers | hydra.customers |
| Customer Groups | hydra.customerGroups |
| Addresses | hydra.addresses |
| Store Credit | hydra.storeCredit |
| Inventory | hydra.inventory |
| Locations | hydra.locations |
| Shipping | hydra.shipping |
| Promotions | hydra.promotions |
| Discounts | hydra.discounts |
| Images | hydra.images |
| Webhooks | hydra.webhooks |
| Store | hydra.store |
| Tags | hydra.tags |
| Redirects | hydra.redirects |
| Companies | hydra.companies |
| Purchase Orders | hydra.purchaseOrders |
| Fulfillment Orders | hydra.fulfillmentOrders |
| Metafields | hydra.metafields |
| Tax | hydra.tax |
| Exchange Rates | hydra.exchangeRates |
| Navigation | hydra.navigation |
| Notifications | hydra.notifications |
| Analytics | hydra.analytics |
TypeScript types
All API resource types are exported for use in your application:
import type { Product, Order, Customer, Variant } from '@gethydra/sdk';