Arke
Build

TypeScript SDK

Using the Arke TypeScript SDK for type-safe API interaction.

Installation

npm install @arke-institute/sdk

Configuration

The SDK is auto-generated from the OpenAPI specification using openapi-typescript and openapi-fetch, so types stay in sync with the API.

import { ArkeClient } from '@arke-institute/sdk';

// With JWT token (from Supabase auth)
const arke = new ArkeClient({
  authToken: 'your-jwt-token',
});

// With agent API key
const arke = new ArkeClient({
  authToken: 'ak_your-agent-api-key',
});

// With user API key
const arke = new ArkeClient({
  authToken: 'uk_your-user-api-key',
});

Configuration Options

interface ArkeClientConfig {
  // Base URL for the Arke API (default: 'https://api.arke.institute')
  baseUrl?: string;

  // Authentication token - JWT, agent key (ak_), or user key (uk_)
  // Authorization header format is auto-detected from token prefix
  authToken?: string;

  // Network to use: 'main' or 'test' (default: 'main')
  // Test network uses 'II' prefixed IDs and isolated data
  network?: 'main' | 'test';

  // Custom headers to include in all requests
  headers?: Record<string, string>;

  // Retry configuration (or false to disable)
  retry?: RetryConfig | false;
}

interface RetryConfig {
  maxRetries?: number;      // Default: 3
  initialDelay?: number;    // Default: 100ms
  maxDelay?: number;        // Default: 5000ms
  retryOn5xx?: boolean;     // Default: true
  retryOnNetworkError?: boolean;  // Default: true
  onRetry?: (attempt: number, error: Error, delayMs: number) => void;
}

Making API Calls

The SDK exposes the raw openapi-fetch client via arke.api, which provides type-safe GET, POST, PUT, and DELETE methods.

// Create an entity
const { data, error } = await arke.api.POST('/entities', {
  body: {
    collection_id: '01ABC...',
    type: 'file',
    properties: { label: 'My File' }
  }
});

if (error) {
  console.error('Failed to create entity:', error);
} else {
  console.log('Created entity:', data.id);
}

// Get an entity
const { data } = await arke.api.GET('/entities/{id}', {
  params: { path: { id: '01XYZ...' } }
});

// Update an entity (with CAS tip for optimistic locking)
const { data } = await arke.api.PUT('/entities/{id}', {
  params: { path: { id: '01XYZ...' } },
  body: {
    tip: 'bafyrei...',  // Current CID for compare-and-swap
    properties: { title: 'Updated Title' }
  }
});

// Delete an entity
const { data } = await arke.api.DELETE('/entities/{id}', {
  params: { path: { id: '01XYZ...' } }
});

File Content Methods

The SDK provides convenience methods for handling binary file content, since openapi-fetch doesn't automatically handle non-JSON responses.

// Get file content as Blob
const { data, error } = await arke.getFileContent('01ABC...');
if (data) {
  const text = await data.text();
}

// Get file content as ArrayBuffer
const { data, error } = await arke.getFileContentAsArrayBuffer('01ABC...');
if (data) {
  const bytes = new Uint8Array(data);
}

// Get file content as ReadableStream (for large files)
const { data, error } = await arke.getFileContentAsStream('01ABC...');
if (data) {
  const reader = data.getReader();
  // Process chunks...
}

// Upload file content
const blob = new Blob(['Hello, world!'], { type: 'text/plain' });
const { data, error } = await arke.uploadFileContent('01ABC...', blob, 'text/plain');

// Upload from ArrayBuffer or Uint8Array
const buffer = new TextEncoder().encode('Hello, world!').buffer;
const { data, error } = await arke.uploadFileContent('01ABC...', buffer, 'text/plain');

Client Utility Methods

// Update auth token (recreates underlying client)
arke.setAuthToken('new-token');

// Clear auth token
arke.clearAuthToken();

// Check authentication status
if (arke.isAuthenticated) {
  // Token is set
}

// Get base URL
console.log(arke.baseUrl);

// Get current config
const config = arke.getConfig();

Type Exports

The SDK exports the generated OpenAPI types for use in your application:

import type { paths, components, operations } from '@arke-institute/sdk';

// Use component schemas
type Entity = components['schemas']['Entity'];
type Collection = components['schemas']['Collection'];
type File = components['schemas']['File'];

// Use operation types for request/response
type CreateEntityBody = operations['createEntity']['requestBody']['content']['application/json'];

Error Classes

The SDK provides typed error classes for common API errors:

import {
  ArkeError,
  CASConflictError,
  NotFoundError,
  ValidationError,
  AuthenticationError,
  ForbiddenError,
  parseApiError,
} from '@arke-institute/sdk';

const { data, error } = await arke.api.PUT('/entities/{id}', {
  params: { path: { id: entityId } },
  body: { tip: oldTip, properties: { title: 'New Title' } }
});

if (error) {
  const apiError = parseApiError(error.status, error);

  if (apiError instanceof CASConflictError) {
    // Entity was modified - refresh and retry
    console.log('Expected tip:', apiError.expectedTip);
    console.log('Actual tip:', apiError.actualTip);
  } else if (apiError instanceof NotFoundError) {
    // Entity doesn't exist
  } else if (apiError instanceof ValidationError) {
    // Invalid request data
  } else if (apiError instanceof AuthenticationError) {
    // Token expired or invalid
  } else if (apiError instanceof ForbiddenError) {
    // Permission denied
  }
}

Upload Module

The SDK includes a high-level upload module for uploading folder trees:

import { ArkeClient } from '@arke-institute/sdk';
import { uploadTree, buildUploadTree } from '@arke-institute/sdk/operations';

const client = new ArkeClient({ authToken: 'your-token' });

// Build upload tree from file data (works in browser and Node.js)
const tree = buildUploadTree([
  { path: 'docs/readme.md', data: readmeBuffer },
  { path: 'images/logo.png', data: logoBlob },
]);

// Upload to a new collection
const result = await uploadTree(client, tree, {
  target: {
    createCollection: {
      label: 'My Upload',
      description: 'Uploaded folder contents',
    },
  },
  onProgress: (p) => console.log(`${p.phase}: ${p.phasePercent}%`),
});

console.log('Created collection:', result.collection.id);
console.log('Uploaded files:', result.files.length);

Upload Options

interface UploadOptions {
  target: {
    // Use existing collection
    collectionId?: string;
    // Parent folder/collection ID
    parentId?: string;
    // Or create a new collection
    createCollection?: {
      label: string;
      description?: string;
      roles?: Record<string, string[]>;
    };
  };

  // Progress callback
  onProgress?: (progress: UploadProgress) => void;

  // Max concurrent operations (default: 5)
  concurrency?: number;

  // Continue uploading even if some files fail (default: false)
  continueOnError?: boolean;

  // Max bytes in flight during upload (default: 200 MB)
  maxBytesInFlight?: number;

  // Custom note for created entities
  note?: string;
}

Browser File Scanning

import { scanFileSystemEntries, scanFileList } from '@arke-institute/sdk/operations';

// From drag-and-drop DataTransferItemList
const tree = await scanFileSystemEntries(dataTransfer.items);

// From file input FileList
const tree = await scanFileList(fileInput.files);

CID Utilities

import { computeCid, verifyCid } from '@arke-institute/sdk/operations';

// Compute CID for content (CIDv1, raw codec, SHA-256)
const cid = await computeCid(fileBuffer);

// Verify content matches expected CID
const isValid = await verifyCid(fileBuffer, expectedCid);

Factory Function

For functional style, use createArkeClient:

import { createArkeClient } from '@arke-institute/sdk';

const arke = createArkeClient({ authToken: 'your-token' });

See Also

On this page