Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions automation/activepieces.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ Every job-shaped action and trigger returns the same flat row, so a table built

`cost_formatted` can be `null` on a row read the moment a job completes, because billing settles a moment later. A later read carries it.

## Wait for a long job
## How do I wait for a long job?

<Frame caption="Polling holds a worker and repeats status calls for the whole job. A waitpoint submits once, parks the flow, and resumes it when Rendobar calls back.">
<img src="/images/activepieces/waitpoint.svg" alt="Two timelines compared. Polling holds a worker open and repeats status calls from submit to done. A waitpoint submits once, shows a paused span with no execution time, and resumes on Rendobar's callback." />
Expand All @@ -112,7 +112,7 @@ Turn **Wait for the Result** off to submit and move on, then pick up the result
- **Fail This Step if the Job Fails** is on by default, so a failed job runs the flow's error path. Turn it off to branch on `succeeded` instead.
- **Idempotency Key** is derived from the run, the step and the submission when left empty. An automatic retry then settles on the job it already created instead of billing a second one.

## Start a flow when a job finishes
## How do I start a flow when a job finishes?

**Finished Job** registers a webhook on your Rendobar account when the flow is turned on, and deletes it when the flow is turned off. **Outcome** picks which jobs start the flow:

Expand Down
6 changes: 3 additions & 3 deletions automation/n8n.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ Every job type returns the same shape on completion, lifted to the top of the it

`file` is the headline result, or `null` for a job that computes data. `data` carries a probe report or a transcript, or `null` for a file-only job. `files` lists every output. **Raw** returns the full job and **Selected Fields** lets you pick.

## Wait for a long job
## How do I wait for a long job?

A transcode can take minutes and an hour-long render can take an hour. The node offers three ways to get the result, and only one of them is right for a long job.

Expand All @@ -155,7 +155,7 @@ The execution parks with no worker held. When the job ends, Rendobar's callback
Leave **Wait for Completion** off when you set a Callback URL. The node refuses the combination rather than picking one, because a hidden field in n8n keeps its value.
</Warning>

## Start a workflow when a job ends
## How do I start a workflow when a job ends?

**Rendobar Trigger** registers a webhook with Rendobar when the workflow activates and removes it on deactivation. Pick the events:

Expand All @@ -176,7 +176,7 @@ Pair `job.failed` with **Job > Get Logs** and the item carries the runner's log,

Rendobar must reach the webhook URL over HTTPS. That's true on n8n Cloud and on any publicly hosted instance. A `localhost` n8n is not reachable, so test locally through a tunnel such as `cloudflared tunnel --url http://localhost:5678` and set `WEBHOOK_URL` to its hostname.

## Use it as an AI Agent tool
## Can I use it as an AI Agent tool?

The node is marked usable as a tool, so it attaches to the AI Agent node's tool port and n8n builds the tool schema from the node's own parameters. Nothing else to define.

Expand Down
2 changes: 1 addition & 1 deletion build-with-ai.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ If I am talking to you inside an MCP-capable client (Claude, Cursor, and others)

Claude has no prefill link. In claude.ai or Claude Code, paste the prompt above, or connect the hosted [MCP server](/mcp-server) at `https://api.rendobar.com/mcp` over OAuth to run jobs straight from the conversation.

## Keep it in your repo
## How do I keep it in my repo?

Save the prompt as an agent rule so the context survives past the first session:

Expand Down
4 changes: 2 additions & 2 deletions cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ A delivery starts after the job completes. rb waits up to five minutes for it an
| `2` | Not authenticated, bad arguments, port in use, or insufficient credits |
| `130` | Cancelled with `Ctrl+C`. The CLI tries to cancel the in-flight job first |

## Run it in CI
## How do I run it in CI?

`RENDOBAR_API_KEY` is the only auth path for CI. It beats any saved credential and writes nothing to disk. Don't run `rb login` in a pipeline, the browser flow will hang.

Expand Down Expand Up @@ -162,7 +162,7 @@ rb ffmpeg --json -i in.mp4 -c:v libx264 out.mp4 | jq -r '.id'

The CLI has no `--idempotency-key`. If a retried step must not double-charge, submit via the [SDK](https://www.npmjs.com/package/@rendobar/sdk) or [`POST /jobs`](/jobs/ffmpeg) with an `idempotencyKey` field.

## Common fixes
## What do I do when a command fails?

`rb doctor` runs the install and connectivity checks and prints a `fix:` line under any failure. Run it first. The three you'll actually hit:

Expand Down
12 changes: 6 additions & 6 deletions concepts/credits.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -51,25 +51,25 @@ For a full pricing breakdown and plan comparison, see [rendobar.com/pricing/](ht

$10 / $25 / $50 / $100 (or custom, $10 minimum). Pro adds **+20%** to every purchase. Buy $25, get $30. Credits never expire.

## How it works: nanodollar billing
## How does nanodollar billing work?

Every job is billed in nanodollars (one-billionth of a US dollar) drawn from your prepaid balance. This differs from tier-based quotas where you buy a plan with a bucket of minutes:

- **Cost matches resources used.** A 30-second 1080p job shouldn't cost the same as a 10-minute 4K render of a large master.
- **Prepaid means predictable budgets.** You top up when you want; jobs run only if affordable. No end-of-month surprise bill.

## Credit lifecycle
## When do credits expire?

1. **Submit gate.** Submit is atomic and does not reject on concurrency. If your balance is greater than zero the job is accepted. Jobs run at your plan's concurrency and any extra wait in a queue, starting in order as slots free. We do not estimate cost up front. A zero balance returns `402 INSUFFICIENT_CREDITS`, and a full queue returns `429 QUEUE_FULL`.
2. **Execution.** Job runs. Balance untouched.
3. **Debit on terminal status.** Every terminal job (`complete`, `failed`, or `cancelled`) is charged for the compute it consumed. The debit is atomic with the status update.
4. **No auto-refund.** Failed jobs are still charged for the compute they consumed. If you believe a job failed due to a platform bug, contact support. Refunds are issued at our discretion via the dispute process.

## Negative balance
## What happens when a balance goes negative?

Because the submit gate checks `balance > 0` rather than an estimate, a single long-running job can drive your balance briefly negative when the terminal debit lands. When that happens, further submits are blocked with `402 INSUFFICIENT_CREDITS` until you top up. Once your balance is positive again, jobs are accepted immediately. Nothing else on the account changes.

## Cost model
## How is a job priced?

`ffmpeg` bills per compute second, which is the wall-clock time FFmpeg ran your command, excluding upload and download. The same per-second rate applies whether the job completes successfully or fails partway through.

Expand All @@ -81,7 +81,7 @@ If your balance is at or below zero when you submit:

HTTP `402`. Top up at [app.rendobar.com/billing](https://app.rendobar.com/billing).

## Check your balance
## How do I check my balance?

```bash
curl https://api.rendobar.com/billing/state \
Expand All @@ -101,7 +101,7 @@ curl https://api.rendobar.com/billing/state \

`balance.amount` is in dollars. Internally balances are stored in nanodollars (1 USD = 1,000,000,000).

## Usage tracking
## How do I track usage?

```bash
curl "https://api.rendobar.com/billing/usage?start=2026-02-01&end=2026-02-09" \
Expand Down
7 changes: 4 additions & 3 deletions concepts/generation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Images are the first modality. You can generate an image from a text prompt, or

More modalities will join the same surface over time. Only image generation and editing are available today.

## Tiers or exact models
## Should I pick a tier or an exact model?

Every generation job takes a `model`. You can name a tier and let the platform choose, or pin an exact model id.

Expand All @@ -51,7 +51,7 @@ Every generation job takes a `model`. You can name a tier and let the platform c

Tier aliases can be re-pointed to newer models as the catalog grows. Pin an exact id when you need a result to stay stable across that change.

## Discover models
## How do I discover models?

`GET /models` returns the live catalog: every model with its supported jobs, tier, relative price, capabilities, and step range. Filter to one job type with `?job=`. Build a model picker against this endpoint instead of hardcoding the list.

Expand Down Expand Up @@ -83,7 +83,7 @@ curl "https://api.rendobar.com/models" \

A model with `underReview: true` is pulled from tier resolution while we re-evaluate its cost and quality. It stays listed so a caller pinning it can see why the submit was rejected, but no tier resolves to it and pinning it returns `VALIDATION_ERROR`.

## Same job, same shape
## Does every model use the same job shape?

A generation job is a [job](/concepts/job) like any other. You submit it to `POST /jobs`, it runs async, and you poll, [wait](/sdk#wait), or receive a [webhook](/guides/webhooks). The image jobs return a single webp file in `output.file`, with `output.data` set to `null`.

Expand All @@ -106,6 +106,7 @@ console.log(outputUrl(job)); // signed URL to the webp

- [Image generate](/jobs/image-generate): text to image, with the full model catalog
- [Image edit](/jobs/image-edit): instruction editing with one to four reference images
- [Image upscale](/jobs/image-upscale): enlarge an image without a prompt
- [How a job works](/concepts/job): statuses and the output shape
- [SDK](/sdk): `jobs.run`, `jobs.wait`, and reading the output
- [Credits and billing](/concepts/credits): how compute-based billing works
12 changes: 8 additions & 4 deletions concepts/job.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ sequenceDiagram
API-->>You: status complete, output
```

## The shape of a job
## What does a job look like?

Every job is a `type` plus the `inputs` and `params` that type expects:

Expand All @@ -62,7 +62,7 @@ To also write the output to a bucket you own, add `destinations`. An input can c

See [storage connections](/storage) for connecting a bucket and how outputs are named.

## The lifecycle
## What are the job statuses?

A job moves through six statuses. Three are terminal.

Expand All @@ -86,7 +86,7 @@ flowchart LR

On any terminal status the job is billed for the compute it used, and a [webhook](/guides/webhooks) fires if you configured one. A job that never started settles free. Failures carry an `error.code` from the [error catalogue](/support/errors). A job that runs past its plan's time limit fails with `JOB_TIMEOUT` and is billed for the compute it consumed. A job a runner accepted but never started fails with `RUNNER_TIMEOUT` and is not charged. Cancelling a `running` job stops the upstream execution too.

## The output
## What does a job return? {#the-output}

A `complete` job carries one `output`. The shape is the same for every type, so you never branch on the job type to find the result.

Expand Down Expand Up @@ -220,7 +220,7 @@ for (const f of job.output.files) console.log(f.path, f.type, f.size); // the fu

Three invariants hold for every type, so you can code against them: `output.file` is always one of `output.files` (or `null`), `expiresAt` is set whenever `files` is non-empty, and a `complete` job always has `output.data` or `output.files`. It never returns nothing.

## Polling or webhooks
## Should I poll or use webhooks?

Poll `GET /jobs/{id}` every second or two until the status is terminal, or skip polling entirely: register a [webhook](/guides/webhooks) and Rendobar pushes `job.completed` to your server the moment the job lands.

Expand All @@ -230,3 +230,7 @@ Poll `GET /jobs/{id}` every second or two until the status is terminal, or skip
- [Credits and billing](/concepts/credits): how the terminal debit works
- [Error codes](/support/errors): every `error.code` a failed job returns
- [FFmpeg](/jobs/ffmpeg): a job type end to end
- [Compose](/jobs/compose): a render described as a JSON timeline
- [Compress](/jobs/compress): a job that searches encodes to hit a budget
- [Animated captions](/jobs/captions/animate): a job that transcribes and renders
- [Generate an image](/jobs/image-generate): the same job shape on a diffusion model
8 changes: 4 additions & 4 deletions concepts/scopes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Every credential carries scopes, and every endpoint states the one it needs. Wha
comes from what it was granted, not from whether it authenticated with an API key, an OAuth token
or a dashboard session.

## The scopes
## Which scopes exist?

Seven resources, each with a read and a write scope.

Expand All @@ -49,7 +49,7 @@ Two rules cover the rest:
- **Self-description is never scoped.** Any credential can ask which workspace it acts for and what
limits apply, whatever else it holds.

## Narrowing an API key
## How do I narrow an API key?

Pass `scopes` when you create a key and it can do only that.

Expand Down Expand Up @@ -85,7 +85,7 @@ Two limits apply to every key, however it was made:
- **A key is never broader than what created it.** Asking for more than the creating credential
holds is refused rather than quietly narrowed.

## What an app is asking for
## What is an app asking for?

When you connect an app over OAuth, the consent screen lists what it requested, area by area, with
what each one lets it do. You can grant less than it asked for, and the app receives exactly what
Expand All @@ -99,7 +99,7 @@ it can reach and where. Revoking deletes the grant and every stored token, so th
access or renew what it has. An access token it already holds stays valid until it expires, which is
under an hour.

## When a scope is missing
## What happens when a scope is missing?

A request outside a credential's scopes is refused with `403` and a header naming what was missing,
per [RFC 6750](https://datatracker.ietf.org/doc/html/rfc6750#section-3.1).
Expand Down
3 changes: 3 additions & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,9 @@
"The full integration prompt for coding agents is at https://rendobar.com/prompts/integrate.md."
]
},
"metadata": {
"timestamp": true
},
"seo": {
"indexing": "all",
"metatags": {
Expand Down
8 changes: 4 additions & 4 deletions guides/callbacks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ canonical: "https://rendobar.com/docs/guides/callbacks"

A callback attaches a completion hook to one [job](/concepts/job). You pass `callback.url` when you create the job, and the moment that job reaches a terminal state Rendobar POSTs the result there. The body is byte-identical to the [webhook](/guides/webhooks) envelope, so the same receiver code handles both. The correlation lives in the URL you chose, so the receiver stays stateless and never polls `GET /jobs/{id}`.

## Attach a callback
## How do I attach a callback?

Add a `callback` object to `client.jobs.create(...)`. The only required field is `url`.

Expand Down Expand Up @@ -127,7 +127,7 @@ await client.jobs.create({

The waiting Workflow is the same as Shape A. It calls `waitForEvent({ type: "rb-job" })` and resumes when Cloudflare delivers the event.

## Secure it
## How do I secure a callback?

Callbacks are unsigned by default because the URL itself is the capability. Set `callback.verify: true` to sign the POST, then check it on your receiver. The signature is the same HMAC-SHA256 scheme as webhooks, over `${timestamp}.${body}`, and the SDK ships the same verifier.

Expand All @@ -148,7 +148,7 @@ const { data } = await client.orgs.getCallbackSecret();

Rotate the secret with `POST /orgs/current/callback-secret/rotate`. Reach for signing when the callback lands on an endpoint you own and you want to prove the POST came from Rendobar. For Shape B, where you already authenticate to Cloudflare through `callback.headers`, signing usually adds nothing.

## Watch delivery
## How do I watch delivery?

Once a job carries a callback, `GET /jobs/{id}` reports its delivery state under `callback.status`.

Expand All @@ -167,7 +167,7 @@ X-Rendobar-Timestamp: 1707436815
X-Rendobar-Attempt: 1
```

## How it compares to org webhooks
## How do callbacks compare to org webhooks?

[Webhooks](/guides/webhooks) and callbacks carry the identical envelope and verify with the same code. The difference is scope. A webhook is one static URL registered in the dashboard that receives events for every job in the organization. A callback is a per-job URL, set at create time, that receives events for exactly one job. Webhooks fit a central event pipeline. Callbacks fit an orchestrator that dispatches a job and waits on that one job, such as the Cloudflare Workflow above.

Expand Down
10 changes: 5 additions & 5 deletions guides/webhooks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Webhooks push events to your server the moment a [job](/concepts/job) changes st
Want a hook scoped to a single job instead of every job in the organization? See [per-job callbacks](/guides/callbacks).
</Note>

## Create an endpoint
## How do I create an endpoint?

Create and manage endpoints on the [**Webhooks page**](https://app.rendobar.com/webhooks) in the dashboard.

Expand Down Expand Up @@ -60,7 +60,7 @@ Hit **Send Test** on the card to fire a sample event and confirm your receiver r
| `balance.low` | Credit balance crossed the low threshold |
| `balance.depleted` | Credit balance reached zero |

## Verify every delivery
## How do I verify a delivery?

Rendobar signs each payload. Check the signature before you trust the body. The SDK does it in one call.

Expand Down Expand Up @@ -132,7 +132,7 @@ def verify_webhook(body: bytes, signature: str, timestamp: str, secret: str) ->
Compare with a timing-safe function (`timingSafeEqual`, `hmac.compare_digest`). Plain string equality leaks the signature one byte at a time.
</Warning>

## Payload
## What is in the payload?

Every delivery carries these headers.

Expand Down Expand Up @@ -204,7 +204,7 @@ For `job.failed`, `data` carries `error` instead of `output`.
}
```

## Delivery and retries
## What happens when a delivery fails?

If your endpoint does not return `2xx` within 10 seconds, Rendobar retries up to 5 times, doubling the wait each attempt.

Expand All @@ -224,7 +224,7 @@ await client.webhooks.retryDelivery(deliveryId);

An endpoint that fails 10 deliveries in a row is disabled automatically and flagged in the dashboard. Update or re-enable it to reset the counter.

## Secret rotation
## How do I rotate the signing secret?

Rotate from the card, or with `client.webhooks.rotateSecret(endpointId)`. For 24 hours Rendobar signs with both secrets, sending `X-Rendobar-Signature` (new) and `X-Rendobar-Signature-Previous` (old), so `verifyWebhook` keeps passing while you roll the new one out. After the window the old secret stops signing. An endpoint can rotate once per 24 hours.

Expand Down
5 changes: 3 additions & 2 deletions index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ sidebarTitle: "Overview"
description: "Start with the quickstart, then browse job types, storage connections, automation platforms, and the SDK, CLI and MCP server."
icon: "book-open"
keywords: ["rendobar docs", "rendobar documentation", "media processing api docs", "video api documentation", "ffmpeg api docs"]
boost: 2
canonical: "https://rendobar.com/docs"
---

Expand All @@ -18,7 +19,7 @@ Rendobar runs media jobs on our infrastructure and hands back a finished file. Y
</Card>
</CardGroup>

## How a job works
## How does a job work?

Every job shares the same shape, whatever its type. Read [how a job works](/concepts/job) for the lifecycle and the output contract, [scopes and access](/concepts/scopes) for what an API key is allowed to do, and [credits](/concepts/credits) for how work is billed.

Expand Down Expand Up @@ -65,6 +66,6 @@ Connect a bucket you own and jobs read inputs from it and write outputs back, so
</Card>
</CardGroup>

## When something goes wrong
## What do I do when something goes wrong?

Check the [FAQ](/support/faq) first, then [error codes](/support/errors) to handle failures by machine code rather than message text. [Limits](/support/limits) covers plan caps, and [versioning](/support/versioning) covers how the API changes.
Loading
Loading