Developers
API and MCP docs
Make, edit and schedule videos from your own code, or let Claude and Cursor do it for you. One API key works for the REST API and the MCP server.
Base URLhttps://clips.lnr.ae/api/v1
On this page
Guide
Overview
Clips has a REST API for your scripts and servers, and an MCP server for AI tools like Claude and Cursor. Both act in one workspace, the one the API key belongs to, and share its plan, credits and connected accounts.
- REST API
- https://clips.lnr.ae/api/v1
- MCP server
- https://clips.lnr.ae/api/mcp
What you can do
- WorkspaceThe workspace a key belongs to, and the templates its projects are built from.
- ProjectsEditable videos built from a template. Create one from a starter or from full props, then change it until it's right.
- AI video generationHave the AI director write, voice and edit a video from a prompt, saved as a project you can open in the editor.
- AI studioFollow and revise AI videos, make product films of real apps, and film AI footage. Paid calls reserve credits first and give them back when nothing is made.
- RenderingTurn a template project into an MP4 on the Clips server, then download it or post it.
- Videos and libraryFind finished videos and library files, download them, and upload your own MP4s, so you have a videoId or storagePath to post.
- Connected accountsThe social accounts connected to the workspace, how posts reach each one, and the weekly posting times that next_free_slot fills.
- Posts and calendarSchedule a finished MP4 to connected accounts, then follow, change, retry, copy or cancel the posts and read their numbers.
- Brand and charactersHow the workspace looks and sounds, and who appears in its videos. Every video, caption and idea follows the brand kit.
- Usage, analytics and notificationsWhat the workspace has left to spend, how its posts did on each platform, and the notices that need attention.
- Ideas and captionsAI help with what to post and how to word it. Each request spends AI writing calls from the daily allowance, never credits.
Quickstart
Create a key
In Clips, open Settings, API and MCP and create a key. Copy it straight away: it's shown once. API access comes with every paid plan.
Make your first call
Ask for your workspace. If the key works, you get its name and plan back.
curl https://clips.lnr.ae/api/v1/workspace \ -H "Authorization: Bearer YOUR_API_KEY"Build something
Create a project, generate a video or schedule a post. Every endpoint is in the API reference below, with an example you can copy.
Authentication and scopes
Send the key in the Authorization header of every request, as a bearer token. Keys start with clp_live_.
Authorization: Bearer YOUR_API_KEYScopes
Each key is read only, read and write, or (made by the workspace owner) read, write and approve. Every endpoint and tool says which scope it needs.
| Scope | What it allows |
|---|---|
| Read | Read your workspace: projects, templates, posts, accounts and results. |
| Write | Change things: create and edit projects, generate videos and schedule posts. Includes read. |
| Approve | Approve posts waiting for the owner's review. Only the owner can make such a key, and it stops approving if its maker is no longer the owner. Includes read and write. |
The Free plan has no API access. Its keys get plan_required (HTTP 402) until the workspace upgrades.
Treat a key like a password. Keep it on your server or in your AI tool's config, never in a web page or a public repository. Revoke a key in Settings the moment you think it's leaked.
Connect AI tools
The MCP server lets an AI tool use Clips for you: it reads your workspace, makes videos and schedules posts when you ask. Replace YOUR_API_KEY with your key.
Claude Code
Run this once in your terminal. Claude Code can then use Clips in every project.
claude mcp add --transport http clips https://clips.lnr.ae/api/mcp \
--header "Authorization: Bearer YOUR_API_KEY"Claude Desktop
Open Settings, Developer, Edit config in Claude Desktop, add this to claude_desktop_config.json and restart Claude. Claude Desktop reaches the server through mcp-remote, so it needs Node.js installed.
{
"mcpServers": {
"clips": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://clips.lnr.ae/api/mcp",
"--header",
"Authorization:${CLIPS_AUTH}"
],
"env": {
"CLIPS_AUTH": "Bearer YOUR_API_KEY"
}
}
}
}Cursor
Add this to ~/.cursor/mcp.json for every project, or to .cursor/mcp.json in one project. Cursor picks it up without a restart.
{
"mcpServers": {
"clips": {
"url": "https://clips.lnr.ae/api/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}Other MCP clients
Any client that supports MCP over Streamable HTTP can connect. Give it the server URL and send the key as a bearer token.
URL: https://clips.lnr.ae/api/mcp
Header: Authorization: Bearer YOUR_API_KEYMCP tools
The MCP server has 59 tools. Your AI tool picks the right one from what you ask, so you rarely name them yourself.
get_workspaceReadGet workspace. Get the Clips workspace this key belongs to: its name, plan, the kinds of video it makes, the platforms it posts to and how many projects it has.
list_templatesReadList templates. List the video templates a project can use.
list_projectsReadList projects. List the workspace's video projects, newest first, without their props.
get_projectReadGet project. Get one video project by id, including its template and full props (the text, numbers and colours in the video).
create_projectWriteCreate project. Create a video project in the workspace.
update_projectWriteUpdate project. Change a project's title, its props, or both.
list_connected_accountsReadList connected accounts. List the Instagram, TikTok and LinkedIn accounts connected to this workspace: id, platform, handle, how posts are delivered (direct = Clips posts it; tiktok_inbox = the creator taps Post in TikTok; manual = the person posts it themselves; browser = a Lunar-owned TikTok account Clips posts to from its logged-in session, temporary), timezone and the next free posting slots.
schedule_postAsks firstWriteSchedule a post. Schedule a finished MP4 to connected accounts, with a caption per platform.
publish_nowAsks firstWritePublish now. Post a finished MP4 to connected accounts right away: Clips sends it within about a minute.
list_postsReadList posts. List the workspace's posts, newest scheduled first, optionally filtered by account, platform, scheduled time range (from/to) and status: ready (waiting for approval), scheduled, publishing, awaiting_creator (waiting for the person to post, e.g. in their TikTok inbox), published, failed or cancelled.
get_postReadGet post. Get one post: its status, scheduled and published times, the link on the platform once it's live, and why it failed if it did.
cancel_postAsks firstWriteCancel post. Cancel a post that hasn't gone out yet (waiting for approval, scheduled, failed, or waiting for the person).
get_post_metricsReadGet post metrics. Get a published post's numbers as collected from the platform about 1, 3 and 7 days after posting.
update_postAsks firstWriteUpdate post. Reschedule a post that hasn't gone out yet (waiting for approval, approved or scheduled), change its caption and hashtags, or both.
retry_postAsks firstWriteRetry failed post. Send a failed post again: it goes out about 3 minutes later.
get_calendarReadGet calendar. List the posts on the calendar between two dates (inclusive, at most 92 days), placed by scheduled time (or published time) in the workspace's timezone: the first connected account's, as on the Calendar page, unless you pass one.
get_accountReadGet account. Get one connected account: platform, handle, status (connected, needs_reauth or disconnected), how posts reach it, its timezone, its weekly posting times and its next free slots.
set_posting_timesAsks firstWriteSet posting times. Replace an account's weekly posting times: the slots "next_free_slot" fills.
duplicate_postAsks firstWriteDuplicate post. Schedule an existing post's video again: to other connected accounts, or at a new time.
approve_postAsks firstApproveApprove post. Approve a post that is waiting for the owner's review (status ready), which schedules it for its time.
generate_videoWriteGenerate video with AI. Have Clips' AI director make a finished animated vertical video and save it as a project: it writes the script, records a voiceover, designs motion-graphics scenes in the workspace's brand, and adds music and captions.
start_video_generationWriteStart an AI video. Start Clips' AI director on a video and return at once with its sessionId, instead of waiting like generate_video.
get_video_sessionReadGet video session. Check on an AI video started with generate_video, start_video_generation or revise_video.
revise_videoWriteRevise video with AI. Change a video the AI director made, by plain instruction: 'make the hook shorter', 'use an Arabic voice', 'swap scene 2 for a stat about churn'.
list_voicesReadList voices. List the narrators a video can use (pass an id as voiceId to revise_video) with gender, accent, age, language and a sample link, plus the languages a video can be written and voiced in.
list_video_modelsReadList video models. List the AI models the director can run on (pass an id as modelId to revise_video), with each one's tier and the credits a new video costs on it.
list_filmsReadList product films. List the workspace's product films, newest first, with status and a download link for finished ones.
create_filmWriteCreate product film. Make a cinematic product film of a real SaaS or app: Clips captures the product's public link and/or uses library screenshots, writes the film in the chosen style and renders it.
get_filmReadGet product film. Check a product film: status (writing, queued, rendering, replan, succeeded, failed), what it is doing now, and a download link that works for 15 minutes once it has succeeded.
generate_footageWriteGenerate AI footage. Film a realistic AI video clip (b-roll) from a prompt and save it to the library.
get_footageReadGet AI footage. Check an AI clip: status (running, succeeded, failed), its library storagePath and a download link that works for 15 minutes once it has succeeded.
list_footageReadList AI footage. List the workspace's AI clips, stills and 4K upscales, newest first, with status, credits used and download links for finished ones.
upscale_footageWriteUpscale AI footage to 4K. Upscale a finished AI clip to 4K (Growth and Scale plans).
render_projectWriteRender project to MP4. Render a template project (stat-reveal or problem-solution) to an MP4 on the Clips server, the same video the editor's export makes.
list_videosReadList finished videos. List the workspace's finished MP4 videos, newest first: each with its id, title, whether it was uploaded or rendered by Clips, and its storagePath.
get_videoReadGet video. Get one finished video by id, with a download link that works for 15 minutes (downloadUrl, null if it hasn't finished rendering).
list_libraryReadList library files. List files in the workspace's media library (uploads and AI-made footage), newest first, plus the library's folders.
create_upload_urlWriteCreate upload URL. Get a signed URL to upload your own file (an MP4, image, audio file or PDF, up to 1 GB and within the plan's library storage) straight into the workspace's library.
complete_uploadWriteComplete upload. Call after the PUT to a create_upload_url uploadUrl has finished.
rename_videoWriteRename video. Change a finished video's title (shown in Clips and used as the post title where a platform has one).
list_foldersReadList library folders. List the media library's folders, A to Z, each with its id, name and how many files are in it.
create_folderWriteCreate library folder. Create a folder in the media library to organise files (up to 100 per library).
rename_folderWriteRename library folder. Rename a Library folder.
delete_folderAsks firstWriteDelete library folder. Delete a media library folder.
move_filesWriteMove files to a folder. File up to 500 library files in a folder, or back in Unfiled with folderId null.
delete_filesAsks firstWriteDelete library files. Permanently delete up to 500 files from the media library.
get_brand_kitReadGet brand kit. Get the workspace's brand kit: name, accent, background and text colours, voice style, tone of voice, banned words, website and a 10-minute logo link, plus the list of all its kits (agencies keep one per client).
update_brand_kitWriteUpdate brand kit. Change the brand kit: any of name, colours (each key on its own), voice style, tone and banned words; fields you leave out stay as they are.
list_charactersReadList characters. List the workspace's characters: its own characters (built from the cast, with colours, an accessory, a line about them and a 10-minute face link) and its Illustrated characters (drawn, with their poses).
create_characterWriteCreate character. Create one of the workspace's own characters from the cast (up to 24).
update_characterWriteUpdate character. Change one of the workspace's own characters; fields you leave out stay as they are.
delete_characterWriteDelete character. Delete one of the workspace's own characters.
get_usageReadGet usage. Get the workspace's plan and what it has used: credits used and left this period (AI videos spend them: about 10 a standard video, 20 Illustrated) and when they renew, pack credits, AI videos made, AI writing calls used today against the daily limit (captions and ideas spend these), and posts this week against the weekly goal.
get_analyticsReadGet analytics. Get how the workspace's published posts did over the last 7, 30 or 90 days: totals (views, reach, likes, comments, shares, saves), the same per platform and per account, the five most viewed posts, and the best weekday and hour to post by median views.
list_ideasReadList ideas. Get this week's video ideas for the workspace (five, each with a title, opening hook, angle and format), if they've been made.
generate_ideasWriteGenerate ideas. Make five fresh video ideas for this week from the workspace's formats, platforms and brand kit, replacing this week's ideas.
write_captionsWriteWrite captions. Write a post caption and hashtags for each platform (Instagram, TikTok, LinkedIn; all three by default), in the brand's tone, from a topic or an existing video (videoId from list_posts).
list_notificationsReadList notifications. List this workspace's notices from the bell, newest first, as the key's maker sees them: a video is ready, a post failed or went out, a payment failed.
mark_notifications_readWriteMark notifications read. Mark notices as read: the ids given, or every unread notice when you pass none.
Asks firstShows a preview and waits for your OK before it changes anything.
Responses and errors
Every response is JSON with two fields, data and error. On success, data holds the result and error is null. On failure it's the other way round, and error has a code to act on and a message you can show a person.
Success
{
"data": {
"id": "6f1c2b8e-4a3d-4e6f-9b1a-2c7d8e9f0a1b",
"title": "Coffee facts"
},
"error": null
}Failure
{
"data": null,
"error": {
"code": "invalid_input",
"message": "Give the project a title."
}
}| Code | HTTP status | What it means |
|---|---|---|
unauthorized | 401 | The key is missing, malformed, revoked or expired. |
forbidden | 403 | The key can't do this: a read-only key tried to write, or your role doesn't allow it. |
not_found | 404 | Nothing with that id in this workspace. |
invalid_input | 400 | A field is missing or out of range. The message says which. |
invalid_json | 400 | The body isn't valid JSON. |
payload_too_large | 413 | The body is over 100 KB. |
unsupported_media_type | 415 | Send the body as JSON, with Content-Type: application/json. |
method_not_allowed | 405 | That path doesn't take this HTTP method. |
rate_limited | 429 | Too many requests from this key. Wait for the Retry-After seconds. |
plan_required | 402 | API access needs a paid plan. |
plan_limit | 403 | You've reached a limit on your plan, such as projects or videos this month. |
internal | 500 | Something failed on our side. Try again; if it keeps happening, tell us. |
Rate limits
Each key can make 60 requests a minute. Past that you get rate_limited (HTTP 429) with a Retry-After header saying how many seconds to wait. Need more? Create a key per script: each has its own limit.
Pagination
Lists come a page at a time, newest first. Set limit for the page size (20 by default, up to 100). When there's more, the response has a nextCursor: send it back as cursor for the next page. It's null on the last page.
curl "https://clips.lnr.ae/api/v1/projects?limit=20&cursor=NEXT_CURSOR" \
-H "Authorization: Bearer YOUR_API_KEY"Previews and confirmation
Writes that act outside Clips, such as scheduling a post, take ?preview=1. With it, Clips checks the request and returns what would happen, without doing anything.
Through MCP, those tools always ask first. The first call returns a preview and a plan_id; your AI tool shows you the preview, and only after you say yes calls again with the same arguments and the plan_id. A plan works once and expires after 10 minutes, so nothing is ever posted twice or without you.
OpenAPI
The whole REST API is described in one OpenAPI 3.1 file. Import it into Postman or Insomnia, give it to Cursor or another AI tool as context, or generate a client in your language.
curl -o clips-openapi.json https://clips.lnr.ae/api/v1/openapi.jsonAPI reference
Workspace
The workspace a key belongs to, and the templates its projects are built from.
/api/v1/workspaceThe key's workspace: its name, plan, the formats and platforms it posts to, and how many projects it has. A good first call to check a key works.
MCP tool: get_workspace
Example request
curl https://clips.lnr.ae/api/v1/workspace \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"id": "6f1c2b8e-4a3d-4e6f-9b1a-2c7d8e9f0a1b",
"name": "Lunar Coffee",
"slug": "lunar-coffee",
"createdAt": "2026-10-01T08:00:00.000Z",
"plan": "pro",
"formats": [
"vertical"
],
"platforms": [
"instagram",
"tiktok"
],
"postsPerWeek": 5,
"projectCount": 12
},
"error": null
}/api/v1/templatesList templates
ReadEvery template with its scenes, a plain description of each field, its JSON Schema and a working example, plus the starters you can create a project from without writing props.
MCP tool: list_templates
Example request
curl https://clips.lnr.ae/api/v1/templates \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"templates": [
{
"id": "stat-reveal",
"name": "Stat reveal",
"summary": "One striking number, revealed and explained.",
"durationSeconds": 15,
"scenes": [
{
"name": "Hook",
"from": 0,
"to": 3
}
],
"fields": [
{
"path": "brand.name",
"description": "Brand name shown at the end, 1–40 characters."
}
],
"propsSchema": {
"type": "object"
},
"exampleProps": {}
}
],
"starters": [
{
"id": "coffee",
"label": "Coffee shop"
}
]
},
"error": null
}Projects
Editable videos built from a template. Create one from a starter or from full props, then change it until it's right.
/api/v1/projectsList projects
ReadProjects, newest first, a page at a time.
MCP tool: list_projects
Parameters
limitintegerQueryOptionalHow many to return. (1–100, default 20)
cursorstringQueryOptionalThe `nextCursor` from the previous page.
Example request
curl https://clips.lnr.ae/api/v1/projects \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"projects": [
{
"id": "6f1c2b8e-4a3d-4e6f-9b1a-2c7d8e9f0a1b",
"title": "Coffee facts",
"template": "stat-reveal",
"createdAt": "2026-11-14T09:30:00.000Z",
"updatedAt": "2026-11-14T09:30:00.000Z"
}
],
"nextCursor": null
},
"error": null
}/api/v1/projectsCreate a project
WriteSend a template with a starter (and optionally a name, hook and accent colour), or a template with full props from List templates.
MCP tool: create_project
Body
titlestringRequired(1–120 characters)
template"stat-reveal" | "problem-solution"Requiredstarter"clips" | "coffee" | "science" | "kids" | "history"OptionalUse a starter, or send props.
namestringOptionalWith a starter: the brand name. (at most 40 characters)
hookstringOptionalWith a starter: the opening line. (at most 80 characters)
accentstringOptionalWith a starter: the accent colour. (matches ^#[0-9a-fA-F]{6}$)
propsobjectOptionalThe template's full props, instead of a starter.
Example request
curl -X POST https://clips.lnr.ae/api/v1/projects \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Coffee facts",
"template": "stat-reveal",
"starter": "coffee",
"name": "Lunar Coffee",
"accent": "#c8a26b"
}'Example response
HTTP 201{
"data": {
"id": "6f1c2b8e-4a3d-4e6f-9b1a-2c7d8e9f0a1b",
"title": "Coffee facts",
"template": "stat-reveal",
"createdAt": "2026-11-14T09:30:00.000Z",
"updatedAt": "2026-11-14T09:30:00.000Z",
"props": {
"brand": {
"name": "Lunar Coffee",
"accent": "#c8a26b"
}
}
},
"error": null
}/api/v1/projects/{id}Get a project
ReadOne project with its full props.
MCP tool: get_project
Parameters
idstring (uuid)PathRequiredThe project's id.
Example request
curl https://clips.lnr.ae/api/v1/projects/ID \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"id": "6f1c2b8e-4a3d-4e6f-9b1a-2c7d8e9f0a1b",
"title": "Coffee facts",
"template": "stat-reveal",
"createdAt": "2026-11-14T09:30:00.000Z",
"updatedAt": "2026-11-14T09:30:00.000Z",
"props": {
"brand": {
"name": "Lunar Coffee",
"accent": "#c8a26b"
}
}
},
"error": null
}/api/v1/projects/{id}Update a project
WriteRename it, replace its props, or both. New props replace the old ones whole and must fit the project's template.
MCP tool: update_project
Parameters
idstring (uuid)PathRequiredThe project's id.
Body
titlestringOptional(1–120 characters)
propsobjectOptional
Example request
curl -X PATCH https://clips.lnr.ae/api/v1/projects/ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Coffee facts, take two"
}'Example response
HTTP 200{
"data": {
"id": "6f1c2b8e-4a3d-4e6f-9b1a-2c7d8e9f0a1b",
"title": "Coffee facts, take two",
"template": "stat-reveal",
"createdAt": "2026-11-14T09:30:00.000Z",
"updatedAt": "2026-11-14T09:30:00.000Z",
"props": {}
},
"error": null
}/api/v1/projects/{id}Delete a project
WriteDeletes the project. This can't be undone.
Parameters
idstring (uuid)PathRequiredThe project's id.
Example request
curl -X DELETE https://clips.lnr.ae/api/v1/projects/ID \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"id": "6f1c2b8e-4a3d-4e6f-9b1a-2c7d8e9f0a1b"
},
"error": null
}AI video generation
Have the AI director write, voice and edit a video from a prompt, saved as a project you can open in the editor.
/api/v1/videos/generateThe formats the director knows, with the fields each one asks for. Use one instead of a free prompt for a predictable structure.
Example request
curl https://clips.lnr.ae/api/v1/videos/generate \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"formats": [
{
"id": "explainer-30",
"name": "Explainer in 30 Seconds",
"summary": "One idea, explained clearly.",
"lengthSeconds": 30,
"fields": [
{
"id": "topic",
"label": "Topic",
"required": true,
"maxLength": 80
}
]
}
]
},
"error": null
}/api/v1/videos/generateGenerate a video
WriteMakes a video from a prompt, or from a format and its fields, and saves it as a project. By default the request waits for the result, usually 1 to 4 minutes, so allow a long timeout. Send "wait": false to get a sessionId back at once (HTTP 202) and poll Get a video session instead. Paid plans only; each video costs credits and counts against the plan's monthly AI video allowance.
MCP tool: generate_video
Body
promptstringOptionalWhat the video is about. Send this, or a format. (at most 4000 characters)
formatstringOptionalA format id from List video formats.
fieldsobjectOptionalThe format's fields, by id (at most 8).
lengthSecondsintegerOptional(10–60, default 30)
voicebooleanOptional(default true)
musicbooleanOptional(default true)
captions"standard" | "animated" | "off"Optional(default "standard")
brollbooleanOptionalAdd stock footage between scenes. (default false)
platform"tiktok" | "instagram" | "linkedin" | "all"Optional(default "all")
waitbooleanOptionalfalse: answer at once with a sessionId (HTTP 202) and poll Get a video session. (default true)
Example request
curl -X POST https://clips.lnr.ae/api/v1/videos/generate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"format": "product-ad",
"fields": {
"product": "Halo, a smart water bottle",
"problem": "People forget to drink water at work",
"cta": "Try it for 30 days"
},
"lengthSeconds": 20
}'Example response
HTTP 201{
"data": {
"projectId": "6f1c2b8e-4a3d-4e6f-9b1a-2c7d8e9f0a1b",
"title": "Halo: drink more without thinking",
"sessionId": "0b9e7c4d-2f1a-4c3b-8d5e-6f7a8b9c0d1e",
"message": "A 20-second ad: the problem, Halo's reminder glow, the 40% proof, then the offer.",
"editorUrl": "https://clips.lnr.ae/app/editor/6f1c2b8e-4a3d-4e6f-9b1a-2c7d8e9f0a1b"
},
"error": null
}AI studio
Follow and revise AI videos, make product films of real apps, and film AI footage. Paid calls reserve credits first and give them back when nothing is made.
/api/v1/videos/sessions/{id}An AI video session started through the API or MCP: running, done or failed, the live steps, the saved project, its scenes and the latest messages. Poll every 15–30 seconds while it runs. Chats made in the app aren't listed here. Free.
MCP tool: get_video_session
Parameters
idstring (uuid)PathRequiredThe sessionId from Generate a video.
Example request
curl https://clips.lnr.ae/api/v1/videos/sessions/ID \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"id": "4d2a9c71-3e5b-4f08-b1c6-7a9e2d4f6b13",
"title": "Heat pumps in 30 seconds",
"status": "done",
"updatedAt": "2026-11-14T09:12:44.208Z",
"projectId": "9e1b7c3a-2f4d-4a6e-8b5c-1d3f5a7e9c20",
"editorUrl": "https://clips.lnr.ae/app/editor/9e1b7c3a-2f4d-4a6e-8b5c-1d3f5a7e9c20",
"revisions": {
"used": 1,
"limit": 10
},
"steps": [],
"scenes": [
{
"id": "hook",
"type": "kinetic-title",
"text": "Your boiler is burning money"
},
{
"id": "stat",
"type": "big-number",
"text": "3x more efficient than gas"
},
{
"id": "outro",
"type": "brand-outro",
"text": "Switch this winter"
}
],
"messages": [
{
"role": "user",
"content": "A 30 second explainer on how heat pumps work, calm and clear",
"projectId": null,
"createdAt": "2026-11-14T09:05:02.114Z"
},
{
"role": "assistant",
"content": "Your video is ready: a calm 30 second explainer in three scenes.",
"projectId": "9e1b7c3a-2f4d-4a6e-8b5c-1d3f5a7e9c20",
"createdAt": "2026-11-14T09:08:31.902Z"
},
{
"role": "user",
"content": "Make the hook shorter",
"projectId": null,
"createdAt": "2026-11-14T09:10:57.330Z"
},
{
"role": "assistant",
"content": "Done: the hook is now four words and lands in under two seconds.",
"projectId": "9e1b7c3a-2f4d-4a6e-8b5c-1d3f5a7e9c20",
"createdAt": "2026-11-14T09:12:44.150Z"
}
]
},
"error": null
}/api/v1/videos/sessions/{id}/reviseRevise a video
WriteChange a generated video by instruction, the whole video or one scene (sceneId). A revision costs 1 credit up to the plan's cap per video; newVersion, or a change past the cap, costs a new video (10 credits). Answers at once; poll the session. With "wait": true it answers 200 with the session when done (1–4 minutes).
MCP tool: revise_video
Parameters
idstring (uuid)PathRequiredThe video's sessionId.
Body
instructionstringRequired(at most 4000 characters)
sceneIdstringOptional(matches ^[a-z0-9-]{1,32}$)
newVersionbooleanOptional(default false)
voiceIdstringOptionallanguagestringOptionalmodelIdstringOptionalwaitbooleanOptional(default false)
Example request
curl -X POST https://clips.lnr.ae/api/v1/videos/sessions/ID/revise \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"instruction": "Use an Arabic voice and make the hook shorter",
"language": "ar"
}'Example response
HTTP 202{
"data": {
"sessionId": "4d2a9c71-3e5b-4f08-b1c6-7a9e2d4f6b13",
"title": "Heat pumps in 30 seconds",
"status": "running"
},
"error": null
}/api/v1/videos/voicesList voices
ReadNarrators to pass as voiceId when revising, and the languages a video can be written and voiced in. source=library searches the public voice library. Free.
MCP tool: list_voices
Parameters
source"account" | "library"QueryOptionalCurated narrators, or the public library. (default "account")
searchstringQueryOptionalWith source=library: words to search for. (at most 60 characters)
languagestringQueryOptionalWith source=library: an ISO 639-1 code.
Example request
curl https://clips.lnr.ae/api/v1/videos/voices \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"voices": [
{
"id": "a1B2c3D4e5F6g7H8i9J0",
"name": "Alice",
"tagline": "Clear, Engaging Educator",
"gender": "female",
"accent": "british",
"age": "middle_aged",
"language": "en",
"useCase": "educational",
"descriptive": "confident",
"previewUrl": "https://…/alice-preview.mp3"
}
],
"languages": [
{
"id": "en",
"name": "English"
},
{
"id": "ar",
"name": "Arabic"
}
],
"hasMore": false
},
"error": null
}/api/v1/videos/modelsThe models the director can run on, by Clips' public name, with each one's tier and the credits a new video costs on it. Pass an id as modelId when revising. Free.
MCP tool: list_video_models
Example request
curl https://clips.lnr.ae/api/v1/videos/models \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"models": [
{
"id": "m_3f9a1c7e5b2d8a40",
"label": "Clips Pro",
"tier": "premium",
"credits": 10,
"recommended": true
}
],
"defaultId": "m_3f9a1c7e5b2d8a40"
},
"error": null
}/api/v1/filmsThe workspace's product films, newest first, with a download link for finished ones. Free.
MCP tool: list_films
Parameters
limitintegerQueryOptionalHow many to return. (1–100, default 20)
cursorstringQueryOptionalThe nextCursor from the previous page.
Example request
curl https://clips.lnr.ae/api/v1/films \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"films": [
{
"id": "b7f3d1e9-6a2c-4e85-9d47-2c8a6e0f4b31",
"status": "succeeded",
"stage": "Ready in your Library",
"style": {
"id": "glass",
"name": "Glass"
},
"aspect": "9:16",
"brief": "Show how Halo turns support tickets into answers in seconds.",
"message": null,
"storagePath": "6b1f0c2e-8d4a-4f3b-9a1e-2c7d5e9f0a11/library/halo-product-film.mp4",
"downloadUrl": "https://storage.clips.lnr.ae/storage/v1/object/sign/media/…/halo-product-film.mp4?token=…",
"createdAt": "2026-11-14T08:40:10.512Z",
"finishedAt": "2026-11-14T08:52:37.006Z"
}
],
"nextCursor": null
},
"error": null
}/api/v1/filmsA cinematic film of a real app from its public link and/or library screenshots. Costs 10 credits, reserved first and refunded if it can't be made; takes about 5–15 minutes, so poll Get a product film. Styles: glass, studio-light, fluid, isometric, flow, turnaround, minimal, neon, vivid, ribbon, canvas, playful, sunlit.
MCP tool: create_film
Body
briefstringRequired(at most 4000 characters)
style"glass" | "studio-light" | "fluid" | "isometric" | "flow" | "turnaround" | "minimal" | "neon" | "vivid" | "ribbon" | "canvas" | "playful" | "sunlit"Requiredaspect"9:16" | "16:9"Optional(default "9:16")
productUrlstringOptionalproductScreensarray of stringOptional(at most 8 items)
brandKitIdstring (uuid)OptionalbrandobjectOptional{ kind: "kit" } (default), { kind: "link", url }, or { kind: "none", name? }.
wideScreens"crop" | "whole"Optional(default "crop")
Example request
curl -X POST https://clips.lnr.ae/api/v1/films \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"brief": "Show how Halo turns support tickets into answers in seconds.",
"style": "glass",
"productUrl": "https://app.halo.example"
}'Example response
HTTP 201{
"data": {
"id": "b7f3d1e9-6a2c-4e85-9d47-2c8a6e0f4b31",
"status": "writing",
"stage": "Writing the film",
"style": {
"id": "glass",
"name": "Glass"
},
"aspect": "9:16",
"brief": "Show how Halo turns support tickets into answers in seconds.",
"message": null,
"storagePath": null,
"downloadUrl": null,
"createdAt": "2026-11-14T08:40:10.512Z",
"finishedAt": null
},
"error": null
}/api/v1/films/{id}A film's status (writing, queued, rendering, replan, succeeded, failed) and stage, and a download link that works for 15 minutes once it has succeeded. Free.
MCP tool: get_film
Parameters
idstring (uuid)PathRequiredThe film's id.
Example request
curl https://clips.lnr.ae/api/v1/films/ID \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"id": "b7f3d1e9-6a2c-4e85-9d47-2c8a6e0f4b31",
"status": "succeeded",
"stage": "Ready in your Library",
"style": {
"id": "glass",
"name": "Glass"
},
"aspect": "9:16",
"brief": "Show how Halo turns support tickets into answers in seconds.",
"message": null,
"storagePath": "6b1f0c2e-8d4a-4f3b-9a1e-2c7d5e9f0a11/library/halo-product-film.mp4",
"downloadUrl": "https://storage.clips.lnr.ae/storage/v1/object/sign/media/…/halo-product-film.mp4?token=…",
"createdAt": "2026-11-14T08:40:10.512Z",
"finishedAt": "2026-11-14T08:52:37.006Z"
},
"error": null
}/api/v1/footageList AI footage
ReadAI clips, stills and 4K upscales, newest first, with credits used and download links for finished ones. Free.
MCP tool: list_footage
Parameters
limitintegerQueryOptionalHow many to return. (1–100, default 20)
cursorstringQueryOptionalThe nextCursor from the previous page.
Example request
curl https://clips.lnr.ae/api/v1/footage \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"footage": [
{
"id": "e2c84a6f-1b9d-4d3e-a7f5-8c0b2e4d6a19",
"kind": "video",
"status": "succeeded",
"model": "motion-2-5",
"modelName": "Lunar Motion 2.5",
"prompt": "A barista pouring latte art in a sunlit cafe, slow motion",
"seconds": 5,
"credits": 15,
"createdAt": "2026-11-14T10:02:18.441Z",
"error": null,
"storagePath": "6b1f0c2e-8d4a-4f3b-9a1e-2c7d5e9f0a11/library/ai-footage/e2c84a6f-1b9d-4d3e-a7f5-8c0b2e4d6a19-barista-latte-art.mp4",
"downloadUrl": "https://storage.clips.lnr.ae/storage/v1/object/sign/media/…/barista-latte-art.mp4?token=…",
"posterUrl": "https://storage.clips.lnr.ae/storage/v1/object/sign/media/…/barista-latte-art.jpg?token=…"
}
],
"nextCursor": null
},
"error": null
}/api/v1/footageGenerate AI footage
WriteFilm a clip from a prompt; it is saved to the library. 15 credits per clip-sized unit (dearer models, lengths and sound take more), reserved first and given back if it fails. Models: motion-2-5 (Starter+), hailuo-h3 (Growth+), wan-3-0 (Growth+), kling-3-0-pro (Growth+), veo-3-1 (Scale+). Poll Get AI footage (1–3 minutes).
MCP tool: generate_footage
Body
promptstringRequired(3–800 characters)
model"motion-2-5" | "hailuo-h3" | "wan-3-0" | "kling-3-0-pro" | "veo-3-1"Optional(default "motion-2-5")
secondsintegerOptional(default 5)
withSoundbooleanOptional(default false)
shotstringOptionalcamerastringOptionallightingstringOptionallookstringOptionalfirstFramePathstringOptional
Example request
curl -X POST https://clips.lnr.ae/api/v1/footage \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A barista pouring latte art in a sunlit cafe, slow motion",
"model": "motion-2-5",
"seconds": 5
}'Example response
HTTP 202{
"data": {
"id": "e2c84a6f-1b9d-4d3e-a7f5-8c0b2e4d6a19",
"kind": "video",
"status": "running",
"model": "motion-2-5",
"modelName": "Lunar Motion 2.5",
"prompt": "A barista pouring latte art in a sunlit cafe, slow motion",
"seconds": 5,
"credits": 15,
"createdAt": "2026-11-14T10:02:18.441Z",
"error": null,
"storagePath": null,
"downloadUrl": null,
"posterUrl": null
},
"error": null
}/api/v1/footage/{id}Get AI footage
ReadA clip's status and, once it has succeeded, its storagePath (post it with POST /api/v1/posts) and a download link that works for 15 minutes. Free.
MCP tool: get_footage
Parameters
idstring (uuid)PathRequiredThe clip's id.
Example request
curl https://clips.lnr.ae/api/v1/footage/ID \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"id": "e2c84a6f-1b9d-4d3e-a7f5-8c0b2e4d6a19",
"kind": "video",
"status": "succeeded",
"model": "motion-2-5",
"modelName": "Lunar Motion 2.5",
"prompt": "A barista pouring latte art in a sunlit cafe, slow motion",
"seconds": 5,
"credits": 15,
"createdAt": "2026-11-14T10:02:18.441Z",
"error": null,
"storagePath": "6b1f0c2e-8d4a-4f3b-9a1e-2c7d5e9f0a11/library/ai-footage/e2c84a6f-1b9d-4d3e-a7f5-8c0b2e4d6a19-barista-latte-art.mp4",
"downloadUrl": "https://storage.clips.lnr.ae/storage/v1/object/sign/media/…/barista-latte-art.mp4?token=…",
"posterUrl": "https://storage.clips.lnr.ae/storage/v1/object/sign/media/…/barista-latte-art.jpg?token=…"
},
"error": null
}/api/v1/footage/{id}/upscaleUpscale a finished AI clip to 4K (Growth and Scale). Draws credits by the clip's length, reserved first and given back if it fails. Returns the new upscale; poll Get AI footage.
MCP tool: upscale_footage
Parameters
idstring (uuid)PathRequiredThe finished clip's id.
Example request
curl -X POST https://clips.lnr.ae/api/v1/footage/ID/upscale \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 202{
"data": {
"id": "f4a1c9e3-7d2b-4b6a-9e8c-3a5d7f1b2c40",
"kind": "upscale",
"status": "running",
"model": "bytedance-upscaler",
"modelName": "4K upscale",
"prompt": "A barista pouring latte art in a sunlit cafe, slow motion",
"seconds": 5,
"credits": 15,
"createdAt": "2026-11-14T10:02:18.441Z",
"error": null,
"storagePath": null,
"downloadUrl": null,
"posterUrl": null
},
"error": null
}Rendering
Turn a template project into an MP4 on the Clips server, then download it or post it.
/api/v1/projects/{id}/renderStarts rendering a template project (stat-reveal or problem-solution) to the same MP4 the editor's export makes, saved to the library. Answers at once; poll Get a video with the videoId until status is done (usually one to three minutes), then use its downloadUrl or post it. One render at a time per workspace (429 while one runs) and a daily number by plan (Starter 10, Growth 30, Scale 100, UTC days). No credits. size is 720p or 1080p, up to the plan's export size; the body is optional.
MCP tool: render_project
Parameters
idstring (uuid)PathRequiredThe project's id.
Body
size"720p" | "1080p"OptionalOutput size by the short side of the 9:16 frame. Default: 1080p where the plan allows it.
Example request
curl -X POST https://clips.lnr.ae/api/v1/projects/ID/render \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"size": "1080p"
}'Example response
HTTP 202{
"data": {
"videoId": "9d2e4f6a-1b3c-4d5e-8f7a-0b1c2d3e4f5a",
"status": "pending",
"projectId": "6f1c2b8e-4a3d-4e6f-9b1a-2c7d8e9f0a1b",
"title": "Coffee facts",
"size": "1080p",
"storagePath": "6b1f0c2e-8d4a-4f3b-9a1e-2c7d5e9f0a11/library/9d2e4f6a-1b3c-4d5e-8f7a-0b1c2d3e4f5a-coffee-facts.mp4"
},
"error": null
}Videos and library
Find finished videos and library files, download them, and upload your own MP4s, so you have a videoId or storagePath to post.
/api/v1/videosFinished MP4s, newest first. A video gets a record once Clips has rendered or scheduled it; MP4s you only uploaded are in the library. Pass a video's id as videoId, or its storagePath, to POST /api/v1/posts.
MCP tool: list_videos
Parameters
limitintegerQueryOptionalHow many to return. (1–100, default 20)
cursorstringQueryOptionalThe nextCursor from the previous page.
Example request
curl https://clips.lnr.ae/api/v1/videos \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"videos": [
{
"id": "c3a9e7d2-5b14-4e8f-a6d0-91b2f4c8e735",
"title": "Launch teaser",
"source": "upload",
"storagePath": "6b1f0c2e-8d4a-4f3b-9a1e-2c7d5e9f0a11/library/8e2b5c1a-4f7d-4a3e-b9c6-0d1e2f3a4b5c-launch-teaser.mp4",
"durationMs": 28400,
"createdAt": "2026-11-12T09:41:07.512Z"
}
],
"nextCursor": null
},
"error": null
}/api/v1/videos/{id}Get a video
ReadOne video with its status and a download link that works for 15 minutes. downloadUrl is null until the render is done. Ask again for a fresh link rather than storing one.
MCP tool: get_video
Parameters
idstring (uuid)PathRequiredThe video's id, from List finished videos.
Example request
curl https://clips.lnr.ae/api/v1/videos/ID \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"id": "c3a9e7d2-5b14-4e8f-a6d0-91b2f4c8e735",
"title": "Launch teaser",
"source": "upload",
"storagePath": "6b1f0c2e-8d4a-4f3b-9a1e-2c7d5e9f0a11/library/8e2b5c1a-4f7d-4a3e-b9c6-0d1e2f3a4b5c-launch-teaser.mp4",
"durationMs": 28400,
"createdAt": "2026-11-12T09:41:07.512Z",
"status": "done",
"downloadUrl": "https://storage.clips.lnr.ae/storage/v1/object/sign/media/…/launch-teaser.mp4?token=…&download=launch-teaser.mp4",
"downloadUrlExpiresAt": "2026-11-14T10:15:00.000Z"
},
"error": null
}/api/v1/libraryFiles in the media library (your uploads and AI footage), newest first, with the library's folders. A file with postable: true is an MP4 you can pass as storagePath to POST /api/v1/posts. Files waiting for a content review are left out.
MCP tool: list_library
Parameters
folderstringQueryOptionalall, unfiled, or a folder id from the folders list. (default "all")
kind"video" | "image" | "audio" | "pdf"QueryOptionalOnly files of this kind.
limitintegerQueryOptionalHow many to return. (1–100, default 20)
cursorstringQueryOptionalThe nextCursor from the previous page.
Example request
curl https://clips.lnr.ae/api/v1/library \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"folders": [
{
"id": "0f5d8a3c-7e21-4b96-8c4d-3a6e9b1f2d58",
"name": "November campaign"
}
],
"files": [
{
"name": "launch-teaser.mp4",
"storagePath": "6b1f0c2e-8d4a-4f3b-9a1e-2c7d5e9f0a11/library/8e2b5c1a-4f7d-4a3e-b9c6-0d1e2f3a4b5c-launch-teaser.mp4",
"kind": "video",
"mimeType": "video/mp4",
"sizeBytes": 18734210,
"createdAt": "2026-11-12T09:38:52.104Z",
"folderId": "0f5d8a3c-7e21-4b96-8c4d-3a6e9b1f2d58",
"postable": true
},
{
"name": "product-shot.png",
"storagePath": "6b1f0c2e-8d4a-4f3b-9a1e-2c7d5e9f0a11/library/2d4f6a8c-1b3e-4c5d-8e7f-9a0b1c2d3e4f-product-shot.png",
"kind": "image",
"mimeType": "image/png",
"sizeBytes": 842113,
"createdAt": "2026-11-10T16:02:31.877Z",
"folderId": null,
"postable": false
}
],
"nextCursor": "MjAyNi0xMS0xMFQxNjowMjozMS44Nzd8MmQ0ZjZhOGMtMWIzZS00YzVkLThlN2YtOWEwYjFjMmQzZTRm"
},
"error": null
}/api/v1/library/uploadsReturns a signed URL for one new file and the storagePath it will have. PUT the bytes to uploadUrl with the returned headers within two hours, then call Complete an upload with the same storagePath and sizeBytes to start the file's content check. Videos, raster images, audio and PDFs up to 1 GB are accepted, within your plan's library storage.
MCP tool: create_upload_url
Body
fileNamestringRequiredThe file's name with its extension. (1–200 characters)
contentTypestringRequiredThe file's mime type, e.g. video/mp4. SVG isn't accepted.
sizeBytesintegerRequiredThe file's exact size in bytes. (at least 1)
Example request
curl -X POST https://clips.lnr.ae/api/v1/library/uploads \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fileName": "launch-teaser.mp4",
"contentType": "video/mp4",
"sizeBytes": 18734210
}'Example response
HTTP 201{
"data": {
"storagePath": "6b1f0c2e-8d4a-4f3b-9a1e-2c7d5e9f0a11/library/8e2b5c1a-4f7d-4a3e-b9c6-0d1e2f3a4b5c-launch-teaser.mp4",
"uploadUrl": "https://storage.clips.lnr.ae/storage/v1/object/upload/sign/media/…/launch-teaser.mp4?token=…",
"method": "PUT",
"headers": {
"Content-Type": "video/mp4"
},
"expiresAt": "2026-11-14T12:00:00.000Z",
"kind": "video",
"postable": true
},
"error": null
}/api/v1/library/uploads/completeComplete an upload
WriteCall once the PUT to uploadUrl has finished. Clips reads the stored file: if its real size differs from sizeBytes, it isn't a type the library takes, or it takes the workspace over its plan's storage, the file is removed and the call fails. Otherwise its content check starts. POST /api/v1/posts accepts the file once the check is done, usually within a minute; until then it answers that the file is still being checked.
MCP tool: complete_upload
Body
storagePathstringRequiredThe storagePath the upload request returned. (at most 400 characters)
sizeBytesintegerRequiredThe sizeBytes sent with the upload request. (at least 1)
Example request
curl -X POST https://clips.lnr.ae/api/v1/library/uploads/complete \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"storagePath": "6b1f0c2e-8d4a-4f3b-9a1e-2c7d5e9f0a11/library/8e2b5c1a-4f7d-4a3e-b9c6-0d1e2f3a4b5c-launch-teaser.mp4",
"sizeBytes": 18734210
}'Example response
HTTP 200{
"data": {
"storagePath": "6b1f0c2e-8d4a-4f3b-9a1e-2c7d5e9f0a11/library/8e2b5c1a-4f7d-4a3e-b9c6-0d1e2f3a4b5c-launch-teaser.mp4",
"name": "launch-teaser.mp4",
"kind": "video",
"sizeBytes": 18734210,
"postable": true,
"contentCheck": "started"
},
"error": null
}/api/v1/videos/{id}Rename a video
WriteChanges a video's title. Videos have no separate description.
MCP tool: rename_video
Parameters
idstring (uuid)PathRequiredThe video's id.
Body
titlestringRequired(1–120 characters)
Example request
curl -X PATCH https://clips.lnr.ae/api/v1/videos/ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Launch teaser (final)"
}'Example response
HTTP 200{
"data": {
"id": "c3a9e7d2-5b14-4e8f-a6d0-91b2f4c8e735",
"title": "Launch teaser (final)"
},
"error": null
}/api/v1/library/foldersThe library's folders, A to Z, with how many files each holds. Folders are labels: filing a file never changes its storagePath.
MCP tool: list_folders
Example request
curl https://clips.lnr.ae/api/v1/library/folders \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"folders": [
{
"id": "0f5d8a3c-7e21-4b96-8c4d-3a6e9b1f2d58",
"name": "November campaign",
"fileCount": 12
}
]
},
"error": null
}/api/v1/library/foldersCreates a folder. A library holds up to 100.
MCP tool: create_folder
Body
namestringRequiredUnique in the library, ignoring case. (1–60 characters)
Example request
curl -X POST https://clips.lnr.ae/api/v1/library/folders \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "November campaign"
}'Example response
HTTP 201{
"data": {
"id": "0f5d8a3c-7e21-4b96-8c4d-3a6e9b1f2d58",
"name": "November campaign"
},
"error": null
}/api/v1/library/folders/{id}Renames a folder.
MCP tool: rename_folder
Parameters
idstring (uuid)PathRequiredThe folder's id.
Body
namestringRequiredUnique in the library, ignoring case. (1–60 characters)
Example request
curl -X PATCH https://clips.lnr.ae/api/v1/library/folders/ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "December campaign"
}'Example response
HTTP 200{
"data": {
"id": "0f5d8a3c-7e21-4b96-8c4d-3a6e9b1f2d58",
"name": "December campaign"
},
"error": null
}/api/v1/library/folders/{id}Deletes a folder. Its files aren't deleted: they go back to Unfiled. With ?preview=1 it returns the preview and deletes nothing.
MCP tool: delete_folder
Parameters
idstring (uuid)PathRequiredThe folder's id.
preview"1"QueryOptional1 returns what would happen without changing anything.
Example request
curl -X DELETE https://clips.lnr.ae/api/v1/library/folders/ID \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"id": "0f5d8a3c-7e21-4b96-8c4d-3a6e9b1f2d58"
},
"error": null
}/api/v1/library/files/moveFiles up to 500 library files in a folder, or back in Unfiled with folderId null. Nothing moves in storage, so storagePaths and posts using them keep working.
MCP tool: move_files
Body
storagePathsarray of stringRequiredstoragePath values from List library files. (1–500 items)
folderIdstring | null (uuid)Required
Example request
curl -X POST https://clips.lnr.ae/api/v1/library/files/move \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"storagePaths": [
"6b1f0c2e-8d4a-4f3b-9a1e-2c7d5e9f0a11/library/8e2b5c1a-4f7d-4a3e-b9c6-0d1e2f3a4b5c-launch-teaser.mp4",
"6b1f0c2e-8d4a-4f3b-9a1e-2c7d5e9f0a11/library/2d4f6a8c-1b3e-4c5d-8e7f-9a0b1c2d3e4f-product-shot.png"
],
"folderId": "0f5d8a3c-7e21-4b96-8c4d-3a6e9b1f2d58"
}'Example response
HTTP 200{
"data": {
"moved": 2,
"folderId": "0f5d8a3c-7e21-4b96-8c4d-3a6e9b1f2d58"
},
"error": null
}/api/v1/library/files/deleteDelete library files
WritePermanently deletes up to 500 library files. This can't be undone, and posts that haven't gone out yet and use a deleted MP4 will fail. Call with ?preview=1 first: it lists the files and counts those posts without deleting anything.
MCP tool: delete_files
Parameters
preview"1"QueryOptional1 returns what would happen without changing anything.
Body
storagePathsarray of stringRequiredstoragePath values from List library files. (1–500 items)
Example request
curl -X POST https://clips.lnr.ae/api/v1/library/files/delete \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"storagePaths": [
"6b1f0c2e-8d4a-4f3b-9a1e-2c7d5e9f0a11/library/2d4f6a8c-1b3e-4c5d-8e7f-9a0b1c2d3e4f-product-shot.png"
]
}'Example response
HTTP 200{
"data": {
"deleted": [
"6b1f0c2e-8d4a-4f3b-9a1e-2c7d5e9f0a11/library/2d4f6a8c-1b3e-4c5d-8e7f-9a0b1c2d3e4f-product-shot.png"
],
"failed": 0
},
"error": null
}Connected accounts
The social accounts connected to the workspace, how posts reach each one, and the weekly posting times that next_free_slot fills.
/api/v1/accountsList accounts
ReadThe connected accounts with their delivery (`direct`: Clips posts it; `tiktok_inbox`: lands in the creator's TikTok inbox and they tap Post; `manual`: the person posts it; `browser`: temporary Lunar-owned TikTok mode), timezone and next free posting slots. Call this before scheduling.
MCP tool: list_connected_accounts
Example request
curl https://clips.lnr.ae/api/v1/accounts \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"accounts": [
{
"id": "c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b",
"platform": "instagram",
"handle": "@lunarcoffee",
"status": "connected",
"publishMode": "auto",
"delivery": "direct",
"timezone": "Asia/Dubai",
"nextFreeSlots": [
"2026-11-16T05:00:00.000Z"
]
},
{
"id": "d7e8f9a0-1b2c-4d3e-8f4a-5b6c7d8e9f0a",
"platform": "tiktok",
"handle": "@lunarcoffee",
"status": "connected",
"publishMode": "auto",
"delivery": "tiktok_inbox",
"timezone": "Asia/Dubai",
"nextFreeSlots": [
"2026-11-16T15:00:00.000Z"
]
}
]
},
"error": null
}/api/v1/accounts/{id}Get an account
ReadOne account in this workspace, connected or not: status (`connected`, `needs_reauth` or `disconnected`), delivery, timezone, its weekly posting times (weekday 0 = Sunday, local 24-hour time) and its next free slots.
MCP tool: get_account
Parameters
idstring (uuid)PathRequiredThe account's id, from List accounts.
Example request
curl https://clips.lnr.ae/api/v1/accounts/ID \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"id": "c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b",
"platform": "instagram",
"handle": "@lunarcoffee",
"status": "connected",
"publishMode": "auto",
"delivery": "direct",
"timezone": "Asia/Dubai",
"postingTimes": [
{
"weekday": 1,
"time": "09:00"
},
{
"weekday": 3,
"time": "18:30"
},
{
"weekday": 5,
"time": "12:00"
}
],
"nextFreeSlots": [
"2026-11-16T05:00:00.000Z",
"2026-11-18T14:30:00.000Z"
]
},
"error": null
}/api/v1/accounts/{id}/posting-timesReplaces the account's weekly posting times with the list you send (an empty list clears them; repeats are dropped; at most 42). Times are in the account's timezone. Posts already scheduled keep their times. Returns the updated account.
MCP tool: set_posting_times
Parameters
idstring (uuid)PathRequiredThe account's id, from List accounts.
preview"1"QueryOptional`1` runs every check and returns `{ preview }` (what would happen) without changing anything.
Body
postingTimesarray of objectRequired(at most 42 items)
Example request
curl -X PUT https://clips.lnr.ae/api/v1/accounts/ID/posting-times \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"postingTimes": [
{
"weekday": 1,
"time": "09:00"
},
{
"weekday": 3,
"time": "18:30"
},
{
"weekday": 5,
"time": "12:00"
}
]
}'Example response
HTTP 200{
"data": {
"id": "c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b",
"platform": "instagram",
"handle": "@lunarcoffee",
"status": "connected",
"publishMode": "auto",
"delivery": "direct",
"timezone": "Asia/Dubai",
"postingTimes": [
{
"weekday": 1,
"time": "09:00"
},
{
"weekday": 3,
"time": "18:30"
},
{
"weekday": 5,
"time": "12:00"
}
],
"nextFreeSlots": [
"2026-11-16T05:00:00.000Z",
"2026-11-18T14:30:00.000Z"
]
},
"error": null
}Posts and calendar
Schedule a finished MP4 to connected accounts, then follow, change, retry, copy or cancel the posts and read their numbers.
/api/v1/postsList posts
ReadPosts, latest scheduled time first, filtered by status, account, platform or a scheduled-time range. `failureReason` is set only on failed posts.
MCP tool: list_posts
Parameters
status"draft" | "ready" | "approved" | "scheduled" | "publishing" | "awaiting_creator" | "published" | "failed" | "cancelled"QueryOptional`ready` waits for approval; `awaiting_creator` waits for the person (e.g. their TikTok inbox).
accountIdstring (uuid)QueryOptionalOnly this account's posts.
platform"instagram" | "tiktok" | "linkedin" | "facebook" | "threads" | "youtube" | "pinterest"QueryOptionalOnly this platform's posts.
fromstring (date-time)QueryOptionalScheduled at or after this time (ISO 8601 with offset).
tostring (date-time)QueryOptionalScheduled before this time (ISO 8601 with offset).
limitintegerQueryOptionalHow many to return. (1–100, default 20)
Example request
curl https://clips.lnr.ae/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"posts": [
{
"id": "3f8f6c1e-2b4a-4c3d-9e5f-1a2b3c4d5e6f",
"platform": "instagram",
"accountId": "c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b",
"status": "scheduled",
"caption": "Three things nobody tells you about cold brew.",
"hashtags": [
"coldbrew",
"coffee"
],
"scheduledFor": "2026-11-16T14:00:00.000Z",
"publishedAt": null,
"externalUrl": null,
"failureReason": null,
"videoId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
}
]
},
"error": null
}/api/v1/postsSchedules a finished MP4 (a `videoId`, or a Library `storagePath`) to up to 3 accounts, one per platform, with a caption per platform. `when` is "next_free_slot" (default), an ISO time, or "now" to publish within about a minute (the publish_now tool). A Library file you uploaded must have finished its content check (see Complete an upload). Returns the new post ids; `awaitingApproval` is true when the workspace reviews posts first.
MCP tool: schedule_post
Parameters
preview"1"QueryOptional`1` runs every check and returns `{ preview }` (what would happen) without changing anything.
Body
accountIdsarray of string (uuid)Required(1–3 items)
captionsobjectRequiredOne caption per platform you post to.
videoIdstring (uuid)OptionalA finished video. Pass this or storagePath.
storagePathstringOptionalA workspace Library MP4, '<workspaceId>/library/<file>.mp4'. Pass this or videoId. (at most 400 characters)
titlestringOptionalUsed as the YouTube, Pinterest and LinkedIn title and in the calendar. (at most 200 characters)
whenstringOptional"next_free_slot" (default), "now", or an ISO 8601 time with offset at least 2 minutes ahead.
sendForReviewbooleanOptionalHold the posts for the owner's approval. Review workspaces always hold API posts.
tiktokobjectOptionalOnly when TikTok direct posting is on (delivery `direct`). Ask the person; never assume.
youtubeobjectOptional
Example request
curl -X POST https://clips.lnr.ae/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"videoId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"accountIds": [
"c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b",
"d7e8f9a0-1b2c-4d3e-8f4a-5b6c7d8e9f0a"
],
"captions": {
"instagram": {
"caption": "Three things nobody tells you about cold brew.",
"hashtags": [
"coldbrew",
"coffee"
]
},
"tiktok": {
"caption": "Cold brew, explained in 15 seconds"
}
},
"when": "2026-11-16T18:00:00+04:00"
}'Example response
HTTP 201{
"data": {
"postIds": [
"3f8f6c1e-2b4a-4c3d-9e5f-1a2b3c4d5e6f",
"8b2d4f6a-1c3e-4a5b-9d7f-0e2a4c6b8d1f"
],
"awaitingApproval": false
},
"error": null
}/api/v1/posts/{id}Get a post
ReadOne post: status, scheduled and published times, its link once live, and why it failed if it did.
MCP tool: get_post
Parameters
idstring (uuid)PathRequiredThe post's id.
Example request
curl https://clips.lnr.ae/api/v1/posts/ID \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"id": "3f8f6c1e-2b4a-4c3d-9e5f-1a2b3c4d5e6f",
"platform": "instagram",
"accountId": "c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b",
"status": "published",
"caption": "Three things nobody tells you about cold brew.",
"hashtags": [
"coldbrew",
"coffee"
],
"scheduledFor": "2026-11-16T14:00:00.000Z",
"publishedAt": "2026-11-16T14:00:41.000Z",
"externalUrl": "https://www.instagram.com/reel/C9xYz12AbCd/",
"failureReason": null,
"videoId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
},
"error": null
}/api/v1/posts/{id}Moves a post that hasn't gone out (`draft`, `ready`, `approved` or `scheduled`) and/or replaces its caption and hashtags; only what you send changes. In a workspace that reviews posts, a caption or hashtag change sends an approved post back to the owner (`ready`); a move doesn't. The video, accounts and title can't change here: cancel and schedule again, or duplicate.
MCP tool: update_post
Parameters
idstring (uuid)PathRequiredThe post's id.
preview"1"QueryOptional`1` runs every check and returns `{ preview }` (what would happen) without changing anything.
Body
whenstring (date-time)OptionalISO 8601 with offset, at least 2 minutes ahead, at most a year out.
captionstringOptional(at most 5000 characters)
hashtagsarray of stringOptional(at most 30 items)
Example request
curl -X PATCH https://clips.lnr.ae/api/v1/posts/ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"when": "2026-11-17T19:30:00+04:00",
"caption": "Cold brew: three things nobody tells you."
}'Example response
HTTP 200{
"data": {
"id": "3f8f6c1e-2b4a-4c3d-9e5f-1a2b3c4d5e6f",
"platform": "instagram",
"accountId": "c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b",
"status": "scheduled",
"caption": "Cold brew: three things nobody tells you.",
"hashtags": [
"coldbrew",
"coffee"
],
"scheduledFor": "2026-11-17T15:30:00.000Z",
"publishedAt": null,
"externalUrl": null,
"failureReason": null,
"videoId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
},
"error": null
}/api/v1/posts/{id}Cancel a post
WriteCancels a post that hasn't gone out (waiting for approval, scheduled, failed, or waiting for the person). A post that is publishing or published can't be cancelled or removed from the platform here; delete it on the platform.
MCP tool: cancel_post
Parameters
idstring (uuid)PathRequiredThe post's id.
preview"1"QueryOptional`1` runs every check and returns `{ preview }` (what would happen) without changing anything.
Example request
curl -X DELETE https://clips.lnr.ae/api/v1/posts/ID \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"id": "3f8f6c1e-2b4a-4c3d-9e5f-1a2b3c4d5e6f",
"platform": "instagram",
"accountId": "c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b",
"status": "cancelled",
"caption": "Three things nobody tells you about cold brew.",
"hashtags": [
"coldbrew",
"coffee"
],
"scheduledFor": "2026-11-16T14:00:00.000Z",
"publishedAt": null,
"externalUrl": null,
"failureReason": null,
"videoId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
},
"error": null
}/api/v1/posts/{id}/retryRetry a failed post
WriteSends a failed post again about 3 minutes later. Refused when its account needs reconnecting, or when the platform refused the post for good (then cancel it and schedule the video again with the change the platform asks for). No body.
MCP tool: retry_post
Parameters
idstring (uuid)PathRequiredThe post's id.
preview"1"QueryOptional`1` runs every check and returns `{ preview }` (what would happen) without changing anything.
Example request
curl -X POST https://clips.lnr.ae/api/v1/posts/ID/retry \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"id": "3f8f6c1e-2b4a-4c3d-9e5f-1a2b3c4d5e6f",
"platform": "instagram",
"accountId": "c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b",
"status": "scheduled",
"caption": "Three things nobody tells you about cold brew.",
"hashtags": [
"coldbrew",
"coffee"
],
"scheduledFor": "2026-11-14T10:03:00.000Z",
"publishedAt": null,
"externalUrl": null,
"failureReason": null,
"videoId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
},
"error": null
}/api/v1/posts/{id}/approveApprove a post
ApproveApproves a post waiting for the owner's review, which schedules it for its time. Needs a key with approve access: only the workspace owner can make one, and it stops approving if its maker is no longer the owner. Refused when the post isn't waiting for approval or its time has passed. No body.
MCP tool: approve_post
Parameters
idstring (uuid)PathRequiredThe post's id.
preview"1"QueryOptional`1` runs every check and returns `{ preview }` (what would happen) without changing anything.
Example request
curl -X POST https://clips.lnr.ae/api/v1/posts/ID/approve \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"id": "3f8f6c1e-2b4a-4c3d-9e5f-1a2b3c4d5e6f",
"status": "scheduled",
"scheduledFor": "2026-11-16T14:00:00.000Z"
},
"error": null
}/api/v1/posts/{id}/duplicateDuplicate a post
WriteSchedules this post's video again, to other accounts or at a new time, with the same rules as Schedule a post. Captions default to the source post's. Each video goes to one account per platform, so a copy to a platform the video is already scheduled or live on is refused.
MCP tool: duplicate_post
Parameters
idstring (uuid)PathRequiredThe post's id.
preview"1"QueryOptional`1` runs every check and returns `{ preview }` (what would happen) without changing anything.
Body
accountIdsarray of string (uuid)Required(1–3 items)
whenstringOptional"next_free_slot" (default), or an ISO 8601 time with offset at least 2 minutes ahead and at most a year out.
captionsobjectOptionalOne caption per platform you post to.
sendForReviewbooleanOptionaltiktokobjectOptionalOnly when TikTok direct posting is on (delivery `direct`). Ask the person; never assume.
youtubeobjectOptional
Example request
curl -X POST https://clips.lnr.ae/api/v1/posts/ID/duplicate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountIds": [
"d7e8f9a0-1b2c-4d3e-8f4a-5b6c7d8e9f0a"
],
"when": "next_free_slot",
"captions": {
"tiktok": {
"caption": "Cold brew, explained"
}
}
}'Example response
HTTP 201{
"data": {
"postIds": [
"8b2d4f6a-1c3e-4a5b-9d7f-0e2a4c6b8d1f"
],
"awaitingApproval": false
},
"error": null
}/api/v1/posts/{id}/metricsGet post metrics
ReadThe numbers collected from the platform about 1, 3 and 7 days after posting. Real platform figures only: an empty list means none collected yet, and null means the platform doesn't report that metric.
MCP tool: get_post_metrics
Parameters
idstring (uuid)PathRequiredThe post's id.
Example request
curl https://clips.lnr.ae/api/v1/posts/ID/metrics \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"post": {
"id": "3f8f6c1e-2b4a-4c3d-9e5f-1a2b3c4d5e6f",
"platform": "instagram",
"accountId": "c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b",
"status": "published",
"caption": "Three things nobody tells you about cold brew.",
"hashtags": [
"coldbrew",
"coffee"
],
"scheduledFor": "2026-11-16T14:00:00.000Z",
"publishedAt": "2026-11-16T14:00:41.000Z",
"externalUrl": "https://www.instagram.com/reel/C9xYz12AbCd/",
"failureReason": null,
"videoId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
},
"snapshots": [
{
"window": "1d",
"capturedAt": "2026-11-17T14:05:00.000Z",
"views": 4210,
"reach": 3880,
"likes": 312,
"comments": 18,
"shares": 25,
"saves": 41,
"avgWatchTimeMs": 9400
}
],
"note": "Numbers come from the platform about 1, 3 and 7 days after posting."
},
"error": null
}/api/v1/calendarGet the calendar
ReadPosts placed on local days `from` to `to` (inclusive, at most 92 days) by scheduled time, or published time when there is none, in the workspace's timezone: the first connected account's, as on the Calendar page, unless you pass one. Cancelled posts are left out; `truncated` is true past 1,000 posts.
MCP tool: get_calendar
Parameters
fromstring (date)QueryRequiredFirst day, YYYY-MM-DD.
tostring (date)QueryRequiredLast day, YYYY-MM-DD.
timezonestringQueryOptionalAn IANA timezone such as Europe/London.
Example request
curl "https://clips.lnr.ae/api/v1/calendar?from=DATE&to=DATE" \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"timezone": "Asia/Dubai",
"from": "2026-11-16",
"to": "2026-11-22",
"posts": [
{
"id": "3f8f6c1e-2b4a-4c3d-9e5f-1a2b3c4d5e6f",
"platform": "instagram",
"accountId": "c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b",
"status": "scheduled",
"caption": "Three things nobody tells you about cold brew.",
"hashtags": [
"coldbrew",
"coffee"
],
"scheduledFor": "2026-11-16T14:00:00.000Z",
"publishedAt": null,
"externalUrl": null,
"failureReason": null,
"videoId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"videoTitle": "Cold brew facts",
"localDate": "2026-11-16",
"localTime": "18:00"
}
],
"truncated": false
},
"error": null
}Brand and characters
How the workspace looks and sounds, and who appears in its videos. Every video, caption and idea follows the brand kit.
/api/v1/brandThe default brand kit (or the one `kitId` names) with its colours, voice style, tone of voice, banned words and a logo link valid for 10 minutes, plus the list of all the workspace's kits.
MCP tool: get_brand_kit
Parameters
kitIdstring (uuid)QueryOptionalOne of the workspace's kits. Omit for the default.
Example request
curl https://clips.lnr.ae/api/v1/brand \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"kit": {
"id": "5c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"name": "Ember Bakery",
"isDefault": true,
"colors": {
"accent": "#ff6b4a",
"background": "#1f1d36",
"text": "#ffffff"
},
"voice": {
"id": "warm-deep",
"label": "Warm and deep"
},
"tone": "Speak like a friendly expert: plain words, short sentences, one idea at a time. Confident, never pushy.",
"bannedWords": [
"cheap",
"best ever"
],
"website": "https://emberbakery.com",
"logoUrl": "https://media.clips.lnr.ae/storage/v1/object/sign/media/…?token=…",
"updatedAt": "2026-11-12T09:41:00.000Z"
},
"kits": [
{
"id": "5c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"name": "Ember Bakery",
"accent": "#ff6b4a",
"isDefault": true
},
{
"id": "6d2e3f4a-5b6c-4d7e-8f9a-0b1c2d3e4f5a",
"name": "Ember Catering",
"accent": "#2bb3a3",
"isDefault": false
}
]
},
"error": null
}/api/v1/brandUpdate the brand kit
WriteChange any of name, colours (each key on its own), voice, tone and banned words; fields you leave out stay. `bannedWords` replaces the list. Edits the default kit unless `kitId` names another. When the workspace has no kit yet, pass a name to create it. Validated exactly as the Brand kit page.
MCP tool: update_brand_kit
Body
kitIdstring (uuid)OptionalnamestringOptional(1–60 characters)
colorsobjectOptionalvoice"warm-deep" | "bright-energetic" | "clear-neutral" | "soft-friendly" | "bold-dramatic"OptionaltonestringOptional(at most 500 characters)
bannedWordsarray of stringOptional(at most 50 items)
Example request
curl -X PATCH https://clips.lnr.ae/api/v1/brand \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"colors": {
"accent": "#ff6b4a"
},
"tone": "Warm, plain and short. Talk to the viewer as '\''you'\''.",
"bannedWords": [
"cheap",
"best ever"
]
}'Example response
HTTP 200{
"data": {
"kit": {
"id": "5c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"name": "Ember Bakery",
"isDefault": true,
"colors": {
"accent": "#ff6b4a",
"background": "#1f1d36",
"text": "#ffffff"
},
"voice": {
"id": "warm-deep",
"label": "Warm and deep"
},
"tone": "Warm, plain and short. Talk to the viewer as 'you'.",
"bannedWords": [
"cheap",
"best ever"
],
"website": "https://emberbakery.com",
"logoUrl": "https://media.clips.lnr.ae/storage/v1/object/sign/media/…?token=…",
"updatedAt": "2026-11-12T09:41:00.000Z"
},
"kits": [
{
"id": "5c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"name": "Ember Bakery",
"accent": "#ff6b4a",
"isDefault": true
},
{
"id": "6d2e3f4a-5b6c-4d7e-8f9a-0b1c2d3e4f5a",
"name": "Ember Catering",
"accent": "#2bb3a3",
"isDefault": false
}
]
},
"error": null
}/api/v1/charactersList characters
ReadThe workspace's own characters (built from the cast) and its Illustrated characters with their poses. Images are links valid for 10 minutes. Name a character in a video brief to cast them.
MCP tool: list_characters
Example request
curl https://clips.lnr.ae/api/v1/characters \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"characters": [
{
"id": "7e3f4a5b-6c7d-4e8f-9a0b-1c2d3e4f5a6b",
"name": "Mia",
"base": "woman",
"look": "flat",
"colors": {
"skin": "#e9b08a",
"hair": "#2c2420",
"outfit": "#ff6b4a",
"outfitAccent": null
},
"accessory": "glasses",
"about": "Head baker. Calm, funny, explains every step.",
"faceUrl": null
}
],
"illustrated": [
{
"id": "8f4a5b6c-7d8e-4f9a-0b1c-2d3e4f5a6b7c",
"name": "Leo",
"description": "A cheerful delivery cyclist in a red cap",
"approved": true,
"referenceUrl": "https://media.clips.lnr.ae/storage/v1/object/sign/media/…?token=…",
"poses": [
{
"name": "Waving",
"url": "https://media.clips.lnr.ae/storage/v1/object/sign/media/…?token=…"
},
{
"name": "Pointing",
"url": "https://media.clips.lnr.ae/storage/v1/object/sign/media/…?token=…"
}
]
}
]
},
"error": null
}/api/v1/charactersCreate a character
WriteAdd one of the workspace's own characters from the cast, up to 24. Free: nothing is drawn by AI. Illustrated characters are made in the app.
MCP tool: create_character
Body
namestringRequiredUnique in the workspace. (1–40 characters)
base"kid" | "girl" | "woman" | "man" | "gran" | "grandpa" | "blob" | "robot" | "cat"RequiredThe cast figure they're built on.
look"flat" | "3d"OptionalFlat cartoon (default) or 3D toon figure.
colorsobjectOptionalColours as #rrggbb; null for the figure's default.
accessory"none" | "glasses" | "sunglasses" | "cap" | "headphones" | "bow" | "crown" | "party-hat"OptionalaboutstringOptionalOne line on who they are; the AI director uses it when writing them into a video. (at most 200 characters)
facePathstringOptionalA picture already in the Library to use as their face. Once set it is their locked reference.
Example request
curl -X POST https://clips.lnr.ae/api/v1/characters \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Mia",
"base": "woman",
"colors": {
"hair": "#2c2420",
"outfit": "#ff6b4a"
},
"accessory": "glasses",
"about": "Head baker. Calm, funny, explains every step."
}'Example response
HTTP 201{
"data": {
"id": "7e3f4a5b-6c7d-4e8f-9a0b-1c2d3e4f5a6b",
"name": "Mia",
"base": "woman",
"look": "flat",
"colors": {
"skin": "#e9b08a",
"hair": "#2c2420",
"outfit": "#ff6b4a",
"outfitAccent": null
},
"accessory": "glasses",
"about": "Head baker. Calm, funny, explains every step.",
"faceUrl": null
},
"error": null
}/api/v1/characters/{id}Update a character
WriteChange any of a character's fields; fields you leave out stay. A face that is already set is a locked reference and can't be swapped for an AI-made one.
MCP tool: update_character
Parameters
idstring (uuid)PathRequiredThe character's id, from List characters.
Body
namestringOptionalUnique in the workspace. (1–40 characters)
base"kid" | "girl" | "woman" | "man" | "gran" | "grandpa" | "blob" | "robot" | "cat"OptionalThe cast figure they're built on.
look"flat" | "3d"OptionalFlat cartoon (default) or 3D toon figure.
colorsobjectOptionalColours as #rrggbb; null for the figure's default.
accessory"none" | "glasses" | "sunglasses" | "cap" | "headphones" | "bow" | "crown" | "party-hat"OptionalaboutstringOptionalOne line on who they are; the AI director uses it when writing them into a video. (at most 200 characters)
facePathstringOptionalA picture already in the Library to use as their face. Once set it is their locked reference.
Example request
curl -X PATCH https://clips.lnr.ae/api/v1/characters/ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"look": "3d",
"about": "Head baker and owner. Calm, funny, explains every step."
}'Example response
HTTP 200{
"data": {
"id": "7e3f4a5b-6c7d-4e8f-9a0b-1c2d3e4f5a6b",
"name": "Mia",
"base": "woman",
"look": "3d",
"colors": {
"skin": "#e9b08a",
"hair": "#2c2420",
"outfit": "#ff6b4a",
"outfitAccent": null
},
"accessory": "glasses",
"about": "Head baker and owner. Calm, funny, explains every step.",
"faceUrl": null
},
"error": null
}/api/v1/characters/{id}Delete a character
WriteRemoves one of the workspace's own characters. Videos already made keep them. This can't be undone.
MCP tool: delete_character
Parameters
idstring (uuid)PathRequiredThe character's id, from List characters.
Example request
curl -X DELETE https://clips.lnr.ae/api/v1/characters/ID \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"id": "7e3f4a5b-6c7d-4e8f-9a0b-1c2d3e4f5a6b"
},
"error": null
}Usage, analytics and notifications
What the workspace has left to spend, how its posts did on each platform, and the notices that need attention.
/api/v1/usageGet usage
ReadThe workspace's plan and what it has used: credits used and left this month with the renewal date (AI videos spend 10, Illustrated 20), pack credits, AI videos made, AI writing calls used today against the daily limit (ideas and captions spend these), and posts this week (Monday to Sunday, UTC) against the weekly goal. Check it before an AI request.
MCP tool: get_usage
Example request
curl https://clips.lnr.ae/api/v1/usage \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"plan": {
"id": "growth",
"name": "Growth"
},
"credits": {
"used": 140,
"limit": 360,
"left": 220,
"bonus": 10,
"trial": false,
"periodStart": "2026-11-01T00:00:00.000Z",
"resetsAt": "2026-12-01T00:00:00.000Z"
},
"packCredits": {
"balance": 100,
"expiresAt": "2027-02-08T00:00:00.000Z"
},
"aiVideos": {
"made": 12,
"canMakeAbout": 32
},
"aiHelp": {
"usedToday": 18,
"dailyLimit": 400,
"resetsAt": "2026-11-15T00:00:00.000Z"
},
"posts": {
"thisWeek": 4,
"weeklyGoal": 7,
"weekStart": "2026-11-09T00:00:00.000Z",
"weekEnd": "2026-11-16T00:00:00.000Z"
}
},
"error": null
}/api/v1/analyticsGet analytics
ReadHow published posts did over the last 7, 30 or 90 days: totals, per platform and per account, the five most viewed posts and the best weekday and hour to post (by median views, once an hour has two measured posts). Every figure is what the platform reported; one a platform doesn't give is null, never 0.
MCP tool: get_analytics
Parameters
days7 | 30 | 90QueryOptionalThe range, counted back from now. (default 30)
Example request
curl https://clips.lnr.ae/api/v1/analytics \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"days": 30,
"from": "2026-10-15T12:00:00.000Z",
"to": "2026-11-14T12:00:00.000Z",
"totals": {
"posts": 18,
"measured": 16,
"figures": {
"views": 48210,
"reach": 39120,
"likes": 2311,
"comments": 184,
"shares": 96,
"saves": 140
}
},
"platforms": [
{
"platform": "instagram",
"posts": 10,
"measured": 9,
"figures": {
"views": 21400,
"reach": 18050,
"likes": 1290,
"comments": 92,
"shares": 61,
"saves": 140
}
},
{
"platform": "linkedin",
"posts": 2,
"measured": 1,
"figures": {
"views": 1240,
"reach": null,
"likes": 41,
"comments": 7,
"shares": null,
"saves": null
}
},
{
"platform": "tiktok",
"posts": 6,
"measured": 6,
"figures": {
"views": 25570,
"reach": 21070,
"likes": 980,
"comments": 85,
"shares": 35,
"saves": null
}
}
],
"accounts": [
{
"id": "c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b",
"platform": "instagram",
"handle": "@emberbakery",
"posts": 10,
"measured": 9,
"figures": {
"views": 21400,
"reach": 18050,
"likes": 1290,
"comments": 92,
"shares": 61,
"saves": 140
}
},
{
"id": "d7e8f9a0-1b2c-4d3e-8f4a-5b6c7d8e9f0a",
"platform": "tiktok",
"handle": "@emberbakery",
"posts": 6,
"measured": 6,
"figures": {
"views": 25570,
"reach": 21070,
"likes": 980,
"comments": 85,
"shares": 35,
"saves": null
}
}
],
"topPosts": [
{
"id": "3f8f6c1e-2b4a-4c3d-9e5f-1a2b3c4d5e6f",
"platform": "tiktok",
"account": "@emberbakery",
"title": "Sourdough in 30 seconds",
"publishedAt": "2026-11-03T17:00:00.000Z",
"url": "https://www.tiktok.com/@emberbakery/video/7312…",
"measuredAt": "2026-11-10T17:05:00.000Z",
"figures": {
"views": 9800,
"reach": 8100,
"likes": 412,
"comments": 31,
"shares": 18,
"saves": null
}
},
{
"id": "8b2d4f6a-1c3e-4a5b-9d7f-0e2a4c6b8d1f",
"platform": "instagram",
"account": "@emberbakery",
"title": "Three proofing mistakes",
"publishedAt": "2026-10-29T18:00:00.000Z",
"url": "https://www.instagram.com/reel/C9…",
"measuredAt": "2026-11-05T18:04:00.000Z",
"figures": {
"views": 6100,
"reach": 5200,
"likes": 380,
"comments": 22,
"shares": 14,
"saves": 51
}
}
],
"bestTimes": {
"timezone": "Asia/Dubai",
"slots": [
{
"weekday": "Tuesday",
"hour": 18,
"medianViews": 4200,
"posts": 3
},
{
"weekday": "Saturday",
"hour": 10,
"medianViews": 3100,
"posts": 2
}
]
}
},
"error": null
}/api/v1/notificationsThis workspace's notices from the bell, newest first, as the key's maker sees them: a video is ready, a post failed or went out, a payment failed. Personal community notifications are never included.
MCP tool: list_notifications
Parameters
limitintegerQueryOptionalHow many to return. (1–100, default 20)
unread"true" | "false"QueryOptional`true` for unread notices only.
Example request
curl https://clips.lnr.ae/api/v1/notifications \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"notifications": [
{
"id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"title": "Your video is ready",
"body": "\"Sourdough in 30 seconds\" is ready to review.",
"link": "https://clips.lnr.ae/app/films",
"read": false,
"createdAt": "2026-11-14T09:12:00.000Z"
},
{
"id": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
"title": "A post didn't go out",
"body": "Instagram needs you to reconnect @emberbakery.",
"link": "https://clips.lnr.ae/app/accounts",
"read": true,
"createdAt": "2026-11-12T18:01:00.000Z"
}
],
"unread": 1
},
"error": null
}/api/v1/notifications/readMarks the notices you list as read, or every unread notice when you send no ids. Returns how many changed.
MCP tool: mark_notifications_read
Body
idsarray of string (uuid)Optional(1–100 items)
Example request
curl -X POST https://clips.lnr.ae/api/v1/notifications/read \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ids": [
"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
]
}'Example response
HTTP 200{
"data": {
"marked": 1
},
"error": null
}Ideas and captions
AI help with what to post and how to word it. Each request spends AI writing calls from the daily allowance, never credits.
/api/v1/ideasList ideas
ReadThis week's five video ideas (title, opening hook, angle and format), if they've been made. Free: it never makes new ones.
MCP tool: list_ideas
Example request
curl https://clips.lnr.ae/api/v1/ideas \
-H "Authorization: Bearer YOUR_API_KEY"Example response
HTTP 200{
"data": {
"week": "2026-11-09",
"ideas": [
{
"title": "Three proofing mistakes",
"hook": "Your dough isn't lazy. You're rushing it.",
"angle": "Side-by-side loaves show what under-proofing does, then the one-finger test that fixes it.",
"format": {
"id": "explainers",
"label": "Explainers and science"
}
},
{
"title": "Behind the 5am bake",
"hook": "This is what a bakery looks like before you're awake.",
"angle": "A fast walk through the first hour of the day, ending on the first tray out of the oven.",
"format": {
"id": "uploads",
"label": "My own videos"
}
}
],
"createdAt": "2026-11-10T08:02:11.000Z"
},
"error": null
}/api/v1/ideasGenerate ideas
WriteMakes five fresh ideas for this week from the workspace's formats, platforms and brand kit, replacing this week's. Costs one AI writing call from the daily allowance, not credits; refused with `plan_limit` when today's allowance is used up. Takes up to a minute.
MCP tool: generate_ideas
Example request
curl -X POST https://clips.lnr.ae/api/v1/ideas \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'Example response
HTTP 201{
"data": {
"week": "2026-11-09",
"ideas": [
{
"title": "Three proofing mistakes",
"hook": "Your dough isn't lazy. You're rushing it.",
"angle": "Side-by-side loaves show what under-proofing does, then the one-finger test that fixes it.",
"format": {
"id": "explainers",
"label": "Explainers and science"
}
},
{
"title": "Behind the 5am bake",
"hook": "This is what a bakery looks like before you're awake.",
"angle": "A fast walk through the first hour of the day, ending on the first tray out of the oven.",
"format": {
"id": "uploads",
"label": "My own videos"
}
}
],
"createdAt": "2026-11-14T12:00:41.000Z"
},
"error": null
}/api/v1/captionsWrite captions
WriteA caption and hashtags for each platform, in the brand's tone, from a topic or one of the workspace's videos. Each platform costs one AI writing call from the daily allowance, not credits; if there aren't enough left for every platform asked for, it's refused with `plan_limit` before anything is spent.
MCP tool: write_captions
Body
topicstringOptionalWhat the post is about. Required unless videoId is given. (at most 200 characters)
descriptionstringOptionalMore to write from. Nothing that isn't here is invented. (at most 1000 characters)
videoIdstring (uuid)OptionalOne of the workspace's videos; its title is used when there's no topic.
platformsarray of "instagram" | "tiktok" | "linkedin"OptionalDefault: all three. (1–3 items)
Example request
curl -X POST https://clips.lnr.ae/api/v1/captions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"videoId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"description": "New winter loaf with roasted chestnuts. In store Friday.",
"platforms": [
"instagram",
"linkedin"
]
}'Example response
HTTP 200{
"data": {
"captions": {
"instagram": {
"caption": "Our winter loaf is back, now with roasted chestnuts.\nIn store from Friday, while the trays last.",
"hashtags": [
"#Sourdough",
"#WinterBaking",
"#DubaiBakery"
],
"full": "Our winter loaf is back, now with roasted chestnuts.\nIn store from Friday, while the trays last.\n\n#Sourdough #WinterBaking #DubaiBakery"
},
"linkedin": {
"caption": "Seasonal products give regulars a reason to come back.\n\nOur winter loaf returns on Friday with roasted chestnuts, and we filmed the first bake to show how it's made.",
"hashtags": [
"#SmallBusiness",
"#Bakery"
],
"full": "Seasonal products give regulars a reason to come back.\n\nOur winter loaf returns on Friday with roasted chestnuts, and we filmed the first bake to show how it's made.\n\n#SmallBusiness #Bakery"
}
},
"notWritten": [],
"aiCallsLeftToday": 380
},
"error": null
}