> ## Documentation Index
> Fetch the complete documentation index at: https://docs.slog.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK

# TypeScript SDK

The `@slog-ai/sdk` package provides a typed client for the Slog API with a fluent query builder.

## Installation

```bash theme={null}
npm install @slog-ai/sdk
```

## Setup

```typescript theme={null}
import { SlogSdk, op } from "@slog-ai/sdk"

const slog = SlogSdk({ apiKey: "sl_abc.secret...", baseUrl: "..." }); // baseUrl optional
```

`apiKey` is required. `baseUrl` defaults to the Slog cloud endpoint.

***

## Authentication

### Current user

```typescript theme={null}
const me = await slog.me();
```

***

## CRUD Operations

```typescript theme={null}
await slog.tasks.create({ title: "New feature", priority: "HIGH", teamId: "team_01jq..." });

await slog.tasks.update("PLAT-123", { title: "New feature", priority: "HIGH" });

await slog.tasks.delete(task.id);
```

Required fields for `create`: `title`, `teamId`.

For `update`, all fields are optional — only the provided fields are changed.

***

## Querying

Queries are lazy: they execute only when awaited.

### Filtering

Chain multiple `.where()` calls; all conditions are combined with AND.

```typescript theme={null}
const tasks = await slog.tasks
  .where({ status: "TODO" })
  .where({ teamId: "123" })
  .where({ title: op.contains("foo") })
  .select({ id: true, title: true, assignee: { name: true } })
  .order({ priority: "desc" })
```

### Field selection

Pass an object or a list of field name strings.

```typescript theme={null}
// Object form — supports nested relations
const tasks = await slog.tasks.select({ id: true, title: true, assignee: { name: true } })

// Array form
const tasks = await slog.tasks.select("id", "title")
```

### Sorting

```typescript theme={null}
const tasks = await slog.tasks.order({ priority: "desc" })
```

### Pagination

```typescript theme={null}
const page1 = await slog.tasks.limit(20).select("id", "title")
// page1.pagination.nextCursor
```

Pass `nextCursor` to fetch the next page:

```typescript theme={null}
const page2 = await slog.tasks.limit(20).select("id", "title").cursor(page1.pagination.nextCursor)
```

`nextCursor` is `null` when there are no more pages.

***

## Filter Operators

```typescript theme={null}
import { op } from "@slog-ai/sdk"
```

| Operator           | Description                | Example                                         |
| ------------------ | -------------------------- | ----------------------------------------------- |
| `op.contains(v)`   | Case-insensitive substring | `where({ title: op.contains("auth") })`         |
| `op.startsWith(v)` | Case-insensitive prefix    | `where({ title: op.startsWith("Q2") })`         |
| `op.gt(v)`         | Greater than               | `where({ createdAt: op.gt("2025-05-23") })`     |
| `op.gte(v)`        | Greater than or equal      | `where({ createdAt: op.gte("2025-05-23") })`    |
| `op.lt(v)`         | Less than                  | `where({ dueDate: op.lt("2026-01-01") })`       |
| `op.lte(v)`        | Less than or equal         | `where({ dueDate: op.lte("2026-01-01") })`      |
| `op.oneOf(arr)`    | Match any value in list    | `where({ labels: op.oneOf(["red", "green"]) })` |
| `op.present()`     | Field is not null          | `where({ assignee: op.present() })`             |

Examples:

```typescript theme={null}
const tasks = await slog.tasks
  .select("id", "title")
  .where({ createdAt: op.gt("2025-05-23") })
  .where({ labels: op.oneOf(["red", "green"]) })
  .where({ assignee: op.present() })
```

***

## Get a Single Record

Use the convenience singular methods — they accept either a UUID or a short reference.

```typescript theme={null}
const task = await slog.task("PLAT-123")
const project = await slog.project("proj_01jq...")
```

***

***

## Agents

Create an AI agent user. The response includes the agent's profile and a ready-to-use
API key (shown only once).

```typescript theme={null}
const result = await slog.agents.create({ name: "My Agent" });
// result.agent.id, result.agent.apiKey
```

Only human users may create agents. The agent is added to the current workspace with
the `MEMBER` role.

***

## API Keys

List, create, and delete API keys for the current user and their owned agents.

```typescript theme={null}
// List keys (raw key value never returned — only prefix)
const { api_keys } = await slog.apiKeys.list();

// Create a key
const { key, ...meta } = await slog.apiKeys.create({ name: "CI/CD key" });
// key is the full raw value — store it now, not shown again

// Create with expiry
await slog.apiKeys.create({ name: "Temp key", expiresAt: "2027-01-01T00:00:00.000Z" });

// Delete a key
await slog.apiKeys.delete("apik_01jq...");
```

***

## Fields

Manage workspace-scoped custom field definitions. Built-in fields are included
automatically in list responses with `isBuiltIn: true`.

```typescript theme={null}
// List all field definitions (built-ins first, then custom)
const { fields } = await slog.fields.list();

// Filter to a specific resource type
const taskFields = await slog.fields
  .where({ recordType: "task" })

// Get a single field definition
const field = await slog.field("fdef_01jq...");

// Create a custom field (requires ADMIN or OWNER workspace role)
await slog.fields.create({
  key: "sprint_points",
  name: "Sprint Points",
  type: "number",
  recordTypes: ["task"],
});

// Create a select field with choices
await slog.fields.create({
  key: "quarter",
  name: "Quarter",
  type: "select",
  metadata: { choices: ["Q1", "Q2", "Q3", "Q4"] },
  recordTypes: ["task", "project"],
});

// Update a field (key and type are immutable)
await slog.fields.update("fdef_01jq...", { name: "Story Points" });

// Delete a field
await slog.fields.delete("fdef_01jq...");
```

***

## Other Resources

The same query API is available on all resource collections.

```typescript theme={null}
slog.teams.where(...)
slog.projects.where(...)
slog.milestones.where(...)
slog.fields.where(...)
```
