SDK — Error handling

Every failure is a typed ApulodiError:

ts
import { ApulodiError } from "@apulodi/sdk";

try {
  await apulodi.files.get("file_missing");
} catch (error) {
  if (error instanceof ApulodiError) {
    error.status;     // HTTP status; 0 for network/timeout failures
    error.code;       // "FILE_NOT_FOUND"
    error.message;    // human-readable
    error.details;    // structured extras (validation issues, …)
  }
}

Properties

PropertyTypeMeaning
statusnumberHTTP status, or 0 when the network/transport failed
codestringStable machine-readable code (see Errors)
messagestringHuman-readable explanation
detailsunknownOptional structured context (Zod issues, …)
isClientErrorbooleanTrue for 4xx responses
isServerErrorbooleanTrue for 5xx responses

What never leaks

  • Your API key — scrubbed ([REDACTED]) from any error message or body.
  • Raw provider/database errors — the API converts them to INTERNAL_ERROR; the SDK re-checks in case a proxy returns something raw.
  • Internal stack traces — SDK errors carry a clean, stable message.

Network & timeouts

When fetch fails (DNS, connection refused, …) or the request times out, the SDK still throws ApulodiError with status: 0:

ts
catch (error) {
  if (error instanceof ApulodiError) {
    if (error.status === 0) {
      // NETWORK_ERROR or TIMEOUT — safe to retry
    } else if (error.isServerError) {
      // 5xx — exponential backoff retry
    }
  }
}
ts
const apulodi = new Apulodi({
  apiKey: process.env.APULODI_API_KEY!,
  timeoutMs: 15000, // per-request timeout
});

Retry with idempotency

files.upload() supports an optional Idempotency-Key for retry-safe upload initialization:

ts
const file = await apulodi.files.upload({
  file: data,
  fileName: "report.txt",
  contentType: "text/plain",
  idempotencyKey: crypto.randomUUID(),
});

Repeating the same key returns the same file instead of creating a duplicate.

Next: Guide — Upload from Next.js.