API Client
Low-level API access using authenticated Connect RPC clients.
For operations beyond the high-level upload() and download() methods, you can create authenticated API clients that call the upl.im services directly. The SDK handles token management and authentication retry automatically.
Creating an API client
From an Upl instance
import { Upl } from '@xeonr/uploads-sdk';
import { BucketUploadsService } from '@xeonr/uploads-protocol/uplim/api/v1/uploads_pb';
const upl = new Upl({ clientId: 'your-client-id' });
// Option 1: Get a typed client directly
const uploads = upl.getApiClient(BucketUploadsService, {
interactive: true, // Allow popup login if token is missing
});
// Option 2: Get an adapter and create clients manually
const adapter = upl.getApiAdapter({ interactive: true });Using getUploadClientWithEnv
For use outside of the Upl class (e.g. in renderers or services), create clients from an adapter directly:
import { getUploadClientWithEnv } from '@xeonr/uploads-sdk/api/base';
import { BucketUploadsService } from '@xeonr/uploads-protocol/uplim/api/v1/uploads_pb';
const client = getUploadClientWithEnv(BucketUploadsService, adapter);The adapter can come from upl.getApiAdapter(), a renderer's apiAdapter, or a manually constructed IUploadAdapterEnv.
Adapter interface
interface IUploadAdapterEnv {
hostname?: string;
tokenHelper?: () => Promise<string | null>;
onAuthenticationExpired?: (retryCount: number) => Promise<boolean>;
onAuthenticationFailed?: () => Promise<any>;
extraHeaders?: () => Record<string, string>;
}| Field | Description |
|---|---|
hostname | API base URL |
tokenHelper | Returns the current access token (called on every request) |
onAuthenticationExpired | Called when a request returns Unauthenticated — return true to retry |
onAuthenticationFailed | Called when retry also fails |
extraHeaders | Additional headers to include on every request |
The SDK's auth interceptor:
- Adds
Authorization: Bearer {token}viatokenHelper - Adds any
extraHeaders - On
Unauthenticatederror: callsonAuthenticationExpired, retries if it returnstrue - On second failure: calls
onAuthenticationFailed
Available services
BucketUploadsService
File upload and management operations.
import { BucketUploadsService } from '@xeonr/uploads-protocol/uplim/api/v1/uploads_pb';
const uploads = getUploadClientWithEnv(BucketUploadsService, adapter);
// List uploads
const result = await uploads.listUploads({
bucketRef: { type: { case: 'bucketId', value: 'bkt_123' } },
path: '/',
pagination: { case: 'limit', value: 20 },
});
// Get a single upload
const { upload } = await uploads.getUpload({
bucketRef: { type: { case: 'bucketId', value: 'bkt_123' } },
uploadRef: { type: { case: 'uploadId', value: 'upl_456' } },
});
// Delete an upload
await uploads.deleteUpload({
bucketRef: { type: { case: 'bucketId', value: 'bkt_123' } },
uploadRef: { type: { case: 'uploadId', value: 'upl_456' } },
});
// Get download URL
const { url } = await uploads.getUploadDownloadUrl({
bucketRef: { type: { case: 'bucketId', value: 'bkt_123' } },
uploadRef: { type: { case: 'uploadId', value: 'upl_456' } },
});
// Get/set text content
const { content } = await uploads.getTextContent({
bucketRef: { type: { case: 'bucketId', value: 'bkt_123' } },
uploadRef: { type: { case: 'uploadId', value: 'upl_456' } },
});
// Copy/move uploads
await uploads.copyUpload({ /* ... */ });
await uploads.moveUpload({ /* ... */ });
// Upload history
const history = await uploads.listUploadHistory({ /* ... */ });
await uploads.restoreUploadFromHistory({ /* ... */ });BucketFoldersService
Folder and directory management.
import { BucketFoldersService } from '@xeonr/uploads-protocol/uplim/api/v1/uploads_pb';
const folders = getUploadClientWithEnv(BucketFoldersService, adapter);
// List folders
const result = await folders.listFolders({
bucketRef: { type: { case: 'bucketId', value: 'bkt_123' } },
path: '/',
});
// Create a folder
const { folder } = await folders.createFolder({
bucketRef: { type: { case: 'bucketId', value: 'bkt_123' } },
name: 'New Folder',
path: '/',
});
// Get folder tree
const tree = await folders.listFolderTree({
bucketRef: { type: { case: 'bucketId', value: 'bkt_123' } },
});BucketsService
Bucket-level operations, permissions, and bulk actions.
import { BucketsService } from '@xeonr/uploads-protocol/uplim/api/v1/uploads_pb';
const buckets = getUploadClientWithEnv(BucketsService, adapter);
// List buckets
const result = await buckets.listBuckets({});
// Get bucket details
const { bucket } = await buckets.getBucket({
bucketRef: { type: { case: 'bucketId', value: 'bkt_123' } },
});
// Bucket permissions
await buckets.grantBucketPermission({ /* ... */ });
await buckets.revokeBucketPermission({ /* ... */ });
// Bulk operations
await buckets.bulkMoveContent({ /* ... */ });
await buckets.bulkDeleteContent({ /* ... */ });
await buckets.bulkCopyContent({ /* ... */ });IntegrationsService
Integration and renderer resolution.
import { IntegrationsService } from '@xeonr/uploads-protocol/uplim/api/v1/uploads_pb';
const integrations = getUploadClientWithEnv(IntegrationsService, adapter);
// List available integrations
const result = await integrations.listIntegrations({});
// Resolve integrations for a resource
const resolved = await integrations.resolveResourceIntegrations({
bucketRef: { type: { case: 'bucketId', value: 'bkt_123' } },
target: { type: { case: 'uploadRef', value: { /* ... */ } } },
});AuthService
Token refresh (typically handled automatically by the SDK).
import { AuthService } from '@xeonr/uploads-protocol/uplim/api/v1/uploads_pb';
const auth = getUploadClientWithEnv(AuthService, adapter);
const { token } = await auth.refreshToken({ refreshToken: '...' });Reference patterns
Bucket references
Most API calls require a BucketRef to identify the bucket:
// By bucket ID
{ type: { case: 'bucketId', value: 'bkt_123' } }
// By hostname/alias
{ type: { case: 'hostname', value: 'my-bucket.upl.im' } }Upload references
// By upload ID
{ type: { case: 'uploadId', value: 'upl_456' } }
// By path
{ type: { case: 'path', value: '/images/photo.jpg' } }Folder references
// By folder ID
{ type: { case: 'folderId', value: 'fld_789' } }
// By path
{ type: { case: 'path', value: '/documents' } }Pagination
List endpoints support cursor-based or limit-based pagination:
// Limit-based (first page)
const page1 = await uploads.listUploads({
bucketRef: { type: { case: 'bucketId', value: 'bkt_123' } },
pagination: { case: 'limit', value: 20 },
});
// Cursor-based (subsequent pages)
const page2 = await uploads.listUploads({
bucketRef: { type: { case: 'bucketId', value: 'bkt_123' } },
pagination: { case: 'cursor', value: page1.nextCursor },
});