Generate short-form 2x2 grid videos and slideshow carousels programmatically. Create content briefs, generate images with AI, and render outputs — all via API. Available on PRO and ULTIMATE plans.
Authorization headercurl -X GET https://lowkeyviral.com/api/v1/account \
-H "Authorization: Bearer lkv_sk_your_key_here"
All API requests require a Bearer token in the Authorization header. API keys start with lkv_sk_.
Authorization: Bearer lkv_sk_...
| Plan | Limit |
|---|---|
| PRO | 10 requests / minute |
| ULTIMATE | 30 requests / minute |
| Progress polling (all plans) | 60 requests / minute |
When rate limited you will receive a 429 response with a Retry-After header indicating seconds to wait.
POST /api/v1/briefs (AI-generated) or POST /api/v1/briefs/manual (your own content).POST /api/v1/briefs/:id/generate with your preferred model.POST /api/v1/briefs/:id/render to start Lambda rendering.GET /api/v1/briefs/:id/render/:renderId/progress every 2-3 seconds until status is "done".Tip: With POST /api/v1/briefs/manual you can combine all steps into one call. Give images a description instead of a url to have them AI-generated, and pass render: true to start rendering right away. See the render parameter for details.
POST /api/v1/briefs with type: "slideshow" (AI-generated) or POST /api/v1/briefs/manual with type: "slideshow".POST /api/v1/briefs/:id/generate (auto-detects portrait 9:16).POST /api/v1/briefs/:id/render returns rendered slides immediately (no polling needed).Tip: Same as grid — POST /api/v1/briefs/manual with render: true can do it all in one call. Slideshow renders are synchronous, so the response includes the finished slides array directly.
/api/v1/briefs2 creditsGenerate AI content briefs from a business description.
Returns 5 briefs per request for both grid and slideshow types.
Example
curl -X POST https://lowkeyviral.com/api/v1/briefs \
-H "Authorization: Bearer lkv_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{"prompt": "A travel app for Gen-Z backpackers"}'
Response
{
"briefs": [
{
"id": "clxyz...",
"type": "grid",
"hook": "pov: your euro trip bucket list is about to be god tier",
"title": "find these hidden gems and more on WanderApp 🌍✈️",
"caption_style": null,
"images": [
{ "id": "...", "position": 0, "title": "Hallstatt", "description": "..." },
{ "id": "...", "position": 1, "title": "Kotor", "description": "..." },
{ "id": "...", "position": 2, "title": "Colmar", "description": "..." },
{ "id": "...", "position": 3, "title": "Sintra", "description": "..." }
]
}
]
}
Slideshow Example
curl -X POST https://lowkeyviral.com/api/v1/briefs \
-H "Authorization: Bearer lkv_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{"prompt": "A skincare brand for 20-somethings", "type": "slideshow", "slide_count": 6}'
| Parameter | Type | Required | Description |
|---|---|---|---|
| prompt | string | yes | Business description |
| type | string | no | "grid" (default) or "slideshow" |
| slide_count | integer | no | 4-10, only for slideshow type (default: 6) |
/api/v1/briefs/manual0+ creditsCreate a manual content brief with your own images and text.
Example
curl -X POST https://lowkeyviral.com/api/v1/briefs/manual \
-H "Authorization: Bearer lkv_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"hook": "these coffee shops are insane",
"title": "Best Coffee Shops",
"images": [
{ "url": "https://...", "title": "Cafe A", "description": "Cozy vibes" },
{ "url": "https://...", "title": "Cafe B", "description": "Great latte" },
{ "url": "https://...", "title": "Cafe C", "description": "Hidden gem" },
{ "url": "https://...", "title": "Cafe D", "description": "Rooftop" }
]
}'
| Parameter | Type | Required | Description |
|---|---|---|---|
| hook | string | yes (grid) / no (slideshow) | Text overlay / video text. For slideshows, auto-derived from first slide caption if omitted. |
| title | string | no | Post caption (defaults to hook) |
| type | string | no | "grid" (default) or "slideshow" |
| caption_style | string | no | Slideshow only: "classic_bold", "background_bar", or "neon_glow" |
| images | array | yes | Grid: exactly 4. Slideshow: 2-10. |
| image_model | string | no | AI model for image generation when images have descriptions but no URLs. One of: z_image_turbo, p_image, flux_2_dev. |
| render | boolean | no | Also render after creation. See render parameter below. |
| design | string | no | Grid + render: true only. One of: "default", "withCaptions", "noSpaces" |
| soundtrack | string | no | Grid + render: true only. See soundtrack list below. |
The render parameter
When render: true, the endpoint triggers rendering after the brief is created (and after image generation, if any images needed to be generated). This is the same as calling POST /api/v1/briefs/:id/render yourself, just bundled into the same request.
For grid briefs: Starts an async Lambda video render. The response includes a render_id — poll GET /api/v1/briefs/:id/render/:renderId/progress every 2-3 seconds until status is "done".
For slideshow briefs: Renders slides synchronously with text overlays. The response includes a slides array with the finished URLs. No polling needed.
Credit cost: +1 render credit on top of whatever else the call costs (image generation, etc.). Image generation credits are only charged for images that need generation (description present, url missing).
render is independent of image generation. You can pass your own image URLs and still use render: true — it will skip image generation and go straight to rendering. Or you can omit render and just have images generated without rendering.
Response
{
"id": "clxyz...",
"hook": "these coffee shops are insane",
"title": "Best Coffee Shops",
"images": [
{ "id": "...", "position": 0, "title": "Cafe A", "description": "Cozy vibes", "url": "https://...", "rendered_url": null }
]
}
When render: true for a grid, the response includes a render_id for polling:
{
"id": "clxyz...",
"hook": "...",
"title": "...",
"images": [...],
"render_id": "abc123"
}
When render: true for a slideshow, the response includes a slides array immediately:
{
"id": "clxyz...",
"hook": "...",
"title": "...",
"images": [...],
"slides": [
{ "index": 0, "url": "https://generated.lowkeyviral.com/slideshows/briefId/slide-0.jpg" },
{ "index": 1, "url": "https://generated.lowkeyviral.com/slideshows/briefId/slide-1.jpg" }
]
}
/api/v1/briefs0 creditsList all your content briefs.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
| type | string | Filter by type: "grid" or "slideshow". Omit for all. |
| limit | integer | Max results (default 20, max 100) |
| cursor | string | Pagination cursor |
Invalid type or limit values return 422 validation_error.
Example
curl https://lowkeyviral.com/api/v1/briefs \
-H "Authorization: Bearer lkv_sk_your_key_here"
Response
{
"data": [
{
"id": "...",
"hook": "...",
"title": "...",
"is_generated": true,
"video_url": null,
"images": [...]
}
],
"has_more": false,
"next_cursor": null
}
/api/v1/briefs/:id0 creditsGet a single content brief by ID.
Example
curl https://lowkeyviral.com/api/v1/briefs/BRIEF_ID \
-H "Authorization: Bearer lkv_sk_your_key_here"
Response
{
"id": "clxyz...",
"type": "slideshow",
"hook": "...",
"title": "...",
"is_generated": true,
"video_url": null,
"caption_style": "classic_bold",
"created_at": "2026-02-12T00:00:00Z",
"images": [
{ "id": "...", "position": 0, "title": "...", "description": "...", "url": "https://...", "rendered_url": "https://generated.lowkeyviral.com/slideshows/.../slide-0.jpg" }
]
}
For slideshow briefs, rendered_url on each image contains the rendered slide with text overlay applied. This field is null until the slideshow is rendered.
/api/v1/briefs/:id0 creditsDelete a content brief and its associated images.
Example
curl -X DELETE https://lowkeyviral.com/api/v1/briefs/BRIEF_ID \
-H "Authorization: Bearer lkv_sk_your_key_here"
Response
{ "success": true }
/api/v1/briefs/:id/generate4-8+ creditsGenerate images for a brief. Pass render: true to also start rendering once images are ready (same behavior as the render parameter on /briefs/manual).
Credits depend on model: z_image_turbo = 4, p_image = 8, flux_2_dev = 8. Add +1 credit if render is true.
For slideshow briefs, images are generated in portrait (9:16) orientation automatically. Credit cost scales with slide count: z_image_turbo = 1 credit/image, p_image = 2 credits/image, flux_2_dev = 2 credits/image.
| Parameter | Type | Required | Description |
|---|---|---|---|
| image_model | string | no | One of: z_image_turbo, p_image, flux_2_dev. Defaults to your preferred model. |
| render | boolean | no | Also render after generation. Grid returns render_id; slideshow returns slides. |
| design | string | no | Grid + render: true only. "default", "withCaptions", "noSpaces" |
| soundtrack | string | no | Grid + render: true only. See soundtrack list below |
Example
curl -X POST https://lowkeyviral.com/api/v1/briefs/BRIEF_ID/generate \
-H "Authorization: Bearer lkv_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"image_model": "z_image_turbo",
"render": true,
"design": "default",
"soundtrack": "City Sunshine"
}'
Response
{
"id": "clxyz...",
"hook": "...",
"title": "...",
"is_generated": true,
"video_url": null,
"created_at": "...",
"images": [...],
"render_id": "abc123"
}
When render: true for a slideshow, the response includes rendered slides immediately:
{
"id": "clxyz...",
"hook": "...",
"title": "...",
"is_generated": true,
"images": [...],
"slides": [
{ "index": 0, "url": "https://generated.lowkeyviral.com/slideshows/briefId/slide-0.jpg" },
{ "index": 1, "url": "https://generated.lowkeyviral.com/slideshows/briefId/slide-1.jpg" }
]
}
/api/v1/briefs/:id/render1 creditStart rendering. For grid briefs, returns a renderId for polling. For slideshow briefs, returns rendered slides immediately.
Grid Example
curl -X POST https://lowkeyviral.com/api/v1/briefs/BRIEF_ID/render \
-H "Authorization: Bearer lkv_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{"design": "default", "soundtrack": "City Sunshine"}'
Grid Response
{ "render_id": "abc123" }
Slideshow Example
curl -X POST https://lowkeyviral.com/api/v1/briefs/BRIEF_ID/render \
-H "Authorization: Bearer lkv_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{"caption_style": "classic_bold"}'
Slideshow Response
{
"slides": [
{ "index": 0, "url": "https://generated.lowkeyviral.com/slideshows/briefId/slide-0.jpg" },
{ "index": 1, "url": "https://generated.lowkeyviral.com/slideshows/briefId/slide-1.jpg" }
]
}
| Parameter | Type | Applies to | Description |
|---|---|---|---|
| design | string | Grid only | "default", "withCaptions", "noSpaces" |
| soundtrack | string | Grid only | See soundtrack list below |
| caption_style | string | Slideshow only | "classic_bold", "background_bar", "neon_glow" |
/api/v1/briefs/:id/render/:renderId/progress0 creditsPoll render progress. Call every 2-3 seconds.
Note: This endpoint is for grid briefs only. Slideshow renders are synchronous and return immediately from the render endpoint. Calling this on a slideshow brief returns 422.
Type values: "progress", "done", "error". Poll every 2-3 seconds.
Example
curl https://lowkeyviral.com/api/v1/briefs/BRIEF_ID/render/RENDER_ID/progress \
-H "Authorization: Bearer lkv_sk_your_key_here"
Responses
In progress:
{
"type": "progress",
"progress": 0.45,
"started_at": "2026-02-12T00:00:00.000Z",
"elapsed_seconds": 32,
"stalled": false
}
stalled is true when progress has not changed for an extended period, typically during Lambda cold starts. The server will automatically return type: "error" if the render times out.
Completed:
{
"type": "done",
"url": "https://s3.us-east-1.amazonaws.com/.../out.mp4",
"size": 1234567
}
Error:
{
"type": "error",
"message": "Render timed out. The Lambda function did not complete in time."
}
/api/v1/uploads0 creditsGet a presigned URL to upload a custom image.
PUT your image file to the upload_url with the matching Content-Type header. Max 10 MB.
Supported content_type values: image/jpeg, image/png, image/webp.
Example
curl -X POST https://lowkeyviral.com/api/v1/uploads \
-H "Authorization: Bearer lkv_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{"content_type": "image/jpeg"}'
Response
{
"upload_url": "https://...",
"file_url": "https://generated.lowkeyviral.com/...",
"content_type": "image/jpeg",
"max_size": 10485760
}
/api/v1/account0 creditsGet your account info including credits and plan type.
Example
curl https://lowkeyviral.com/api/v1/account \
-H "Authorization: Bearer lkv_sk_your_key_here"
Response
{
"credits": 42,
"plan_type": "PRO",
"next_reset_date": "2026-03-01T00:00:00Z"
}
| Field | Description |
|---|---|
type | Brief type: "grid" or "slideshow" |
hook | Short text rendered in the video (grid) or derived from first slide caption (slideshow). Max 80 chars. |
title | Post caption for socials (not shown in video/slides) |
caption_style | Slideshow only: text overlay style ("classic_bold", "background_bar", "neon_glow") |
images[].title | Per-image caption label |
images[].description | Image generation prompt (not shown in output) |
images[].rendered_url | Slideshow only: rendered slide URL with text overlay applied (null until rendered) |
default, withCaptions, noSpaces
| Model | Credits | Notes |
|---|---|---|
| z_image_turbo | 1 credit/image | Fastest, good quality |
| p_image | 2 credits/image | High quality |
| flux_2_dev | 2 credits/image | High quality, detailed |
Total image-generation cost = per-image cost × number of images/slides.
| Style | Description |
|---|---|
| classic_bold | White text with black outline stroke |
| background_bar | White text on semi-transparent dark background |
| neon_glow | Bright green (#00ff88) text with glow effect |
Advertime, And Just Like That, Blippy Trance, Brewing Potions, City Sunshine, Funshine, Happy Whistling Ukulele, I Guess What I'm Trying to Say, La Citadelle, Lukewarm Banjo, Magical Transition, Martini Sunset, Meditating Beat, Night in Venice, River Meditation, Soundtrack From the Starcourt Mall, Strength of the Titans, Study and Relax, Sun Up Gunned Down, The Celebrated Minuet
| Operation | Endpoint | Grid | Slideshow |
|---|---|---|---|
| Generate AI briefs | POST /api/v1/briefs | 2 (5 briefs) | 2 (5 briefs) |
| Create manual brief | POST /api/v1/briefs/manual | 0 | 0 |
| Generate images (z_image_turbo) | POST /api/v1/briefs/:id/generate | 4 (4 x 1) | 1 per image |
| Generate images (p_image) | POST /api/v1/briefs/:id/generate | 8 (4 x 2) | 2 per image |
| Generate images (flux_2_dev) | POST /api/v1/briefs/:id/generate | 8 (4 x 2) | 2 per image |
| Render | POST /api/v1/briefs/:id/render | 1 | 1 |
| All other endpoints | GET / DELETE | 0 | 0 |
All errors return a consistent format:
{
"error": {
"code": "error_code",
"message": "Human-readable description"
}
}
| HTTP Status | Code | Description |
|---|---|---|
| 401 | unauthorized | Invalid or missing API key |
| 403 | forbidden | API keys require a PRO or ULTIMATE plan |
| 402 | insufficient_credits | Not enough credits for this operation |
| 422 | validation_error | Invalid request body or parameters |
| 404 | not_found | Resource not found |
| 429 | rate_limited | Too many requests |
| 500 | internal_error | Unexpected server error |
Need help? Contact support or check our FAQ.