Skip to content
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"plugins": [
{
"name": "rendobar",
"description": "Integrate Rendobar's media processing and AI generation API: FFmpeg jobs, target size compression, captions, image generation, webhooks, and MCP",
"description": "Integrate Rendobar's media processing and AI generation API: FFmpeg jobs, target size compression, captions, composition, image generation, webhooks, and MCP",
"source": "./",
"category": "developer-tools",
"homepage": "https://rendobar.com",
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "rendobar",
"description": "Process and generate media over one API: FFmpeg jobs, target size compression, captions, composition, and image generation, editing, and upscaling",
"version": "1.2.0",
"version": "1.3.0",
"author": {
"name": "Rendobar",
"url": "https://rendobar.com"
Expand Down
38 changes: 31 additions & 7 deletions skills/rendobar/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: "Use this skill whenever a task involves media files or media gener
license: MIT
metadata:
author: rendobar
version: "1.2.0"
version: "1.3.0"
source: https://github.com/rendobar/agent-skills
homepage: https://rendobar.com
---
Expand Down Expand Up @@ -114,11 +114,35 @@ right.**
- `dryRun` on `compress.target` reads like a free estimate. It is not: it runs
real probe encodes and bills close to the full job. Do not sprinkle it in to
"check cost first".
- Never smoke test with a long or high resolution source. Billing tracks the
compute a job actually uses, so a 2 hour 4K render costs real money and
proves nothing the 5 second sample does not. Current rates are on the
[pricing page](https://rendobar.com/pricing/), and the charge for a specific
job appears on the job once billing settles, shortly after it completes.
- Never smoke test with a long or high resolution source. A 2 hour 4K render
costs real money and proves nothing the 5 second sample does not. How a job
bills depends on its type:
- Most types bill the compute the job actually uses.
- `compose` bills $0.04 per minute of the video it returns, counted by the
second, with a 15 second minimum per render. The rate is the same on every
plan, at every frame size and with animated graphics, so a low resolution
draft costs the same per second as a 1080p final. Keep test renders short
rather than small.
- What a plan can render differs. Free renders compose up to 1080p at
30 fps. Pro adds 1440p, and Studio adds 4K and 60 fps. Animated
graphics (text split into letters, words or lines, a `blur` or `scale`
entrance, any text exit, and 3D turns) above 1080p or 30 fps need an
enterprise plan. They work only on top-level tracks and in `overlays`,
never inside a scene or a composition. Lottie animations are not
animated graphics. A video above the plan fails at submit with
`PLAN_LIMIT`. Read `upgradeTo` on the problem in `error.details`:
`"pro"` or `"studio"` names the plan that renders it, and `null` means
only an enterprise plan does. Do not parse the message. Tell the user,
do not retry.
- The `validate_compose` MCP tool (or `POST /compose/validate`) runs the
same plan check for free and quotes the price as
`{ perMinuteUsd, minSeconds }` before you render.
- Every compose feature is listed with its JSON field and a rendered preview
at https://rendobar.com/compose/features/, searchable by name.

Current rates are on the [pricing page](https://rendobar.com/pricing/), and
the charge for a specific job appears on the job once billing settles,
shortly after it completes.
- Check the balance before a large batch: `client.billing.state()`.

## Common mistakes
Expand Down Expand Up @@ -150,7 +174,7 @@ bugs in both directions.
| Field | Means | Typical |
|---|---|---|
| `output.expiresAt` | When this signed download URL stops working | 1 hour |
| `retentionExpiresAt` | When the stored file is actually deleted | Plan driven, 7 days on free, 30 on pro |
| `retentionExpiresAt` | When the stored file is actually deleted | Plan driven, 7 days on free, 30 on pro, 90 on studio |

So a URL going stale does not mean the output is gone: re-fetch the job for a
fresh URL. And a file still being in retention does not mean an old URL works.
Expand Down
8 changes: 5 additions & 3 deletions skills/rendobar/references/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,24 @@ must handle.
|---|---|---|
| `VALIDATION_ERROR` | 400 | The request body or params failed schema validation. Fix the payload. Re-read the type's schema at `GET /jobs/types/{type}/schema`. Do not retry unchanged. |
| `INVALID_JOB_TYPE` | 400 | The type does not exist. Re-read the live catalog at `GET /jobs/types`. Never guess type names. |
| `FEATURE_NOT_ENABLED` | 400 | A compose job uses animated text or 3D turns, which are still rolling out and not enabled for this account. Tell the user. Offer to render without them, or point them to support for access. Do not retry unchanged. |
| `UNAUTHORIZED` | 401 | Two distinct causes, check both before reporting: the key may not be reaching the process env, or the key itself may be invalid for this API (revoked, mistyped, or issued for another environment such as staging). Confirm which one rather than guessing. |
| `INSUFFICIENT_CREDITS` | 402 | The org balance cannot cover the job. Tell the user to top up at https://app.rendobar.com/billing. Do not retry until they do. |
| `FORBIDDEN` | 403 | The key's org cannot access this resource. |
| `PLAN_LIMIT` | 403 | A plan limit was hit (file size, concurrency, and similar). Surface it to the user, do not silently retry. |
| `PLAN_LIMIT` | 403 | A plan limit was hit (file size, job timeout, GPU FFmpeg on the free plan, a compose frame or frame rate above the plan, and similar). A compose or GPU refusal lists problems in `details`, each with `upgradeTo`: `"pro"` or `"studio"` for the cheapest plan that runs it, `null` when only an enterprise plan does. Read `upgradeTo`, not the message. Surface it to the user, do not silently retry. |
| `NOT_FOUND` | 404 | The resource does not exist or belongs to another org. Check the id. |
| `CONFLICT` | 409 | State conflict, for example cancelling a job that already finished. |
| `RATE_LIMITED` | 429 | Too many requests. Retry with exponential backoff and jitter. |
| `RUNNER_ERROR` | 502 | The processing backend failed. Safe to retry the job (use an `idempotencyKey`). |
| `RUNNER_TIMEOUT` | 504 | The job exceeded its timeout. Retrying the same input usually times out again, so reconsider the input or params. |
| `RUNNER_TIMEOUT` | 504 | A runner accepted the job but never started it, or lost the run. Not charged. A job that ran past its plan timeout fails with `JOB_TIMEOUT` instead, and retrying the same input usually times out again. |
| `INTERNAL_ERROR` | 500 | Unexpected server error. Retry with backoff, then surface. |

## Rules of thumb

- Retryable with backoff: `RATE_LIMITED`, `RUNNER_ERROR`, `INTERNAL_ERROR`.
- Fix-then-retry: `VALIDATION_ERROR`, `INVALID_JOB_TYPE`, `UNAUTHORIZED`.
- User action required: `INSUFFICIENT_CREDITS`, `PLAN_LIMIT`.
- User action required: `INSUFFICIENT_CREDITS`, `PLAN_LIMIT`,
`FEATURE_NOT_ENABLED`.
- For a failed job, do not apply these rules of thumb at all. Read
`error.retryable` on the job, which is authoritative for that specific
failure.
5 changes: 3 additions & 2 deletions skills/rendobar/references/jobs.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,9 @@ A completed job carries `output` with four fields:

`output.expiresAt` is the URL's life, not the file's. The file itself is
deleted at `retentionExpiresAt` on the job, which is plan driven (7 days on
free, 30 on pro). Re-fetch the job for a fresh URL rather than caching one, and
copy anything that must outlive retention into your own storage.
free, 30 on pro, 90 on studio). Re-fetch the job for a fresh URL rather than
caching one, and copy anything that must outlive retention into your own
storage.

## Response envelope

Expand Down
Loading