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

# API

> Corsair API.

When you create a Corsair instance, every plugin exposes its API endpoints through a nested, intuitive structure. Each plugin's API is accessible directly on the Corsair instance.

```ts corsair.ts theme={null}
import { createCorsair } from "corsair";
import { slack } from "@corsair-dev/slack";
import { linear } from "@corsair-dev/linear";

export const corsair = createCorsair({
    plugins: [
        slack({ authType: "api_key", credentials: { botToken: "xoxb-..." } }),
        linear({ authType: "api_key", credentials: { apiKey: "lin_..." } }),
    ],
});

// Send a message to Slack
await corsair.slack.api.messages.post({
    channel: "C01234567",
    text: "Hello from Corsair!",
});

// Create a Linear issue
await corsair.linear.api.issues.create({
    title: "New feature request",
    teamId: "TEAM_123",
});
```

## API Structure

All plugins follow the same pattern: `corsair.[plugin].api.[resource].[action]()`.

```ts example.ts theme={null}
// Slack examples
corsair.slack.api.channels.create({ name: "engineering" });
corsair.slack.api.channels.list({ limit: 50 });
corsair.slack.api.messages.post({ channel: "C01", text: "Hello" });
corsair.slack.api.messages.delete({ channel: "C01", ts: "123.456" });
corsair.slack.api.users.get({ user: "U01234567" });

// Linear examples
corsair.linear.api.issues.create({ title: "Bug", teamId: "T1" });
corsair.linear.api.issues.update({ id: "ISS-1", input: { title: "Fixed" } });
corsair.linear.api.projects.list({ first: 10 });
corsair.linear.api.comments.create({ issueId: "ISS-1", body: "Done!" });
```

## Strongly Typed

Every API call is fully typed — both request parameters and responses. Your editor shows exactly what's required and what you'll get back.

```ts example.ts theme={null}
// TypeScript knows exactly what parameters are available
const channel = await corsair.slack.api.channels.create({
    name: "engineering",
    is_private: true,  // optional — TypeScript tells you
});

// Response is also strongly typed
console.log(channel.id, channel.name, channel.is_member);
```

## With Multi-Tenancy

When multi-tenancy is enabled, use `withTenant()` to scope operations.

```ts example.ts theme={null}
const tenant = corsair.withTenant("tenant_abc123");

await tenant.slack.api.messages.post({
    channel: "C01234567",
    text: "Scoped to tenant_abc123",
});
```

See [Multi-Tenancy](/concepts/multi-tenancy) for details.

## Automatic Persistence

API responses are stored in your database automatically. Create foreign key relationships to Corsair resources — they stay in sync through API calls and webhooks.

```ts example.ts theme={null}
// Create a channel — Corsair stores it
const channel = await corsair.slack.api.channels.create({ name: "support" });

// Later, retrieve from the database
const stored = await corsair.slack.db.channels.findByResourceId(channel.id);
```

See [Database](/concepts/database) for the full ORM API.

## Hooks

Add before/after hooks to customize API behavior.

```ts corsair.ts theme={null}
slack({
    authType: "api_key",
    credentials: { botToken: "xoxb-..." },
    hooks: {
        channels: {
            create: {
                before: (ctx, args) => {
                    console.log("Creating channel:", args.name);
                    return { ctx, args };
                },
                after: (ctx, result) => {
                    console.log("Created:", result.id);
                },
            },
        },
    },
})
```
