Resources
Every resource family on the Gigadrive Network client, with its methods and the endpoint behind each one.
Each area of Gigadrive Network hangs off the client as a resource object, and every method maps to one HTTP endpoint. The names repeat across families, so list, get, create and delete mean the same thing wherever you meet them.
| Property | Covers | Feature docs |
|---|---|---|
client.organizations | organizations, members, product access, organization variables | Organizations |
client.applications | applications, hostnames, custom domains, variables, request logs | Getting started |
client.storage | buckets, objects, upload sessions, trash | File storage |
client.deployments | deployments, artifact upload, build logs | Deployments |
client.aiGateway | chat completions, responses, models, speech, transcription, video | AI Gateway |
client.apiKeys | application-scoped API keys | API keys |
client.stickySessions | signed URLs that pin related requests to one Function | Sticky sessions |
client.imageOptimization | managed image URLs and cache purge | Image optimization |
client.queues | queues, messages, leases, schedules | Queues |
client.microvms | microVMs, their commands, files and images | microVMs |
client.storage and client.applications.storage are the same object. Prefer client.storage.
Every example uses a client built as described in Authentication:
import { GigadriveClient } from '@gigadrive/sdk';
const client = new GigadriveClient();
const applicationId = process.env.GIGADRIVE_APPLICATION_ID as string;Organizations
| Method | Signature | Endpoint |
|---|---|---|
organizations.list | (query?: ListQuery) => Promise<Paginated<Organization>> | GET /organizations |
organizations.get | (organizationId: string) => Promise<Organization> | GET /organizations/{id} |
organizations.create | (input: CreateOrganizationInput) => Promise<Organization> | POST /organizations |
organizations.members.list | (organizationId, query?: ListQuery) => Promise<Paginated<OrganizationMember>> | GET /organizations/{id}/members |
organizations.products.list | (organizationId, query?: ListQuery) => Promise<Paginated<OrganizationProductAccess>> | GET /organizations/{id}/products |
organizations.products.get | (organizationId, product: string) => Promise<OrganizationProductAccess> | GET /organizations/{id}/products/{product} |
organizations.products.checkEntitlement | (organizationId, product: string) => Promise<OrganizationProductEntitlementCheck> | GET /organizations/{id}/products/{product}/entitlement |
organizations.envVars.list | (organizationId, query?: ListQuery) => Promise<Paginated<EnvVar>> | GET /organizations/{id}/env-vars |
organizations.envVars.create | (organizationId, data: CreateEnvVarInput) => Promise<EnvVar> | POST /organizations/{id}/env-vars |
organizations.envVars.update | (organizationId, envVarId, data: UpdateEnvVarInput) => Promise<EnvVar> | PATCH /organizations/{id}/env-vars/{varId} |
organizations.envVars.delete | (organizationId, envVarId) => Promise<void> | DELETE /organizations/{id}/env-vars/{varId} |
Membership is read-only here, and so is product access: the SDK cannot add a member, change a role, or activate a plan. create needs a user-backed token with platform:organizations:write, and the caller becomes the owner.
const org = await client.organizations.create({ name: 'Acme Corp' });
const { items: members } = await client.organizations.members.list(org.id);
const { hasAccess } = await client.organizations.products.checkEntitlement(org.id, 'office');
console.log(`${members.length} members, office access: ${hasAccess}`);Applications
| Method | Signature | Endpoint |
|---|---|---|
applications.list | (query?: ListApplicationsQuery) => Promise<Paginated<Application>> | GET /applications |
applications.create | (input: CreateApplicationInput) => Promise<CreatedApplication> | POST /applications |
applications.hostnames | (applicationId: string) => Promise<ApplicationHostnameList> | GET /applications/{id}/hostnames |
applications.checkHostnameAvailability | (applicationId: string, label: string) => Promise<HostnameAvailability> | GET /applications/{id}/hostname/availability |
applications.setProductionHostname | (applicationId: string, label: string) => Promise<SetProductionHostnameResult> | PUT /applications/{id}/hostname |
applications.envVars.list | (applicationId, query?: ListQuery) => Promise<Paginated<EnvVar>> | GET /applications/{id}/env-vars |
applications.envVars.pull | (applicationId, query?: PullEnvVarsQuery) => Promise<PullEnvVarsResult> | GET /applications/{id}/env-vars/pull |
applications.envVars.create | (applicationId, data: CreateEnvVarInput) => Promise<EnvVar> | POST /applications/{id}/env-vars |
applications.envVars.update | (applicationId, envVarId, data: UpdateEnvVarInput) => Promise<EnvVar> | PATCH /applications/{id}/env-vars/{varId} |
applications.envVars.delete | (applicationId, envVarId) => Promise<void> | DELETE /applications/{id}/env-vars/{varId} |
applications.requests.list | (applicationId, query?: ListRequestsQuery) => Promise<Paginated<NetworkRequestSummary>> | GET /applications/{id}/requests |
applications.requests.get | (applicationId, requestId) => Promise<NetworkRequest> | GET /applications/{id}/requests/{requestId} |
There is no applications.get(id) and no applications.delete(id). Filter list by organizationId to narrow it down.
pull merges the organization, application and environment layers into the values a deployment would see, and it never returns a sensitive value. It reports how many it skipped as omittedSensitive, so a build script can fail loudly instead of booting with a missing secret:
const { items, omittedSensitive } = await client.applications.envVars.pull(applicationId, {
environment: 'production',
});
if (omittedSensitive > 0) {
throw new Error(`${omittedSensitive} sensitive variables were not returned`);
}
for (const variable of items) {
console.log(`${variable.key} (from ${variable.source})`);
}Request logs are filtered through ListRequestsQuery: from, to, method, status, statusFamily, hostname, pathPrefix, country, cacheStatus, cacheHit, deploymentId, plus limit and cursor. get returns the same record with sanitized request and response headers attached. Request logs explains what each field means.
Custom domains
client.applications.domains manages the custom domains of an application, and client.organizations.domains manages the domains an organization verified with a TXT record. Custom domains explains the lifecycle and the DNS records.
| Method | Signature | Endpoint |
|---|---|---|
applications.domains.list | (applicationId, query?: ListQuery) => Promise<Paginated<CustomDomain>> | GET /applications/{id}/domains |
applications.domains.add | (applicationId, data: AddCustomDomainInput) => Promise<CustomDomain> | POST /applications/{id}/domains |
applications.domains.get | (applicationId, domainId, options?) => Promise<CustomDomain> | GET /applications/{id}/domains/{domainId} |
applications.domains.update | (applicationId, domainId, data: UpdateCustomDomainInput) => Promise<CustomDomain> | PATCH /applications/{id}/domains/{domainId} |
applications.domains.refresh | (applicationId, domainId) => Promise<CustomDomain> | POST /applications/{id}/domains/{domainId}/refresh |
applications.domains.remove | (applicationId, domainId) => Promise<void> | DELETE /applications/{id}/domains/{domainId} |
applications.domains.claim | (applicationId, hostname: string) => Promise<CustomDomain> | POST /applications/{id}/domains/claim |
applications.domains.waitUntilActive | (applicationId, domainId, options?: WaitUntilActiveOptions) => Promise<CustomDomain> | polls GET /applications/{id}/domains/{domainId} |
organizations.domains.list | (organizationId, query?: ListQuery) => Promise<Paginated<DomainOwnership>> | GET /organizations/{id}/domains |
organizations.domains.add | (organizationId, name: string) => Promise<DomainOwnership> | POST /organizations/{id}/domains |
organizations.domains.get | (organizationId, domainId) => Promise<DomainOwnership> | GET /organizations/{id}/domains/{domainId} |
organizations.domains.verify | (organizationId, domainId) => Promise<DomainOwnership> | POST /organizations/{id}/domains/{domainId}/verify |
organizations.domains.remove | (organizationId, domainId) => Promise<void> | DELETE /organizations/{id}/domains/{domainId} |
add returns the records to publish in requiredRecords. target chooses what the domain serves: { type: 'production' } (the default), { type: 'branch', branchId }, or { type: 'redirect', to, statusCode?, preservePath? }. update also accepts primary: true.
waitUntilActive polls every 5 seconds for up to 10 minutes, and returns once the domain is active or degraded. Set timeoutMs, intervalMs or signal to change that, or pass onState to follow each state change. Rate limits, server errors and network failures do not end the wait. It throws DomainNotActiveError when the domain fails, is suspended or removed, or the timeout runs out. Read error.reason (timeout, failed, suspended or removing) and error.domain.error?.message to see what to fix:
import { DomainNotActiveError } from '@gigadrive/sdk';
try {
await client.applications.domains.waitUntilActive(applicationId, domain.id, {
onState: (current) => console.log(current.state),
});
} catch (error) {
if (!(error instanceof DomainNotActiveError)) throw error;
console.error(error.reason, error.domain.error?.message);
}Deployments
| Method | Signature | Endpoint |
|---|---|---|
deployments.list | (query?: ListDeploymentsQuery) => Promise<Paginated<Deployment>> | GET /deployments |
deployments.get | (deploymentId: string) => Promise<Deployment> | GET /deployments/{id} |
deployments.create | (data: CreateDeploymentInput) => Promise<Deployment> | POST /deployments |
deployments.startUpload | (deploymentId: string) => Promise<StartUploadResult> | POST /deployments/{id}/upload/start |
deployments.getPresignedUrl | (deploymentId, uploadId, partNumber: number) => Promise<PresignedUrlResult> | POST /deployments/{id}/upload/part |
deployments.uploadPart | (presignedUrl, data: ArrayBuffer | Uint8Array | Blob, partNumber) => Promise<UploadPart> | PUT to the presigned URL |
deployments.completeUpload | (deploymentId, uploadId, parts: UploadPart[]) => Promise<void> | POST /deployments/{id}/upload/complete |
deployments.getLogs | (deploymentId, query?: ListDeploymentLogsQuery) => Promise<DeploymentLogPage> | GET /deployments/{id}/logs |
deployments.getHostnames | (deploymentId: string) => Promise<Paginated<Hostname>> | GET /deployments/{id}/hostnames |
status moves through PENDING, QUEUED, STARTING, BUILDING, PROVISIONING, and ends at ACTIVE or FAILED. A deployment created from an uploaded archive stays PENDING until the upload completes.
Uploading an artifact runs through create, startUpload, one presigned PUT per part, and completeUpload. Parts are numbered from 1, every part is sent as application/zip, and each returns the ETag that completeUpload needs:
import { readFileSync } from 'node:fs';
import type { UploadPart } from '@gigadrive/sdk';
const archive = readFileSync('./build.zip');
const deployment = await client.deployments.create({ applicationId });
const { uploadId } = await client.deployments.startUpload(deployment.id);
const partSize = 10 * 1024 * 1024;
const parts: UploadPart[] = [];
for (let offset = 0, partNumber = 1; offset < archive.byteLength; offset += partSize, partNumber++) {
const { url } = await client.deployments.getPresignedUrl(deployment.id, uploadId, partNumber);
parts.push(await client.deployments.uploadPart(url, archive.subarray(offset, offset + partSize), partNumber));
}
await client.deployments.completeUpload(deployment.id, uploadId, parts);Build output arrives through getLogs, which pages by offset and limit rather than by cursor. Errors and pagination has a loop that tails a build to its final status.
Storage
Buckets are addressed by name, the immutable identifier that is unique within an environment. The global slug is for CDN and S3 delivery and is not accepted here; bucket UUIDs still work but are deprecated.
The bucket and object methods in this table also have older overloads that take an application ID as the first argument. Set applicationId on the client, or run inside a Function, and you can omit it.
| Method | Signature | Endpoint |
|---|---|---|
storage.buckets.list | (query?: ListStorageBucketsQuery) => Promise<Paginated<StorageBucket>> | GET .../storage/buckets |
storage.buckets.create | (data: CreateStorageBucketInput) => Promise<StorageBucket> | POST .../storage/buckets |
storage.buckets.get | (bucketRef, options?: StorageEnvironmentOptions) => Promise<StorageBucket> | GET .../buckets/{bucket} |
storage.buckets.delete | (bucketRef, options?: StorageEnvironmentOptions) => Promise<void> | DELETE .../buckets/{bucket} |
storage.objects.list | (bucketRef, query?: ListStorageObjectsQuery) => Promise<StorageObjectList> | GET .../buckets/{bucket}/objects |
storage.objects.get | (bucketRef, objectId, options?) => Promise<StorageObject> | GET .../objects/{objectId} |
storage.objects.getByKey | (bucketRef, key, options?) => Promise<StorageObject | null> | pages a prefix listing |
storage.objects.delete | (bucketRef, objectId, options?) => Promise<void> | DELETE .../objects/{objectId} |
storage.objects.getAccessUrl | (bucketRef, objectId, options?: StorageObjectAccessOptions) => Promise<StorageObjectAccess> | GET .../objects/{objectId}/access-url |
storage.trash.list | (bucketRef, query?: ListStorageTrashQuery) => Promise<StorageTrashList> | GET .../buckets/{bucket}/trash |
storage.trash.restore | (bucketRef, objectId, options?) => Promise<StorageObject> | POST .../trash/{objectId}/restore |
storage.trash.purge | (bucketRef, objectId, options?) => Promise<void> | DELETE .../trash/{objectId} |
storage.trash.empty | (bucketRef, options?) => Promise<EmptyStorageTrashResult> | DELETE .../buckets/{bucket}/trash |
objects.delete is a soft delete that moves the object to the bucket trash, where restore can bring it back and purge removes it for good. Deleting the bucket takes live and trashed objects with it. Trash and restore covers the retention side.
New buckets are private unless you say otherwise, and a private object needs a signed URL from getAccessUrl:
const bucket = await client.storage.buckets.create({
name: 'invoices',
environment: 'production',
visibility: 'private',
});
const { items, commonPrefixes } = await client.storage.objects.list(bucket.name, {
prefix: '2026/',
delimiter: '/',
});
for (const object of items) {
const { url, expiresAt } = await client.storage.objects.getAccessUrl(bucket.name, object.id, {
expiresInSeconds: 3600,
});
console.log(object.key, url, `expires ${expiresAt}`);
}
console.log('folders:', commonPrefixes);Sending bytes is a subject of its own, in Uploading files.
AI Gateway
| Method | Signature | Endpoint |
|---|---|---|
aiGateway.chatCompletions | (data: ChatCompletionRequest, options?) => Promise<ChatCompletionResponse> | POST /ai/v1/chat/completions |
aiGateway.chatCompletionsWithResponse | (data, options?) => Promise<GatewayResult<ChatCompletionResponse>> | POST /ai/v1/chat/completions |
aiGateway.chatCompletionsStream | (data, options?) => AsyncGenerator<ChatCompletionChunk> | POST /ai/v1/chat/completions |
aiGateway.responses | (data: ResponsesRequest, options?) => Promise<ResponsesResponse> | POST /ai/v1/responses |
aiGateway.responsesStream | (data, options?) => AsyncGenerator<unknown> | POST /ai/v1/responses |
aiGateway.listModels | () => Promise<Paginated<AiModel>> | GET /ai/v1/models |
aiGateway.getModel | (modelId: string) => Promise<AiModel> | GET /ai/v1/models/{id} |
aiGateway.audio.speech | (data: SpeechRequest, options?) => Promise<ArrayBuffer> | POST /ai/v1/audio/speech |
aiGateway.audio.transcriptions | (data: TranscriptionRequest, options?) => Promise<TranscriptionResponse> | POST /ai/v1/audio/transcriptions |
aiGateway.videos.generations | (data: VideoGenerationRequest, options?) => Promise<VideoGenerationResponse> | POST /ai/v1/videos |
aiGateway.videos.listModels | () => Promise<VideoModelList> | GET /ai/v1/videos/models |
chatCompletions forces stream: false and chatCompletionsStream forces stream: true, so the stream field you pass is ignored either way.
for await (const chunk of client.aiGateway.chatCompletionsStream({
model: 'openai/gpt-4o',
messages: [{ role: 'user', content: 'Write a haiku about the sea.' }],
})) {
process.stdout.write(chunk.choices[0]?.delta.content ?? '');
}Use chatCompletionsWithResponse when you want the response object alongside the body: it returns data, the raw response, and the requestId the gateway puts in the X-Gigadrive-Request-Id header. The result type also declares costMicros, which is always undefined, because no endpoint returns a cost header. Spend per request comes from Analytics.
Governance lives under the organization, and is separate from inference:
| Method | Signature | Endpoint |
|---|---|---|
organizations.aiGateway.usage.summary | (organizationId, query?: AiGatewayUsageQuery) => Promise<AiGatewayUsageSummary> | GET .../ai-gateway/usage/summary |
organizations.aiGateway.usage.requests | (organizationId, query?: AiGatewayRequestsQuery) => Promise<Paginated<AiGatewayRequestEvent>> | GET .../usage/requests |
organizations.aiGateway.usage.export | (organizationId, query?: AiGatewayRequestsQuery) => Promise<string> | GET .../usage/export |
organizations.aiGateway.budgets.list | (organizationId) => Promise<{ items: AiGatewayBudget[] }> | GET .../budgets |
organizations.aiGateway.budgets.replace | (organizationId, budgets: AiGatewayBudgetInput[]) => Promise<{ items: AiGatewayBudget[] }> | PUT .../budgets |
organizations.aiGateway.policies.get | (organizationId, options?: { applicationId?: string }) => Promise<AiGatewayPolicy | null> | GET .../policies |
organizations.aiGateway.policies.put | (organizationId, data: AiGatewayPolicyInput) => Promise<AiGatewayPolicy> | PUT .../policies |
budgets.replace overwrites the whole set. Passing [] clears every budget on the organization. usage.export returns CSV text rather than JSON.
API keys
| Method | Signature | Endpoint |
|---|---|---|
apiKeys.create | (data: CreateApiKeyInput) => Promise<CreateApiKeyResult> | POST /api-keys |
apiKeys.list | (query: ListApiKeysQuery) => Promise<Paginated<ApiKey>> | GET /api-keys |
apiKeys.delete | (apiKeyId: string) => Promise<void> | DELETE /api-keys/{id} |
Keys are application-scoped, so applicationId is required on both create and list. Requested scopes must be a subset of the scopes your own token carries, and a key cannot be granted API key management scopes.
const key = await client.apiKeys.create({
name: 'ci',
applicationId,
scopes: ['network:deployments:trigger', 'network:deployments:read'],
});
// key.secret is returned once and cannot be read again.
const ci = new GigadriveClient({ clientId: key.id, clientSecret: key.secret });Omit expiresAt and the key expires in 90 days.
Sticky sessions
| Method | Signature | Endpoint |
|---|---|---|
stickySessions.createUrl | (input: CreateStickySessionUrlInput) => Promise<CreateStickySessionUrlResult> | POST /sticky-sessions/urls |
A sticky URL routes every request that uses it to the same Function, which is what makes in-memory state such as a WebSocket room work. It is routing authority and not user authentication, so keep your own authorization checks. expiresInSeconds defaults to 14400 and accepts 60 to 86400.
const { url, expiresAt } = await client.stickySessions.createUrl({
key: 'room-42',
endpoint: '/socket',
expiresInSeconds: 3600,
});
console.log(`join at ${url}, valid until ${expiresAt}`);Only a Function may mint one, and only for its own deployment.
Image optimization
| Method | Signature | Endpoint |
|---|---|---|
createManagedImageUrl | (options: ManagedImageUrlOptions) => string | none, it builds a URL locally |
imageOptimization.url | (options: ManagedImageUrlOptions) => string | none, it builds a URL locally |
imageOptimization.inspect | (deploymentId: string, source?: string) => Promise<ImageCacheInspection> | GET /deployments/{id}/image-cache |
imageOptimization.purge | (deploymentId: string, source?: string) => Promise<ImageCachePurgeResult> | DELETE /deployments/{id}/image-cache |
createManagedImageUrl is exported from the package root, so a component can build image URLs without holding a client. purge with no source clears every optimized image in the deployment.
import { createManagedImageUrl } from '@gigadrive/sdk';
const src = createManagedImageUrl({
origin: 'https://acme.gigadrive.app',
source: '/photos/hero.jpg',
width: 1280,
format: 'avif',
quality: 80,
});Queues
client.queues manages the queues of an application, and the top-level queue() function returns the same handle from a client it configures from the environment. Every endpoint sits under /applications/{id}/queues, shortened to .../queues in the following table.
| Method | Signature | Endpoint |
|---|---|---|
queues.queue | <T>(name: string, options?: QueueOptions<T>) => Queue<T> | none, it builds a handle locally |
queues.list | (options?: QueueScopeOptions) => Promise<{ items: QueueInfo[]; total: number }> | GET .../queues |
queues.get | (name, options?) => Promise<QueueInfo> | GET .../queues/{queue} |
queues.create | (name, settings?: QueueSettings, options?) => Promise<QueueInfo> | POST .../queues |
queues.ensure | (name, settings?: QueueSettings, options?) => Promise<QueueInfo & { created: boolean }> | PUT .../queues/{queue} |
queues.update | (name, settings: QueueSettings, options?) => Promise<QueueInfo> | PATCH .../queues/{queue} |
queues.delete | (name, options?) => Promise<{ purgedMessages: number }> | DELETE .../queues/{queue} |
queues.pause, queues.resume | (name, options?) => Promise<QueueInfo> | POST .../queues/{queue}/pause, POST .../queues/{queue}/resume |
queues.purge | (name, scope?: 'all' | 'dead', options?) => Promise<{ purgedMessages: number }> | POST .../queues/{queue}/purge |
queues.redrive | (name, messageIds?: string[], options?) => Promise<{ redrivenMessages: number }> | POST .../queues/{queue}/redrive |
queues.send | (name, message: QueueMessageInput, options?) => Promise<QueueSendResult> | POST .../queues/{queue}/messages |
queues.sendBatch | (name, messages: QueueMessageInput[], options?) => Promise<QueueSendResult[]> | POST .../queues/{queue}/messages |
queues.listMessages | (name, query?, options?) => Promise<{ items: QueueMessageRecord[]; total: number }> | GET .../queues/{queue}/messages |
queues.getMessage | (name, messageId, options?) => Promise<QueueMessageRecord> | GET .../queues/{queue}/messages/{messageId} |
queues.deleteMessage | (name, messageId, options?) => Promise<{ deleted: boolean }> | DELETE .../queues/{queue}/messages/{messageId} |
queues.receive | (name, request?, options?) => Promise<QueueMessageRecord[]> | POST .../queues/{queue}/messages/receive |
queues.ack | (name, messageId, receipt, options?) => Promise<{ acknowledged: boolean }> | POST .../queues/{queue}/messages/{messageId}/ack |
queues.ackBatch | (name, messages, options?) => Promise<{ results: QueueAckResult[] }> | POST .../queues/{queue}/messages/ack |
queues.nack | (name, messageId, request, options?) => Promise<QueueNackResult> | POST .../queues/{queue}/messages/{messageId}/nack |
queues.extend | (name, messageId, receipt, visibilityTimeoutSeconds, options?) => Promise<{ leaseExpiresAt: string }> | POST .../queues/{queue}/messages/{messageId}/extend |
queues.listSchedules | (name, options?) => Promise<{ items: QueueSchedule[]; total: number }> | GET .../queues/{queue}/schedules |
queues.createSchedule | (name, schedule, input, options?) => Promise<QueueSchedule> | POST .../queues/{queue}/schedules |
queues.updateSchedule | (name, schedule, input, options?) => Promise<QueueSchedule> | PATCH .../queues/{queue}/schedules/{schedule} |
queues.deleteSchedule | (name, schedule, options?) => Promise<{ deleted: boolean }> | DELETE .../queues/{queue}/schedules/{schedule} |
queues.triggerSchedule | (name, schedule, options?) => Promise<{ messageId: string }> | POST .../queues/{queue}/schedules/{schedule}/trigger |
options is a QueueScopeOptions: applicationId defaults to the client's application, and environment takes a slug or UUID. A deployed Function omits environment, because its credential selects the environment.
queue(name) returns the typed handle the Queues pages use for sending, push handlers and pull consumers. Prefer it to the raw methods, which take bodies as strings:
const emails = client.queues.queue<{ to: string }>('emails', { environment: 'production' });
await emails.send({ to: 'jane@example.com' }, { delay: '10m' });
const { items, total } = await client.queues.listMessages(
'emails',
{ state: 'scheduled', limit: 20 },
{ environment: 'production' }
);
console.log(`${items.length} of ${total} scheduled messages`);microVMs
MicroVM is exported from the package root and configures its client from the environment, like queue(). Pass client in its options to use a client you built yourself. client.microvms is the same API as plain request methods that return the JSON objects, client.microvms.images manages images, client.microvms.volumes manages volumes, and client.microvms.webhooks manages webhooks.
| Method | What it does | Endpoint |
|---|---|---|
MicroVM.create(options?) | Create a microVM and resolve once it is running | POST /microvms, then GET /microvms/{id} |
MicroVM.get(id) | Connect to an existing microVM | GET /microvms/{id} |
MicroVM.list(options?) | Iterate microVMs, newest first, across all pages | GET /microvms |
vm.run(cmd, args?, options?) | Run a command and resolve with its exit code and output | POST /microvms/{id}/commands |
vm.spawn(cmd, args?, options?) | Start a detached command and return a Command | POST /microvms/{id}/commands |
vm.commands.get(commandId), vm.commands.list() | Reattach to a detached command, or list them | GET /microvms/{id}/commands |
command.logs() | Stream the command's output, starting with what it already printed | GET /microvms/{id}/commands/{commandId}/logs |
command.output(), command.stdout(), command.stderr() | Collect the output until the command exits | GET /microvms/{id}/commands/{commandId}/logs |
command.wait() | Resolve when the command exits | POST /microvms/{id}/commands/{commandId}/wait |
command.kill(signal?) | Send a signal, SIGTERM by default | POST /microvms/{id}/commands/{commandId}/signal |
command.write(data), command.end(data?) | Write to the command's input, and close it | POST /microvms/{id}/commands/{commandId}/stdin |
command.resize(cols, rows) | Resize the command's terminal | POST /microvms/{id}/commands/{commandId}/resize |
vm.files.read(path), vm.files.readText(path) | Read a file as bytes or as text | GET /microvms/{id}/files/content |
vm.files.readStream(path) | Read a file as a stream | GET /microvms/{id}/files/content |
vm.files.write(path, content), vm.files.writeMany(files) | Write one file or several | PUT /microvms/{id}/files/content |
vm.files.list(path?, options?) | List a directory | GET /microvms/{id}/files |
vm.files.stat(path), vm.files.exists(path) | Describe a path, or check whether it exists | GET /microvms/{id}/files/stat |
vm.files.mkdir(path) | Create a directory and its parents | POST /microvms/{id}/files/mkdir |
vm.files.move(from, to) | Rename a file or directory | POST /microvms/{id}/files/move |
vm.files.remove(path, options?) | Delete a file, or a directory with recursive | DELETE /microvms/{id}/files |
vm.url(port) | The preview URL of an exposed port | none, it reads the created microVM |
vm.waitForPort(port, options?) | Resolve with the preview URL once a server answers on the port | requests the preview URL until it answers |
vm.refresh() | Read the microVM's current state | GET /microvms/{id} |
vm.getMetrics(options?) | CPU over a window, and memory and disk in use now | GET /microvms/{id}/metrics |
vm.extendTimeout(duration) | Push the automatic stop out, counted from now | POST /microvms/{id}/timeout |
vm.stop() | Stop the microVM, waiting until its volumes are saved | POST /microvms/{id}/stop |
vm.saveVolumes() | Save the attached volumes without stopping | POST /microvms/{id}/volumes/save |
vm.delete() | Delete the microVM, stopping it first if it runs | DELETE /microvms/{id} |
client.microvms.images.create(input) | Start building a custom image | POST /microvm-images |
client.microvms.images.waitUntilReady(id) | Resolve once the image is ready | GET /microvm-images/{id} |
client.microvms.images.list() | List the built-in and the application's custom images | GET /microvm-images |
client.microvms.images.get(id) | Read one image and its build status | GET /microvm-images/{id} |
client.microvms.images.delete(id) | Delete a custom image | DELETE /microvm-images/{id} |
client.microvms.volumes.create(input) | Create an empty volume | POST /microvm-volumes |
client.microvms.volumes.list(), .get(id) | List the application's volumes, or read one | GET /microvm-volumes |
client.microvms.volumes.rename(id, name) | Rename a volume | PATCH /microvm-volumes/{id} |
client.microvms.volumes.delete(id) | Delete a volume and its contents | DELETE /microvm-volumes/{id} |
client.microvms.webhooks.create(input) | Add a webhook; the result carries its signing secret | POST /microvm-webhooks |
client.microvms.webhooks.list(), .get(id) | List the application's webhooks, or read one | GET /microvm-webhooks |
client.microvms.webhooks.update(id, input) | Change the URL, events, description or enabled state | PATCH /microvm-webhooks/{id} |
client.microvms.webhooks.rotateSecret(id) | Replace the signing secret | POST /microvm-webhooks/{id}/secret |
client.microvms.webhooks.listDeliveries(id) | List the 50 most recent deliveries | GET /microvm-webhooks/{id}/deliveries |
client.microvms.webhooks.delete(id) | Delete a webhook | DELETE /microvm-webhooks/{id} |
verifyMicroVmWebhook({ body, headers, secret }) | Check a webhook request's signature and return its event | none, it runs in your endpoint |
MicroVM.create takes image, vcpus, memoryMb, diskMb, timeout, ports, env, metadata, network, volumes and applicationId, all optional. network: 'deny' blocks outbound traffic, and wait: false returns before the microVM is running. vm.run and vm.spawn take cwd, env, user, sudo, timeout, onStdout and onStderr. vm.run also takes stdin, throwOnError and signal, and vm.spawn takes stdin: true and pty. Commands and Files describe what each option does.
Durations such as timeout and extendTimeout take milliseconds or a string such as '30s', '10m' or '2h'.
A microVM is disposable, so declare it with await using and it stops when the scope ends, even when a command throws:
import { MicroVM } from '@gigadrive/sdk';
await using vm = await MicroVM.create({ image: 'python3.13', timeout: '10m' });
const { exitCode, stdout } = await vm.run('python', ['-c', 'print(sum(range(10)))']);
console.log(exitCode, stdout); // 0 "45\n"Failures throw typed errors, among them MicroVmNotRunningError, MicroVmNotFoundError, MicroVmFileNotFoundError, MicroVmQuotaExceededError, MicroVmStartError when the microVM fails to start, and MicroVmTimeoutError when a wait gives up.
