English · 中文 · Français · Español · Deutsch · Русский · 日本語 · 한국어
TypeScript SDK for the Caixuan platform. Integrate with the Caixuan API from Node.js services, scripts, or automation workflows.
npm install @caixuan-cc/sdkRequires Node.js >= 18.
import { createCaixuan } from '@caixuan-cc/sdk';
const client = createCaixuan({
token: process.env.CAIXUAN_TOKEN,
spaceId: process.env.CAIXUAN_SPACE_ID,
});
// Get current session
const session = await client.session.get();
// List spaces
const { rows: spaces } = await client.spaces.list();
// Upload a file and create a document
const file = await client.files.upload('./deck.pptx');
const doc = await client.docs.create({
spaceId: spaces[0].id,
fileId: file.id,
name: file.name,
});Create a client instance with createCaixuan():
import { createCaixuan, DEFAULT_ROOT } from '@caixuan-cc/sdk';
const client = createCaixuan({
root: DEFAULT_ROOT, // API root URL, default https://app.caixuan.cc/api
token: 'your-auth-token', // User token (X-Auth-Token header)
spaceId: 'space-id', // Current space ID (optional; resolved automatically if omitted)
userId: 'user-id', // User ID (optional)
lang: 'en', // Language: 'zh' | 'en'
basicAuth: 'user:pass', // nginx Basic Auth (optional)
onUnauthorized: async () => { // Refresh token on expiry (optional)
const newToken = await refreshToken();
return { token: newToken };
},
});You can also update credentials after the client is created:
client.setToken('new-token');
client.setSpaceId('space-id');
client.setUserId('user-id');
client.setBasicAuth('user:pass');- Complete OAuth login in the Caixuan web app
- Or use the CLI: run
caixuan login, thencaixuan config show
Most APIs require a spaceId. If none is provided at initialization, the SDK resolves it in this order:
- Explicitly set
spaceId defaultSpace.idfrom/session
Access resource APIs through namespaces on the client:
| Module | Description |
|---|---|
client.session |
Session (current user, logout) |
client.spaces |
Space list, details, switch |
client.shares |
Share link CRUD |
client.docs |
Document CRUD |
client.members |
Space member management |
client.files |
File upload |
const session = await client.session.get();
// session.id, session.defaultSpace, ...
await client.session.logout();const { rows, count } = await client.spaces.list();
const space = await client.spaces.get(); // Current space
const current = await client.spaces.current(); // From session
await client.spaces.select('space-id'); // Switch and set as defaultconst { rows } = await client.shares.list(undefined, { _startIndex: 0, _maxResults: 20 });
const share = await client.shares.get('share-id', ['content']);
const created = await client.shares.create({
spaceId: 'space-id',
name: 'My share',
description: 'Optional description',
content: [{ _type: 'doc', id: 'doc-id' }],
needPhone: 'no',
});
await client.shares.update({ id: 'share-id', name: 'New name', password: '1234' });
await client.shares.delete('share-id');const { rows } = await client.docs.list(undefined, { name: 'demo', tag: 'pptx' });
const doc = await client.docs.get('doc-id');
const created = await client.docs.create({
spaceId: 'space-id',
fileId: 'file-id',
name: 'demo.pptx',
folderId: '',
});
await client.docs.rename('doc-id', 'new-name.pptx');
await client.docs.delete('doc-id');
await client.docs.recover('doc-id');const { rows } = await client.members.list();
const member = await client.members.get(undefined, 'user-id');
await client.members.add({
spaceId: 'space-id',
role: 'teammate', // 'manager' | 'teammate' | 'guest'
email: 'user@example.com',
name: 'Jane Doe',
});
await client.members.updateRole(undefined, 'user-id', 'manager');
await client.members.rename(undefined, 'user-id', 'New name');
await client.members.remove(undefined, 'user-id');Supports local file paths or binary data, with automatic single-file and multipart upload:
// Upload a local file
const result = await client.files.upload('./presentation.pptx', {
spaceId: 'space-id',
onProgress: (pct) => console.log(`${Math.round(pct * 100)}%`),
});
// result: { id, name, bytes, hash }
// Upload binary data (name required)
const buffer = new Uint8Array(await fetch(url).then(r => r.arrayBuffer()));
const result2 = await client.files.upload(buffer, {
spaceId: 'space-id',
name: 'remote-file.pptx',
});Typical workflow: call files.upload() to get fileId, then docs.create() to create the document.
List endpoints return ListResult<T>:
interface ListResult<T> {
rows: T[];
count: number;
}Pagination parameters:
await client.shares.list(undefined, { _startIndex: 0, _maxResults: 50 });The SDK wraps API errors as APIError:
import { APIError, isRetriableError } from '@caixuan-cc/sdk';
try {
await client.docs.get('invalid-id');
} catch (err) {
if (err instanceof APIError) {
console.error(err.statusCode); // HTTP status code
console.error(err.code); // Business error code
console.error(err.requestId); // Request trace ID
console.error(err.requestUrl); // Request URL
console.error(err.requestPayload);// Request body
}
if (isRetriableError(err)) {
// Network errors or 502/604 — safe to retry
}
}The SDK automatically retries retriable errors (network timeouts, 502, 604) with exponential backoff.
On 401 Unauthorized, if onUnauthorized is configured, the SDK refreshes the token and retries the request.
import type {
CaixuanClient,
CreateCaixuanOptions,
MySpace,
SessionInfo,
ListResult,
CreateShareParams,
UpdateShareParams,
CreateDocParams,
AddMemberParams,
FileUploadResult,
} from '@caixuan-cc/sdk';