Skip to main content

SDK

Official TypeScript/JavaScript SDK for AnyDB. Provides a type-safe way to interact with the AnyDB API to manage records, databases, teams, and files programmatically.

Installation

npm install anydb-api-sdk-ts

Getting Your API Key

Before using the SDK, you'll need to obtain your API key:

  1. Log in to your AnyDB account at app.anydb.com
  2. Click on the user icon in the bottom right corner
  3. Navigate to the Integration tab in the Profile Dialog
  4. Copy your API key
warning

Keep your API key secure. Never commit it to version control or share it publicly.

Quick Start

import { AnyDBClient } from "anydb-api-sdk-ts";

// Initialize the client
const client = new AnyDBClient({
apiKey: "your-api-key",
userEmail: "user@example.com",
baseURL: "https://app.anydb.com/api", // Optional
});

// List teams
const teams = await client.listTeams();
console.log("Teams:", teams);

// Get a record
const record = await client.getRecord("teamid", "adbid", "adoid");
console.log("Record:", record);

Features

Full TypeScript support with type definitions
Record operations - CRUD operations for AnyDB records
File management - Upload and download files from record cells
Team & database discovery - List teams and databases
Search functionality - Search records by keyword
Error handling - Comprehensive error messages
Debug mode - Optional request/response logging

Client Configuration

Initialize the Client

const client = new AnyDBClient({
apiKey: string, // Required: Your AnyDB API key
userEmail: string, // Required: User email for authentication
baseURL: string, // Optional: API base URL (default: http://localhost:3000/api)
timeout: number, // Optional: Request timeout in ms (default: 30000)
});

Debug Mode

Enable debug logging to see all API requests and responses:

DEBUG_ANYDB=1 node your-script.js

API Reference

Team & Database Operations

List Teams

Get all teams accessible with your credentials.

const teams = await client.listTeams();
// Returns: Team[]

Response:

[
{
teamid: "507f1f77bcf86cd799439011",
name: "My Team",
description: "Team description",
},
];

List Databases for Team

Get all databases within a team.

const databases = await client.listDatabasesForTeam("teamid");
// Returns: ADB[]

Response:

[
{
adbid: "507f1f77bcf86cd799439012",
name: "My Database",
teamid: "507f1f77bcf86cd799439011",
},
];

Record Operations

List Records

List all records in a database with optional filtering and pagination.

const response = await client.listRecords(
"teamid",
"adbid",
"parentid", // Optional: Filter by parent record
"templateid", // Optional: Filter by template
"templatename", // Optional: Filter by template name
"50", // Optional: Page size (default: 50)
"lastmarker" // Optional: Pagination marker from previous response
);

console.log(response.items); // Array of records
console.log(response.total); // Total count
console.log(response.hasmore); // Has more pages
console.log(response.lastmarker); // Marker for next page

Example - Paginated List:

// Get first page
const page1 = await client.listRecords("teamid", "adbid");

// Get next page using lastmarker
if (page1.hasmore) {
const page2 = await client.listRecords(
"teamid",
"adbid",
undefined,
undefined,
undefined,
"50",
page1.lastmarker
);
}

Get Record

Get a specific record with all its data.

const record = await client.getRecord("teamid", "adbid", "adoid");
// Returns: ADORecord

Response:

{
meta: {
adoid: "507f1f77bcf86cd799439013",
adbid: "507f1f77bcf86cd799439012",
teamid: "507f1f77bcf86cd799439011",
name: "Record Name",
description: "Record description",
createdat: "2024-01-01T00:00:00.000Z",
updatedat: "2024-01-01T00:00:00.000Z"
},
content: {
A1: {
pos: "A1",
key: "firstName",
type: "string",
value: "John",
colspan: 1,
rowspan: 1
}
}
}

Create Record

Create a new record in a database.

import { ADOCellValueType } from "anydb-api-sdk-ts";

const newRecord = await client.createRecord({
teamid: "teamid",
adbid: "adbid",
name: "New Record",
description: "Optional description",
attach: "parentAdoid", // Optional: Attach to parent record
template: "templateid", // Optional: Use a template
content: {
A1: {
pos: "A1",
key: "firstName",
type: ADOCellValueType.STRING,
value: "John",
colspan: 1,
rowspan: 1,
},
B1: {
pos: "B1",
key: "age",
type: ADOCellValueType.NUMBER,
value: 30,
colspan: 1,
rowspan: 1,
},
},
});
// Returns: ADORecord

Predefined Templates:

import { PredefinedTemplateAdoIds } from "anydb-api-sdk-ts";

// Create a folder
const folder = await client.createRecord({
teamid,
adbid,
name: "My Folder",
template: PredefinedTemplateAdoIds.FOLDER_TEMPLATE_ADOID,
});

// Create a page
const page = await client.createRecord({
teamid,
adbid,
name: "My Page",
template: PredefinedTemplateAdoIds.PAGE_TEMPLATE_ADOID,
});

// Available templates:
// - FILE_TEMPLATE_ADOID
// - FOLDER_TEMPLATE_ADOID
// - PAGE_TEMPLATE_ADOID
// - LINK_TEMPLATE_ADOID
// - VIEW_TEMPLATE_ADOID

Update Record

Update an existing record.

const updatedRecord = await client.updateRecord({
meta: {
adoid: "adoid",
adbid: "adbid",
teamid: "teamid",
name: "Updated Name",
description: "New description",
},
content: {
A1: { value: "Updated value" },
B1: { value: 25 },
},
});
// Returns: ADORecord

Remove Record

Remove or delete a record.

import { NULL_OBJECTID } from "anydb-api-sdk-ts";

// Option 1: Remove from specific parent(s) (detach)
await client.removeRecord({
adoid: "adoid",
adbid: "adbid",
teamid: "teamid",
removefromids: "parentAdoid1,parentAdoid2", // Comma-separated parent IDs
});

// Option 2: Delete completely
await client.removeRecord({
adoid: "adoid",
adbid: "adbid",
teamid: "teamid",
removefromids: NULL_OBJECTID, // Special constant for complete deletion
});
// Returns: boolean (true on success)

Search Records

Search for records by keyword.

const results = await client.searchRecords({
teamid: "teamid",
adbid: "adbid",
search: "keyword",
limit: "10",
});
// Returns: ADORecord[]

Copy Record

Copy an existing record with optional attachment handling.

// Copy with no attachments
const copiedRecord = await client.copyRecord({
adoid: "sourceRecordId",
adbid: "adbid",
teamid: "teamid",
attachmentsmode: "noattachments", // Don't copy attachments
});

// Copy and link attachments
const copiedRecord = await client.copyRecord({
adoid: "sourceRecordId",
adbid: "adbid",
teamid: "teamid",
attachmentsmode: "link", // Link to original attachments
});

// Deep copy with attachments
const copiedRecord = await client.copyRecord({
adoid: "sourceRecordId",
adbid: "adbid",
teamid: "teamid",
attachmentsmode: "duplicate", // Duplicate all attachments
});

// Copy and attach to another record (e.g., a folder)
const copiedRecord = await client.copyRecord({
adoid: "sourceRecordId",
adbid: "adbid",
teamid: "teamid",
attachto: "targetParentId", // Attach copy to this record
attachmentsmode: "duplicate",
});
// Returns: ADORecord (the copied record)

Parameters:

  • adoid - ID of the record to copy
  • adbid - Database ID
  • teamid - Team ID
  • attachto - Optional: ID of another record to attach the copy to
  • attachmentsmode - Optional: How to handle attachments
    • "noattachments" - Don't copy attachments
    • "link" - Link to the original record's attachments
    • "duplicate" - Create new copies of all attachments

Move Record

Move a record to a different parent folder.

const movedRecord = await client.moveRecord({
adoid: "recordId",
adbid: "adbid",
teamid: "teamid",
parentid: "newParentId", // New parent record ID
});
// Returns: ADORecord (the updated record)

Parameters:

  • adoid - ID of the record to move
  • adbid - Database ID
  • teamid - Team ID
  • parentid - ID of the new parent record
info

moveRecord is a convenience method that uses updateRecord internally to change the record's parent attachment.

File Operations

Download File

Download a file or get its download URL.

// Get download URL
const { url } = await client.downloadFile({
teamid: "teamid",
adbid: "adbid",
adoid: "adoid",
cellpos: "A1",
redirect: false, // Return URL instead of redirecting
preview: false, // Download instead of preview
});

console.log("Download URL:", url);

Parameters:

  • teamid - Team ID
  • adbid - Database ID
  • adoid - Record ID (file record)
  • cellpos - Cell position where file is stored
  • redirect - If true, returns redirect response; if false, returns URL
  • preview - If true, returns preview URL; if false, returns download URL

Upload File

Upload a file in one call. This automatically creates a child file record and handles the complete upload workflow.

// Upload from file content (Buffer or string)
const fileAdoid = await client.uploadFile({
filename: "document.pdf",
fileContent: fileBuffer, // Buffer or string
teamid: "teamid",
adbid: "adbid",
adoid: "parentAdoid", // Parent record to attach file to
cellpos: "A1", // Optional, defaults to "A1"
contentType: "application/pdf", // Optional MIME type
});

// Upload from file path
const fileAdoid = await client.uploadFile({
filename: "document.pdf",
filepath: "/path/to/document.pdf",
teamid: "teamid",
adbid: "adbid",
adoid: "parentAdoid",
cellpos: "A1",
});

console.log("File uploaded with ID:", fileAdoid);
// Returns: string (ADOID of the created file record)
info

The uploadFile method automatically:

  1. Creates a new file record as a child of the specified parent
  2. Gets an upload URL from AnyDB
  3. Uploads the file content to cloud storage
  4. Completes the upload process

Advanced Upload (Step-by-Step)

For more control, you can use the individual upload methods:

// Step 1: Get upload URL
const uploadUrl = await client.getUploadUrl({
filename: "document.pdf",
teamid: "teamid",
adbid: "adbid",
adoid: "adoid",
filesize: "1024",
cellpos: "A1",
});

// Step 2: Upload file to URL
await client.uploadFileToUrl(uploadUrl, fileBuffer, "application/pdf");

// Step 3: Complete upload
await client.completeUpload({
filesize: "1024",
teamid: "teamid",
adbid: "adbid",
adoid: "adoid",
cellpos: "A1",
});

Understanding AnyDB Concepts

IDs

  • teamid - MongoDB ObjectId identifying a team/organization. Each team is a separate workspace
  • adbid - MongoDB ObjectId for an ADB (AnyDB Database). Similar to a spreadsheet or table
  • adoid - MongoDB ObjectId for an ADO (AnyDB Object/Record). Similar to a row in a spreadsheet

Cell Positions

Cell positions follow a grid system similar to spreadsheets:

  • Valid format: A1 to A9, B1 to B9, C1 to C9, etc.
  • Invalid: A0, B0, etc. (0 is not a valid row number)

Record Hierarchy

Records can have parent-child relationships:

  • Use attach parameter when creating records to attach to a parent
  • Use parentid parameter when listing records to filter by parent
  • Files are typically child records attached to their parent records

Complete Example

Here's a complete workflow example:

import { AnyDBClient, ADOCellValueType } from "anydb-api-sdk-ts";

async function main() {
// Initialize client
const client = new AnyDBClient({
apiKey: process.env.ANYDB_API_KEY!,
userEmail: process.env.ANYDB_USER_EMAIL!,
baseURL: "https://app.anydb.com/api",
});

// 1. List teams
const teams = await client.listTeams();
const teamid = teams[0].teamid;
console.log(`Using team: ${teams[0].name}`);

// 2. List databases
const databases = await client.listDatabasesForTeam(teamid);
const adbid = databases[0].adbid;
console.log(`Using database: ${databases[0].name}`);

// 3. Create a new record
const record = await client.createRecord({
teamid,
adbid,
name: "Customer Record",
content: {
A1: {
pos: "A1",
key: "companyName",
type: ADOCellValueType.STRING,
value: "Acme Corp",
colspan: 1,
rowspan: 1,
},
B1: {
pos: "B1",
key: "employees",
type: ADOCellValueType.NUMBER,
value: 50,
colspan: 1,
rowspan: 1,
},
},
});

console.log("Created record:", record.meta.adoid);

// 4. Upload a file to the record
const fileBuffer = Buffer.from("Contract details...");
const fileAdoid = await client.uploadFile({
filename: "contract.txt",
fileContent: fileBuffer,
teamid,
adbid,
adoid: record.meta.adoid,
contentType: "text/plain",
});

console.log("File uploaded:", fileAdoid);

// 5. Search for records
const searchResults = await client.searchRecords({
teamid,
adbid,
search: "Acme",
limit: "10",
});

console.log(`Found ${searchResults.length} records`);

// 6. Update the record
const updated = await client.updateRecord({
meta: {
adoid: record.meta.adoid,
adbid,
teamid,
name: "Customer Record - Updated",
},
content: {
B1: { value: 75 }, // Update employee count
},
});

console.log("Record updated");

// 7. List child records (including the uploaded file)
const children = await client.listRecords(
teamid,
adbid,
record.meta.adoid // Filter by parent
);

console.log(`Record has ${children.items.length} children`);
}

main().catch(console.error);

Error Handling

The SDK throws descriptive errors with HTTP status codes:

try {
const record = await client.getRecord("teamid", "adbid", "invalid-adoid");
} catch (error) {
console.error(error.message);
// Example: "AnyDB API Error (404): Record not found"
}

Common Error Scenarios:

  • 401 Unauthorized - Invalid API key or email
  • 404 Not Found - Record, database, or team doesn't exist
  • 400 Bad Request - Invalid parameters or malformed request
  • 500 Server Error - Server-side error

TypeScript Support

The SDK is written in TypeScript and exports all types:

import type {
ADORecord,
Team,
ADB,
CreateRecordParams,
UpdateRecordParams,
RemoveRecordParams,
ListRecordsResponse,
SearchRecordsParams,
DownloadFileParams,
GetUploadUrlParams,
CompleteUploadParams,
ADOCellValueType,
} from "anydb-api-sdk-ts";

Best Practices

Secure API Keys

Store API keys in environment variables:

// .env file
ANYDB_API_KEY=your-api-key-here
ANYDB_USER_EMAIL=user@example.com

// In your code
import { AnyDBClient } from "anydb-api-sdk-ts";
import * as dotenv from "dotenv";

dotenv.config();

const client = new AnyDBClient({
apiKey: process.env.ANYDB_API_KEY!,
userEmail: process.env.ANYDB_USER_EMAIL!
});

Handle Pagination

Always handle pagination when listing records:

async function getAllRecords(client, teamid, adbid) {
const allRecords = [];
let lastmarker = undefined;
let hasmore = true;

while (hasmore) {
const response = await client.listRecords(
teamid,
adbid,
undefined,
undefined,
undefined,
"100", // Fetch 100 at a time
lastmarker
);

allRecords.push(...response.items);
lastmarker = response.lastmarker;
hasmore = response.hasmore;
}

return allRecords;
}

Use Templates

Leverage predefined templates for consistent record structure:

import { PredefinedTemplateAdoIds } from "anydb-api-sdk-ts";

// Create folder structure
const folder = await client.createRecord({
teamid,
adbid,
name: "Documents",
template: PredefinedTemplateAdoIds.FOLDER_TEMPLATE_ADOID,
});

// Create page inside folder
const page = await client.createRecord({
teamid,
adbid,
name: "Meeting Notes",
attach: folder.meta.adoid,
template: PredefinedTemplateAdoIds.PAGE_TEMPLATE_ADOID,
});

Resources

License

MIT License - See LICENSE for details.