> ## 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.

# Placid plugin

> Creative automation with Placid - render templates to images, PDFs and videos, plus the template, collection, media and font operations behind them.

Use **Placid** through Corsair: one client, typed API calls.

Create an API project in Placid, open the project, then click API Tokens in the left menu. The API has no project selector: every request acts on the project that owns the token, so a token from another project lists and creates resources in its own project rather than failing.

* **Renders are queued.** `images.create`, `pdfs.create`, `videos.create` and `pdfs.merge` reply with `status: 'queued'` almost every time. Poll the matching `get` with the reply's `id` (for example `images.get({ id })`), or pass `webhook_success` and let Placid call you. The file URL is null until `status` is `finished`.
* **Failures are reported after the fact.** A render that fails still returns a 200 from the create call. Read the `status: 'error'` reply for `error_code`, `error_message` and `error_details`. Branch on `error_code`, which does not change; `error_message` can be reworded.
* **Deleting a generated file keeps its record.** `images.delete`, `pdfs.delete` and `videos.delete` answer 204 and rewrite the URL field to the bare directory prefix, dropping the filename but keeping scheme and host. A later `get` still returns 200 rather than a 404. The field is `image_url` for images, `pdf_url` for PDFs and `video_url` for videos. Do not poll for a 404 to confirm a delete.
* **`collections` returns `templates`.** Placid's docs name the member list `template_uuids`, but the API answers `templates`, a plain array of UUID strings. Both are read, so either spelling works.
* **Credits.** One image is one credit, one PDF page is two, and a video is ten credits per ten seconds. `create_now: true` renders immediately instead of queueing, and Placid allows 10 simultaneous calls that way.
* **Rate limit.** 60 requests per minute. A 429 is retried up to three times with backoff. A 5xx is only retried on reads, because repeating a create would render and bill a second file.
* **Layers.** `layers` is keyed by the layer name set in the template editor, and every property a layer type supports is accepted. Omitted properties keep the template default. `templates.list` and `templates.get` return each dynamic layer's name and type, which is how to discover the keys.
* **Uploads take URLs.** `media.upload` and `fonts.create` accept a public `file_url`; the plugin downloads it and forwards the bytes as multipart. The bytes cannot come from a local path.
* **Fonts.** A font upload requires `terms_accepted: true`. The returned `uuid` is the value to set as the `font` property on a text layer.
* **Uploads are checked.** `media.upload` and `fonts.create` fetch a public HTTP(S) `file_url`. Private, loopback and cloud-metadata addresses are rejected, the connection is pinned to a checked address so a changing DNS answer cannot swap in a private one, each redirect hop is checked, and the download has a 30 second deadline and a 25 MB cap.
* **Webhooks.** The plugin does not receive webhooks. Placid calls the `webhook_success` URL you supply on a create.

**What you get:**

* 26 typed API operations

## Setup

**1. Install**

```bash npm theme={null}
npm install corsair @corsair-dev/placid better-sqlite3
npm install --save-dev @types/better-sqlite3
```

```bash yarn theme={null}
yarn add corsair @corsair-dev/placid better-sqlite3
yarn add --dev @types/better-sqlite3
```

```bash pnpm theme={null}
pnpm install corsair @corsair-dev/placid better-sqlite3
pnpm install --save-dev @types/better-sqlite3
```

```bash bun theme={null}
bun add corsair @corsair-dev/placid better-sqlite3
bun add --dev @types/better-sqlite3
```

**2. Add the plugin**

```ts corsair.ts theme={null}
import Database from 'better-sqlite3';
import { createCorsair } from 'corsair';
import { placid } from '@corsair-dev/placid';

export const corsair = createCorsair({
	plugins: [
		placid(),
	],
	database: new Database('corsair.db'),
	kek: process.env.CORSAIR_KEK!,
	multiTenancy: true,
	hub: {
		projectApiKey: process.env.CORSAIR_API_KEY!,
		signingSecret: process.env.CORSAIR_SIGNING_SECRET!,
	},
});
```

With `multiTenancy: true`, scope calls with `corsair.withTenant(id)`. See [Quick start](https://docs.corsair.dev/quick-start.md) for KEK + Hub keys, and [Multi-tenancy](https://docs.corsair.dev/concepts/multi-tenancy.md) for account isolation.

**3. Choose authentication**

> [tab] API Key (Recommended)
>
> No setup required yet. When you make your first request as a tenant, Corsair prompts for the API key.
>
> ```ts theme={null}
> placid()
> ```
>
> More: [API Key](https://docs.corsair.dev/concepts/api-key)

**4. Connect a tenant**

Mint a connect link and send the tenant to it. Hub hosts the page and delivers the result to your app — see [Connect / OAuth](https://docs.corsair.dev/management/connect).

```ts theme={null}
const { connectUrl } = await corsair.manage.connect.createLink({
	plugin: 'placid',
	tenantId: 'acme',
});
// redirect the user's browser to connectUrl
```

## Example API calls

**List templates by tag**

```ts theme={null}
const tenant = corsair.withTenant('acme');
await tenant.placid.api.templates.list({ tag: 'social' });
```

**Render an image from a template**

```ts theme={null}
const tenant = corsair.withTenant('acme');
await tenant.placid.api.images.create({
	template_uuid: 'ospo24ysn',
	layers: {
		title: { text: 'Meet Singh' },
		img: { image: 'https://faywoodwildlife.com/images/lion-singh.jpg' },
	},
});
```

See the full list on the [API](https://docs.corsair.dev/plugins/placid/api.md) page.

## What's next

> [card] [API reference](https://docs.corsair.dev/plugins/placid/api.md)
>
> Every `placid.api.*` operation with input and output types.

> [card] [Connect / OAuth](https://docs.corsair.dev/management/connect)
>
> createLink, Hub delivery, and tenant connect flows.

> [card] [Use with agents](https://docs.corsair.dev/mcp-adapters/mcp-adapters)
>
> Expose this plugin's operations as MCP tools.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.