# SDK

import { Steps } from "@astrojs/starlight/components"

`@renai-labs/sdk` is the TypeScript client for the Ren API. Use it to create tasks from a script, update a skill in CI,
or list projects in an internal tool.

- Use the [CLI](/docs/surfaces/cli/) for one-off changes from a terminal.
- Use [MCP](/docs/surfaces/mcp/) to let another AI tool manage Ren.

## Install

```bash
npm install @renai-labs/sdk
```

## Create an access key

An access key is a token the SDK uses to call the API through your account. It belongs to one organization and has its
own permission role.

<Steps>

1. Open **Settings → Access keys**.
2. On the **Personal tokens** tab, select **Create token**.
3. Enter a **Token name**, such as `CI pipeline`. Choose an **Expiration**. The default is 30 days.
4. Select **Create token**. Copy the key. It starts with `ren_pat_`. Ren shows the full key only once.

</Steps>

App-created keys are read-only and can read the organization resources available to you. The CLI supports `readonly`,
`member`, and `admin` roles, so choose `member` or `admin` for a key that makes changes.

```sh
ren pats create --name "CI pipeline" --role member --expires-at 2027-01-01T00:00:00Z
```

A new key can't exceed your current role. It keeps its original role if your role later changes. It works only in the
organization where you created it.

## Quick start

<Steps>

1. **Create a client** with a base URL and your access key:

   ```ts
   import { createRenClient, pat } from "@renai-labs/sdk"

   const client = createRenClient({
     baseUrl: "https://api.useren.ai",
     auth: pat(process.env.REN_ACCESS_KEY!),
   })
   ```

2. **Call a resource.** Methods are grouped by resource and return `{ data, error, request, response }`:

   ```ts
   const { data: skills } = await client.skill.list()
   ```

</Steps>

Some API resources use a different name than the app:

| In the app | In the SDK           |
| ---------- | -------------------- |
| Space      | `client.pod`         |
| Chat       | `client.session`     |
| Schedule   | `client.cronTrigger` |
| Access key | `client.pat`         |
| Database   | `client.podDatabase` |

The [API reference](/docs/developers/api/) lists every resource and operation.

## Example: create a task from a script

This script creates a high-priority task in the `Support` project. Run it with a `member` key.

```ts title="create-task.ts"
import { createRenClient, pat } from "@renai-labs/sdk"

const client = createRenClient({
  baseUrl: "https://api.useren.ai",
  auth: pat(process.env.REN_ACCESS_KEY!),
})

const { data: projects } = await client.project.list({ throwOnError: true })
const project = projects.find((p) => p.name === "Support")
if (!project) throw new Error("No project named Support")

const { data: task } = await client.task.create({
  body: {
    podId: project.podId,
    projectId: project.id,
    title: "Draft replies to this week's open support tickets",
    priority: "high",
  },
  throwOnError: true,
})

console.log(`Created ${task.identifier}: ${task.title}`)
```

The task appears under **Tasks** in the web app, in the project's space. Creating a task doesn't start work on it. See
[Tasks](/docs/concepts/tasks/).

## Revoke an access key

Revoking a key immediately blocks API calls that use it, including calls from running scripts. Revocation is permanent.

Open **Settings → Access keys**, select the key's revoke button, then select **Revoke token**.

From the CLI, run `ren pats list` to find the key's ID, then `ren pats revoke <id>`.

## Errors

Non-2xx responses don't throw by default. Check `error`, or opt into throwing:

```ts
const { data, error } = await client.skill.get({ path: { id } })
if (error) {
  // error is typed to the operation's error schema
}

const { data } = await client.skill.get({ path: { id }, throwOnError: true })
```

## Configuration

`createRenClient` accepts any `@hey-api/client-fetch` `Config` option: `baseUrl`, `headers`, `fetch`, `credentials`,
interceptors, and more.

```ts
createRenClient({
  baseUrl: "https://api.useren.ai",
  auth: pat(token),
  headers: { "X-Request-Id": crypto.randomUUID() },
  fetch: customFetch,
})
```

## Types only

If you only need types, import from `/types` to leave out the client runtime:

```ts
import type { Skill, SkillCreateData } from "@renai-labs/sdk/types"
```