EdgeStore

Low-level SDK

Use the supported API v2 SDK directly from server-side TypeScript.

@edgestore/sdk is the public, low-level client for EdgeStore API v2. Use it when you need API operations that are not tied to an EdgeStore router. For router-derived bucket names, input, path, and metadata types, use the backend client instead.

The SDK is server-only. Project secrets and management tokens must never be included in browser bundles.

Project client

Project credentials expose runtime operations for the credential's current project. The reserved project selector is handled internally.

import { createEdgeStoreSdk } from '@edgestore/sdk';

const sdk = createEdgeStoreSdk({
  credentials: {
    accessKey: process.env.EDGE_STORE_ACCESS_KEY!,
    secretKey: process.env.EDGE_STORE_SECRET_KEY!,
  },
});

const file = await sdk.runtime.uploads.upload({
  bucket: 'documents',
  source: pdfBlob,
  fileName: 'invoice.pdf',
  metadata: { invoiceId: invoice.id },
  signal,
  onProgress: ({ percentage, phase }) => {
    console.log(phase, percentage);
  },
});

The upload helper selects single or multipart upload automatically, reports progress, supports cancellation, and waits for upload processing to finish. Upload creation is never retried because it is not idempotent. Signed storage transfers may be retried safely, and processing polls follow Retry-After. You can also use runtime.uploads.request, createParts, and completeMultipart when you need to manage transfer details yourself.

Sources can be text, a Blob, an ArrayBuffer or typed-array view, or a known-size Web ReadableStream:

await sdk.runtime.uploads.upload({
  bucket: 'archives',
  source: { stream, sizeBytes },
  fileName: 'archive.tar',
});

await sdk.runtime.uploads.uploadFromUrl({
  bucket: 'imports',
  url: 'https://example.com/report.csv',
});

The defaults are a 100 MiB multipart threshold, 16 MiB parts, concurrency 4, a 30-second control timeout, no transfer timeout, and a 60-second processing timeout. Configure upload defaults with the upload option on createEdgeStoreSdk; pass an AbortSignal for per-operation cancellation or deadlines.

Runtime resources

const page = await sdk.runtime.files.search({
  bucket: 'documents',
  filter: { metadata: { ownerId: user.id } },
  pagination: { limit: 50 },
});

if (page.pagination.hasMore) {
  const nextPage = await sdk.runtime.files.search({
    bucket: 'documents',
    pagination: {
      cursor: page.pagination.nextCursor ?? undefined,
      limit: 50,
    },
  });
}

const { signedUrls } = await sdk.runtime.files.generateSignedReadUrls({
  bucket: 'documents',
  urls: page.files.map((file) => file.url),
  expiresIn: 15 * 60,
});

await sdk.runtime.files.confirm({ file: { id: file.file.id } });
await sdk.runtime.files.delete({ file: { key: file.file.key } });

const batch = await sdk.runtime.files.deleteMany({
  files: [{ id: file.file.id }, { url: legacyFileUrl }],
});

for (const result of batch.results) {
  if (!result.success) console.error(result.fileRef, result.error.code);
}

Runtime resources also include projects, buckets, file lookup, signed read URLs, access tokens, upload inspection, cancellation, and singular or plural restore operations. Singular mutations throw EdgeStoreFileMutationError for an item failure; plural mutations return the complete partial result.

Management client

A management token uses Bearer authentication and exposes account, project, credential, token, and membership resources. Runtime calls can select a project per operation or create an eagerly scoped runtime client once.

const management = createEdgeStoreSdk({
  credentials: {
    token: process.env.EDGE_STORE_MANAGEMENT_TOKEN!,
  },
});

const projects = await management.management.projects.list({
  account: 'account-id',
});

const project = management.runtime.forProject(projects.projects[0]!.id);
const buckets = await project.buckets.list();

// An explicit selector remains useful for one-off calls.
const anotherProject = await management.runtime.projects.get({
  project: 'another-project-id',
});

const { accessUrls } =
  await management.management.files.generateAccessUrls({
    project: projects.projects[0]!.id,
    files: [{ id: 'file-id' }],
    expiresIn: 15 * 60,
  });

Reusing SDK types

Common runtime workflows have named public input and result types:

import type {
  RuntimeFileLookupInput,
  RuntimeFileLookupResult,
  RuntimeSignedReadUrlsGenerateInput,
  RuntimeSignedReadUrlsGenerateResult,
  RuntimeUploadInput,
  RuntimeUploadResult,
} from '@edgestore/sdk';

For any other operation, derive its friendly input and resolved output from the public SDK interface. This includes SDK selectors such as account, project, and bucket, plus signal.

import type { ManagementEdgeStoreSdk } from '@edgestore/sdk';

type CreateProjectMethod =
  ManagementEdgeStoreSdk['management']['projects']['create'];

type CreateProjectInput = Parameters<CreateProjectMethod>[0];
type CreateProjectOutput = Awaited<ReturnType<CreateProjectMethod>>;

You can use the same pattern with a configured SDK value:

type LookupInput = Parameters<typeof sdk.runtime.files.lookup>[0];
type LookupOutput = Awaited<
  ReturnType<typeof sdk.runtime.files.lookup>
>;

The generated OpenAPI operation types remain internal. Deriving from the public interface keeps application types aligned with the supported SDK surface.

Errors

import { EdgeStoreApiError, EdgeStoreNetworkError } from '@edgestore/sdk';

try {
  await sdk.runtime.files.lookup({ file: { url } });
} catch (error) {
  if (error instanceof EdgeStoreApiError) {
    console.error(error.status, error.code, error.requestId);
  } else if (error instanceof EdgeStoreNetworkError) {
    console.error('The API could not be reached', error.cause);
  }
}

API errors preserve the HTTP status, machine-readable code, details, request ID, and retry guidance. Abort, network, upload, cancellation, and processing timeout errors have dedicated classes.

Custom environments

Use apiUrl for a compatible API v2 deployment and fetch to provide a custom server-side transport implementation.

const sdk = createEdgeStoreSdk({
  credentials: { accessKey, secretKey },
  apiUrl: 'https://api.example.com/v2',
  fetch: instrumentedFetch,
});

apiUrl is the complete v2 URL. The SDK does not append /v2 to an explicit value.

On this page