Configure the HTTP transport
Configure the HTTP transport
Every SDK call — client.receipts, client.devices, client.commands, and the rest — sends requests through a single shared HTTP transport. This page shows you how to configure it: pick an authentication method, set timeouts, handle errors, retry safely with idempotency keys, and rotate credentials at runtime.
Choose an authentication method
The SDK supports two auth methods. Pass either an API key or a bearer token when you construct the client.
Use an API key
API keys are the simplest option for server-to-server integrations.
import { EBonClient } from '@e-bon/sdk';
const client = new EBonClient({
baseUrl: 'https://api.e-bon.ro',
apiKey: process.env.EBON_API_KEY,
});
The SDK sends the key in the X-API-Key header on every request.
Use a bearer token
Use a JWT bearer token when you need short-lived credentials or per-user authentication.
import { EBonClient } from '@e-bon/sdk';
const client = new EBonClient({
baseUrl: 'https://api.e-bon.ro',
token: accessToken,
});
The SDK sends the token in Authorization: Bearer <token> on every request.
apiKey and token, the token wins — the API key is ignored. This matters when you migrate a long-lived client from API-key auth to JWT auth.Set timeouts
Requests fall back to a 30-second default. Override the client-wide timeout when you construct the client:
const client = new EBonClient({
baseUrl: 'https://api.e-bon.ro',
apiKey: process.env.EBON_API_KEY,
timeout: 10_000, // 10 seconds for every request
});
When a request exceeds the timeout, the SDK aborts the underlying fetch and throws EBonApiError with code === 'TIMEOUT' and status === 0.
Handle errors
Every error the SDK throws is an instance of EBonApiError. Branch on err.status (HTTP status code) to decide what to do — it's the most reliable field across all error types.
import { EBonApiError } from '@e-bon/sdk';
try {
const receipt = await client.receipts.create(body);
} catch (err) {
if (err instanceof EBonApiError) {
switch (err.status) {
case 0:
// Network error or timeout — safe to retry
console.error('Network problem:', err.message);
break;
case 401:
// Missing or expired credentials — refresh and retry
await refreshCredentials();
break;
case 422:
// Validation failed — inspect err.details
console.error('Validation errors:', err.details);
break;
case 429:
// Rate limited — wait err.retryAfter seconds
await sleep((err.retryAfter ?? 1) * 1000);
break;
default:
throw err;
}
}
}
Common status codes
| Status | Meaning | Recommended action |
|---|---|---|
0 | Network error or timeout | Retry with backoff |
401 | Unauthorized | Refresh credentials |
404 | Resource not found | Surface to the user |
422 | Validation failed | Inspect err.details |
429 | Rate limit hit | Wait err.retryAfter seconds |
500–599 | Server error | Retry with backoff |
err.retryAfter from the Retry-After response header (in seconds). For all other errors retryAfter is undefined.Retry safely with idempotency keys
POST and PATCH calls can produce duplicates if you retry them after a network failure. Send the same Idempotency-Key header on every retry attempt and the API returns the cached response within a 24-hour window — see the Idempotency reference for the full contract.
Wrap your write calls in a small helper that injects the header and retries on transient errors:
import { EBonClient, EBonApiError, type CreateReceiptBody, type Receipt } from '@e-bon/sdk';
import { randomUUID } from 'node:crypto';
async function createReceiptIdempotent(
client: EBonClient,
body: CreateReceiptBody,
): Promise<Receipt> {
const idempotencyKey = randomUUID();
let attempt = 0;
while (true) {
try {
return await client.receipts.create(body, {
headers: { 'Idempotency-Key': idempotencyKey },
});
} catch (err) {
attempt++;
const transient =
err instanceof EBonApiError &&
(err.status === 0 || err.status >= 500);
if (transient && attempt < 3) {
await sleep(2 ** attempt * 250);
continue;
}
throw err;
}
}
}
Rotate credentials at runtime
For long-lived clients, refresh the bearer token without rebuilding the client:
client.setToken(newAccessToken);
The next request picks up the new value. Requests already in flight keep the credentials they captured when they started — setToken does not abort or re-stamp them.
A typical refresh-on-401 pattern:
import { EBonApiError } from '@e-bon/sdk';
async function withRefresh<T>(call: () => Promise<T>): Promise<T> {
try {
return await call();
} catch (err) {
if (err instanceof EBonApiError && err.status === 401) {
const fresh = await refreshAccessToken();
client.setToken(fresh);
return await call();
}
throw err;
}
}
const receipt = await withRefresh(() => client.receipts.get(id));
Where to next
- SDK overview — the high-level shape of
EBonClientand the resource accessors. - Errors — the full
EBonApiErrorshape and the recommended retry pattern. - Events — real-time event delivery over WebSocket.
- Idempotency — wire-level rules for
Idempotency-Keyreuse and the 24-hour cache. - Rate limits — the
Retry-Aftersemantics on 429 responses. - API errors — the full HTTP code catalogue.