TypeScript SDK
@tenergy/sdk is a typed client for the contract: one method per operationId, request and response types generated from openapi.yaml, and every request signed the way the API verifies it.
Published on npm as a beta, 0.1.0-beta.0 — npm install @tenergy/sdk; source at tenergyme/tenergy-js. Without a dependency, the tenergy() helper in the quickstart does the same signing in twenty lines of Node, Python or shell. Other languages: generate a client from openapi.yaml.
Before you begin
| What the SDK does | Why |
|---|---|
| Signs every call with a fresh timestamp, retries included | A signature is single-use: a reused one is 1009 replayed_signature |
| Serialises the body once and signs those bytes | A re-serialised body stops matching its signature (1002) |
Retries GET and DELETE on 429, 5xx or retryable, honouring Retry-After | Those calls are safe to repeat |
Sends POST and PATCH once | A create that timed out may have run; repeat it yourself with the same client_order_id |
Needs apiKey + apiSecret for every call except getOrderBook and the signup calls | For the other public reads without a key, call GET /v1/prices or /v1/estimate with plain fetch |
Step 1 — Create a client
import { TenergyClient } from "@tenergy/sdk";
const tenergy = new TenergyClient({
baseUrl: "https://api-nile.tenergy.me/v1", // https://api.tenergy.me/v1 on mainnet
apiKey: process.env.TENERGY_KEY!, // ak_test_… on Nile; the env names are examples, the SDK reads none itself
apiSecret: process.env.TENERGY_SECRET!, // shown once, when the key was created
});
| Option | Default | Meaning |
|---|---|---|
baseUrl | — (required) | Including /v1. Trailing slashes are stripped. |
apiKey, apiSecret | — | Required for signed calls. |
timeoutMs | 15000 | Per request. |
retry | { maxRetries: 2, baseDelayMs: 200, maxDelayMs: 5000 } | For idempotent calls only. |
fetch | globalThis.fetch | Any fetch-shaped function. |
Step 2 — Quote, order, wait
const quote = await tenergy.createQuote({
resource: "energy",
amount: 65_000,
tier: "1h",
receiver: "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
});
const order = await tenergy.createOrder({ quote_id: quote.id, client_order_id: "payout-8821" });
const settled = await tenergy.waitForOrder(order.id, { timeoutMs: 30_000 });
if (settled.partial) console.log("delivered", settled.delivered_amount, "of", settled.amount);
waitForOrder polls GET /v1/orders/{id} once a second until the order is active, expired, reclaimed, failed or refunded. It does not stop on confirmed: that state is transient and becomes active in the same instant; pass until to choose other states. On timeout it throws TenergyTimeoutError carrying the last order it saw — the order itself is not cancelled.
Step 3 — Handle errors
import { TenergyApiError, TenergyTransportError } from "@tenergy/sdk";
try {
await tenergy.createOrder({ quote_id: quote.id, client_order_id: "payout-8821" });
} catch (error) {
if (error instanceof TenergyApiError && error.slug === "insufficient_funds") {
// top up, then repeat the same call: the same client_order_id cannot charge twice
} else if (error instanceof TenergyTransportError) {
// the API did not answer: repeat with the same client_order_id
} else {
throw error;
}
}
| Class | When | Fields |
|---|---|---|
TenergyApiError | The API answered with an error envelope | code, slug, httpStatus, field, retryable, details, requestId, retryAfterSeconds |
TenergyTransportError | No answer, or one that is not an envelope (a proxy’s 502) | httpStatus, bodyExcerpt |
TenergyTimeoutError | waitForOrder ran out of time | waitedMs, last |
Branch on slug, never on message.
Step 4 — Verify a webhook
import { verifyWebhookSignature } from "@tenergy/sdk";
// rawBody: the request body exactly as received, before any JSON parsing
const valid = await verifyWebhookSignature(
process.env.TENERGY_WEBHOOK_SECRET!,
request.headers["x-api-timestamp"],
rawBody,
request.headers["x-api-sign"],
);
It checks the signature only; check that X-API-TIMESTAMP is within ±300 s yourself, as Webhooks shows.
Methods
| Area | Methods |
|---|---|
| Signup | createAccountChallenge, verifyAccountChallenge, createAccount, getSignupDepositAddress, bootstrap (all five steps in one call; your signMessage signs) |
| Account | getAccount, getBalance, listDepositAddresses |
| Pricing | getPrices, estimateOrder, getOrderBook, createQuote, getQuote |
| Orders | createOrder, listOrders, getOrder (our id or cid:<client_order_id>), reclaimOrder, waitForOrder |
| Batches | createBatch, listBatches, getBatch, cancelBatch |
| Subscriptions | createSubscription, listSubscriptions, getSubscription, updateSubscription, cancelSubscription |
| Webhooks | createWebhook, listWebhooks, getWebhook, updateWebhook, deleteWebhook, rotateWebhookSecret, testWebhook |
| Chain | getAddressResources, estimateTransferEnergy |
| API keys | listApiKeys, createApiKey, updateApiKey, deleteApiKey |
| Signing | signRequest, canonicalString, apiTimestamp, webhookSignature, verifyWebhookSignature |