Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Rendobar Compose API
version: 1.0.0
summary: Serverless media processing API
description: Serverless media processing API. Watermark, transcode, caption, redact, and render videos with one API call. Credit-based billing. MCP-native for AI agents.
termsOfService: https://rendobar.com/terms/
contact:
name: Rendobar Support
url: https://rendobar.com/
email: hello@rendobar.com
license:
name: Proprietary
url: https://rendobar.com/terms/
servers:
- url: https://api.rendobar.com
description: Current environment
security:
- bearerAuth: []
- oauth2: []
tags:
- name: Compose
description: 'Helpers for the compose job that render nothing: the effects reference, and validating params before submitting'
paths:
/compose/validate:
post:
security:
- bearerAuth:
- jobs:write
operationId: validateCompose
tags:
- Compose
summary: Validate compose params
description: 'Check the `params` of a compose job without rendering anything. Free, and nothing is stored. Runs the same checks a submit runs, plus the timeline checks a render would otherwise fail on. The response carries the params as a render would read them: defaults filled in, and a timeline written in an older shape rewritten into the current one. It also runs the plan check: a video above your plan is `valid: false` with a problem at `["output"]` whose `upgradeTo` names the plan that renders it. A valid result carries `price`, the rate per minute of output and the fewest seconds a render bills.'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
params:
type: object
additionalProperties: {}
description: Exactly what you would send as `params` when creating a compose job.
required:
- params
responses:
'200':
description: The verdict. Branch on `valid`.
content:
application/json:
schema:
type: object
properties:
data:
oneOf:
- type: object
properties:
valid:
type: boolean
enum:
- true
params:
type: object
additionalProperties: {}
upgraded:
type: array
items:
type: string
description: Constructs from an older timeline shape that were rewritten into the current one. Empty for a current timeline.
warnings:
type: array
items:
type: object
properties:
path:
type: array
items:
anyOf:
- type: string
- type: number
description: Where in the params the problem is, as keys and indexes. Empty when it concerns the timeline as a whole.
message:
type: string
description: What is wrong and how to fix it.
upgradeTo:
type:
- string
- 'null'
enum:
- pro
- studio
- null
description: 'Only on a video above your plan: the cheapest plan that renders it, or null when only an enterprise plan does.'
required:
- path
- message
description: 'What renders but not as written, and where: a setting the render ignores, like a video codec on an mp3, or a font family it cannot supply and draws in Inter instead. They do not stop a submit.'
price:
type: object
properties:
perMinuteUsd:
type: number
description: What one minute of output costs. The video's length in minutes times this is the charge, billed per second.
minSeconds:
type: integer
description: Every render bills at least this many seconds of output.
required:
- perMinuteUsd
- minSeconds
required:
- valid
- params
- upgraded
- warnings
- price
- type: object
properties:
valid:
type: boolean
enum:
- false
problems:
type: array
items:
type: object
properties:
path:
type: array
items:
anyOf:
- type: string
- type: number
description: Where in the params the problem is, as keys and indexes. Empty when it concerns the timeline as a whole.
message:
type: string
description: What is wrong and how to fix it.
upgradeTo:
type:
- string
- 'null'
enum:
- pro
- studio
- null
description: 'Only on a video above your plan: the cheapest plan that renders it, or null when only an enterprise plan does.'
required:
- path
- message
minItems: 1
params:
type:
- object
- 'null'
additionalProperties: {}
description: Null when the document did not parse.
upgraded:
type: array
items:
type: string
description: Constructs from an older timeline shape that were rewritten into the current one. Empty for a current timeline.
warnings:
type: array
items:
type: object
properties:
path:
type: array
items:
anyOf:
- type: string
- type: number
description: Where in the params the problem is, as keys and indexes. Empty when it concerns the timeline as a whole.
message:
type: string
description: What is wrong and how to fix it.
upgradeTo:
type:
- string
- 'null'
enum:
- pro
- studio
- null
description: 'Only on a video above your plan: the cheapest plan that renders it, or null when only an enterprise plan does.'
required:
- path
- message
description: 'What renders but not as written, and where: a setting the render ignores, like a video codec on an mp3, or a font family it cannot supply and draws in Inter instead. They do not stop a submit.'
required:
- valid
- problems
- params
- upgraded
- warnings
required:
- data
'400':
description: The body is not JSON with a `params` object
content:
application/json:
schema:
type: object
properties:
error:
type: object
properties:
code:
type: string
description: Machine-readable error code
message:
type: string
description: Human-readable error message
details:
description: More about the error when there is more to say. A refusal lists its problems here as `{ path, message, upgradeTo? }`, where `upgradeTo` names the cheapest plan that runs it (null when only an enterprise plan does).
required:
- code
- message
required:
- error
'401':
description: Unauthorized
content:
application/json:
schema:
type: object
properties:
error:
type: object
properties:
code:
type: string
description: Machine-readable error code
message:
type: string
description: Human-readable error message
details:
description: More about the error when there is more to say. A refusal lists its problems here as `{ path, message, upgradeTo? }`, where `upgradeTo` names the cheapest plan that runs it (null when only an enterprise plan does).
required:
- code
- message
required:
- error
/compose/effects:
get:
security:
- bearerAuth:
- jobs:read
operationId: listComposeEffects
tags:
- Compose
summary: List compose effects
description: Every built-in effect an `effects` list takes, with its parameters, ranges, units, defaults and which parameters take keyframes. Each looks right written with nothing but its type.
responses:
'200':
description: The built-in effects
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
effects:
type: array
items:
type: object
properties:
type:
type: string
description: What goes in the entry's "type".
group:
type: string
enum:
- color
- stylize
- layers
- sound
medium:
type: string
enum:
- picture
- sound
description: What it changes.
summary:
type: string
params:
type: object
additionalProperties:
type: object
properties:
kind:
type: string
enum:
- number
- color
- enum
- length
- file
description: 'number, a hex colour, one of `values`, a length (pixels as a number, or a percent of the frame as a string like "50%"), or a file: the URL of one, like a clip''s src.'
description:
type: string
min:
type: number
max:
type: number
default:
anyOf:
- type: number
- type: string
description: Used when the parameter is left out. A parameter with no default and not in `required` changes nothing when left out.
unit:
type: string
description: px, deg, K, dB, Hz, s, LUFS or semitones. Absent for a plain ratio.
keyframes:
type: boolean
description: True when the parameter also takes a keyframe list, [{time, value, easing}].
alpha:
type: boolean
description: 'Colours only: also takes "#RRGGBBAA".'
values:
type: array
items:
type: string
description: 'Enums only: the accepted words.'
measuredAgainst:
type: string
enum:
- width
- height
description: 'Lengths only: the side of the frame a percent is a share of.'
format:
type: string
description: 'Files only: the file''s extension, like ".cube".'
required:
- kind
- description
required:
type: array
items:
type: string
description: Parameters the entry must give.
needsOneOf:
type: array
items:
type: string
description: At least one of these must be given, for an effect that does nothing when empty.
required:
- type
- group
- medium
- summary
- params
- required
required:
- effects
required:
- data
'401':
description: Unauthorized
content:
application/json:
schema:
type: object
properties:
error:
type: object
properties:
code:
type: string
description: Machine-readable error code
message:
type: string
description: Human-readable error message
details:
description: More about the error when there is more to say. A refusal lists its problems here as `{ path, message, upgradeTo? }`, where `upgradeTo` names the cheapest plan that runs it (null when only an enterprise plan does).
required:
- code
- message
required:
- error
/compose/effects/engine:
get:
security:
- bearerAuth:
- jobs:read
operationId: listComposeEngineEffects
tags:
- Compose
summary: List engine filters
description: 'Every filter an `engine` effect may name, {"type":"engine","filter":"...","params":{...}}, with its parameters and what each accepts. A filter a built-in effect already covers is not listed: use the built-in.'
responses:
'200':
description: The engine filters
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
filters:
type: array
items:
type: object
properties:
filter:
type: string
description: What goes in the entry's "filter".
checked:
type: string
enum:
- proven
- unproven
- nondeterministic
description: 'What the engine''s render check found. proven: its parameters visibly change the output. unproven: it renders, and the check could not show a parameter doing anything. nondeterministic: it renders differently every time, by design (noise, glitches).'
params:
type: object
additionalProperties:
type: object
properties:
kind:
type: string
enum:
- number
- switch
- enum
- color
- rect
- size
- flags
description: number, true or false, one of `values`, a hex colour, a rect "x y w h", a size "1280x720", or flag names joined by "+".
min:
type: number
max:
type: number
values:
type: array
items:
type: string
required:
- kind
description: What goes in "params", by parameter name.
required:
- filter
- checked
- params
services:
type: array
items:
type: object
properties:
service:
type: string
checked:
type: string
enum:
- proven
- unproven
- nondeterministic
description: 'What the engine''s render check found. proven: its parameters visibly change the output. unproven: it renders, and the check could not show a parameter doing anything. nondeterministic: it renders differently every time, by design (noise, glitches).'
params:
type: object
additionalProperties:
type: object
properties:
kind:
type: string
enum:
- number
- switch
- enum
- color
- rect
- size
- flags
description: number, true or false, one of `values`, a hex colour, a rect "x y w h", a size "1280x720", or flag names joined by "+".
min:
type: number
max:
type: number
values:
type: array
items:
type: string
required:
- kind
required:
- service
- checked
- params
description: 'Deprecated, always empty: read `filters`. Kept so code written against the first version of this response still compiles.'
required:
- filters
- services
required:
- data
'401':
description: Unauthorized
content:
application/json:
schema:
type: object
properties:
error:
type: object
properties:
code:
type: string
description: Machine-readable error code
message:
type: string
description: Human-readable error message
details:
description: More about the error when there is more to say. A refusal lists its problems here as `{ path, message, upgradeTo? }`, where `upgradeTo` names the cheapest plan that runs it (null when only an enterprise plan does).
required:
- code
- message
required:
- error
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: API key or OAuth access token
description: 'Bearer authentication. Accepts an API key from https://app.rendobar.com/settings/api-keys (`Authorization: Bearer rb_xxx`) or an OAuth 2.1 access token. Both carry the same scopes and the same authority: what a caller may do is a property of the grant, not of how it authenticated.'
oauth2:
type: oauth2
description: OAuth 2.1 with PKCE. Register a client at https://api.rendobar.com/oauth2/register or connect through an integration that does it for you. Scopes are granted at consent and carry the same authority as an API key holding them.
flows:
authorizationCode:
authorizationUrl: https://api.rendobar.com/auth/oauth2/authorize
tokenUrl: https://api.rendobar.com/auth/oauth2/token
refreshUrl: https://api.rendobar.com/auth/oauth2/token
scopes:
jobs:read: See your jobs and their results
jobs:write: Run and cancel jobs
assets:read: See and download your files
assets:write: Upload and delete files
webhooks:read: See where your events are delivered
webhooks:write: Manage where your events are delivered
billing:read: See your plan, balance and usage
billing:write: Change your plan and payment methods
orgs:read: See your organization and its members
orgs:write: Manage your organization and its members
keys:read: See which API keys exist
keys:write: Create and revoke API keys
storage:read: See which storage connections exist
storage:write: Connect, rotate and remove storage connections
externalDocs:
description: Full developer documentation
url: https://rendobar.com/docs/