Errors. A key that is malformed, unknown, revoked, expired, or whose account is no longer on Pro is refused with 401 and {"error":"invalid or revoked API key"}. Each key is limited to 60 requests per minute.
Keep keys secret: use them only from your server or automation tool, never in browser or mobile app code. Revoke a key from the API keys card at any time.
Endpoints
All endpoints live under the API base URL https://reelguud-backend.guud.ai and require Authorization: Bearer rg_live_…. Responses are JSON. The typical flow is: upload media, wait for it to be tagged, then generate a reel.
Uploads one or more images or video clips to your library. Each file becomes an asset with processing_status: "uploading". ReelGuud then tags it with AI and moves it to ready; only ready assets are used to generate reels.
Auth
Authorization: Bearer rg_live_… (Pro plan).
Request body
Send multipart/form-data. Any field name works, and you can include several files in one request.
Field
Type
Description
file
file, required
An image (image/*) or video (video/*). Repeat for more files. Each file can be up to 200 MB.
Each item is the full asset record (abridged above). Video assets also get a poster frame in thumbnail_url.
Errors
Status
Meaning
400
No files were sent, or a file isn’t an image or video.
401
The API key is missing, invalid or revoked.
402
Your plan’s asset limit is reached: {"error", "limit", "used", "upgrade_tier"}.
413
A file is over 200 MB.
429
Rate limited. Wait retry_after_s seconds and try again.
POST/api/reels
Queues a reel. ReelGuud picks matching clips from your ready assets and renders an MP4. The reel starts as status: "pending" and moves to processing, then ready (with an output_url) or failed. You need at least 10 ready assets.
Auth
Authorization: Bearer rg_live_… (Pro plan).
Request body
Send application/json. You need title and theme, unless you send batch_count or a template_id that supplies them.
Field
Type
Description
title
string, required*
Name of the reel.
theme
string, required*
What the reel is about, for example "summer road trip". Used to choose matching clips.
preset
string
Target platform format: reels (default), tiktok or shorts.
keywords
string[]
Extra keywords to help pick clips.
source_asset_ids
number[]
Specific asset_ids to build the reel from.
batch_count
integer 1–7
Generate several reels at once on AI-suggested themes from your library. When set, title and theme are not needed.
template_id
integer
A saved template you own or share through your workspace. Fills in any field you leave out.
music_enabled
boolean
Add matching background music. Default true.
overlay_script
string
Timed captions, one per line as text:seconds.
overlay_font
string
Caption font style name.
overlay_animation
string
Caption animation, or none.
effect_ids
string[]
Video effects to apply.
An invalid preset, overlay_font, overlay_animation or effect_ids value returns 400 with the list of allowed values.
The response is the reel record (abridged above). With batch_count the response is {"batch_count": 3, "jobs": [ … ]}, one record per reel. To be notified when a reel is ready, use the reel.ready webhook.
Errors
Status
Meaning
400
A required field is missing or a value is invalid.
401
The API key is missing, invalid or revoked.
402
Your plan’s monthly reel limit is reached: {"error", "limit", "used", "upgrade_tier"}.
403 / 404
The template_id isn’t yours, or doesn’t exist.
422
Fewer than 10 ready assets: {"error": "Insufficient library", "ready_count": 4}.
429
Rate limited. Wait retry_after_s seconds and try again.
GET/api/reels
Lists your reels, newest first, one page at a time.
Auth
Authorization: Bearer rg_live_… (Pro plan).
Query parameters
Parameter
Type
Description
status
string
Only return reels in this state: pending, processing, ready or failed.
page
integer
Page number, starting at 1 (default).
limit
integer 1–100
Reels per page. Default 20; values over 100 are capped.
Each item is the full reel record (abridged above) plus view_count, download_count and posted. total counts all your reels, whatever the status filter; keep requesting the next page until items is empty.
Errors
Status
Meaning
401
The API key is missing, invalid or revoked.
429
Rate limited. Wait retry_after_s seconds and try again.
GET/api/reels/{id}
Gets one reel by its reel_job_id. Poll this to follow a reel from pending to ready — or skip polling and use the reel.ready webhook.
Auth
Authorization: Bearer rg_live_… (Pro plan). You can only read your own reels.
Path parameters
Parameter
Type
Description
id
integer, required
The reel’s reel_job_id, as returned by POST /api/reels.
HTTP/1.1 200 OK
Content-Type: video/mp4
Content-Disposition: attachment; filename="Summer-road-trip.mp4"
<MP4 bytes>
Errors
Errors are JSON: {"error": "…"}.
Status
Meaning
400
The id isn’t a number.
401
The API key is missing, invalid or revoked.
403
The reel belongs to another account.
404
No reel with this id, or no such variant.
409
The reel isn’t ready yet.
410
The file is no longer available.
429
Rate limited. Wait retry_after_s seconds and try again.
Webhooks
Instead of polling, ReelGuud can call your server when a reel finishes. Set an https:// URL in the Webhook card on Account. Saving the URL shows a signing secret that starts with whsec_; keep it on your server. Saving again creates a new secret, and the old one stops working.
reel.ready
Sent once when a reel you generated changes to status: "ready". ReelGuud sends a POST to your URL with a JSON body:
The reel’s title, or its theme if it has no title.
output_url
string
URL of the finished MP4.
thumbnail_url
string
Poster image URL, or "" if there isn’t one.
Request headers
POST /your/webhook/path HTTP/1.1
Content-Type: application/json
User-Agent: ReelGuud-Webhooks/1
X-ReelGuud-Signature: 5d41402abc4b2a76b9719d911017c592a0f6b3e1c4d7e8f9a0b1c2d3e4f5a6b7
Delivery and retries
Reply with any 2xx status within 10 seconds to accept the event.
Any other status, a timeout or a network error counts as failed. ReelGuud tries up to 3 times in total, waiting a little longer before each retry.
Redirects are not followed. A 3xx counts as failed, so use your final URL.
Retries send the same body and the same signature. The same event can arrive more than once, so ignore an id you have already handled.
Verifying the signature
Every request includes an X-ReelGuud-Signature header. Check it before you trust the body; it proves the request came from ReelGuud and wasn’t changed.
Header: read X-ReelGuud-Signature. It is a 64-character lowercase hex string.
Signed payload: the raw request body, byte for byte as you received it. Don’t parse the JSON and serialize it again first: changes to key order or spacing change the digest. No timestamp or other prefix is added.
Digest: compute HMAC-SHA256 of that raw body, keyed with your full webhook secret (including the whsec_ prefix, as UTF-8), and hex-encode it.
Compare: compare your hex digest with the header value using a constant-time comparison. If they don’t match, reply 401 and ignore the request.
Node.js (Express)
const crypto = require('crypto');
const express = require('express');
const app = express();
const SECRET = process.env.REELGUUD_WEBHOOK_SECRET; // whsec_…
// express.raw keeps the exact bytes that were signed.
app.post('/webhooks/reelguud', express.raw({ type: 'application/json' }), (req, res) => {
const received = req.get('X-ReelGuud-Signature') || '';
const expected = crypto.createHmac('sha256', SECRET).update(req.body).digest('hex');
const ok = received.length === expected.length
&& crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
if (!ok) return res.status(401).send('bad signature');
const event = JSON.parse(req.body.toString('utf8'));
if (event.event === 'reel.ready') {
console.log(`Reel ${event.id} is ready: ${event.output_url}`);
}
res.sendStatus(200);
});