# StrataKit API Reference > Video generation API: JSON → MP4/WebM/GIF Base URL: `https://stratakit.io/api/v1` Auth: `Authorization: Bearer sk_live_xxxxx` ## Quick Reference ``` POST /productions Create video (returns id, poll for status) GET /productions/{id} Get status (pending→processing→completed|failed|cancelled) GET /productions List all (paginated) DELETE /productions/{id} Delete production POST /blueprints Create template GET /blueprints List templates POST /blueprints/{id}/fork Copy template POST /media/upload-url Get presigned upload URL GET /health Health check (no auth required) ``` ## Minimal Working Example ```bash curl -X POST https://stratakit.io/api/v1/productions \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "canvas": { "preset": "youtube_short", "segments": [ { "type": "color", "color": "#4F46E5", "duration": 5 } ] } }' ``` Response (202): `{"id": "uuid", "status": "pending", "credits_used": 5, ...}` Poll `GET /productions/{id}` until `status: "completed"`, then use `output_url`. ## Presigned URL semantics (gotcha: GET-only) `output_url`, `thumbnail_url`, `hls_url`, and `proxy_video_url` are presigned R2 URLs (AWS SigV4) **signed for the GET method only**. Consequences: - `HEAD ` returns **`403 Forbidden`** even with a valid signature. This is correct R2/S3 behavior, not a StrataKit bug — SigV4 binds the signature to the HTTP method. - To probe headers (content-type, existence, total size) without downloading the whole asset, use a ranged GET: `Range: bytes=0-0`. The response is 1 byte (HTTP 206); `Content-Length` reports the **range size** (e.g. `1`), not the full object size — read `Content-Range` (e.g. `bytes 0-0/123456`) for the total. - URLs expire 1 hour after issue. `url_expires_at` is authoritative; re-fetch `GET /productions/{id}` to mint a fresh URL. ```bash # WRONG: returns 403, signature does not authorize HEAD curl -I "$OUTPUT_URL" # RIGHT: cheap header probe with a GET-signed URL curl -sS -r 0-0 -o /dev/null -D - "$OUTPUT_URL" ``` ## Sample Media URLs (Use Directly - No Setup) ``` VIDEO_VERTICAL="https://assets.stratakit.io/samples/video/8366020-hd_1080_1920_25fps.mp4" VIDEO_VERTICAL_30="https://assets.stratakit.io/samples/video/8438335-hd_1080_1920_30fps.mp4" VIDEO_LANDSCAPE_4K="https://assets.stratakit.io/samples/video/12221134_3840_2160_24fps.mp4" VIDEO_LANDSCAPE_4K_60="https://assets.stratakit.io/samples/video/13785842_3840_2160_60fps.mp4" IMAGE_LANDSCAPE="https://assets.stratakit.io/samples/image/sample-landscape-720p.jpg" IMAGE_VERTICAL="https://assets.stratakit.io/samples/image/sample-vertical-9x16.jpg" IMAGE_SQUARE="https://assets.stratakit.io/samples/image/sample-square-1x1.jpg" AUDIO="https://assets.stratakit.io/samples/audio/Waltz%20in%20B%20minor%2C%20Op.%2069%20no.%202.mp3" ``` ## TypeScript Types ```typescript // === REQUEST === interface CreateProductionRequest { canvas?: Canvas; // Direct canvas definition templateId?: string; // OR use a blueprint template bindings?: Record; // Variables for template webhookUrl?: string; // Callback URL when complete name?: string; // Optional name for the production testMode?: boolean; // Watermarked, no credits charged } interface Canvas { // Resolution - use ONE of: preset, OR width+height, OR aspectRatio preset?: ResolutionPreset; // e.g., "youtube_short" (1080x1920) width?: number; // Custom width in pixels (100-7680) height?: number; // Custom height in pixels (100-4320) aspectRatio?: "16:9" | "9:16" | "1:1" | "4:3" | "4:5" | "21:9"; // Content segments: FlatSegment[]; // Flat segment list — base content auto-sequences, overlays render on top // Global settings (all optional) fps?: number; // 1-120, default: 30 duration?: number; // 0.1-7200 seconds, auto-calculated if omitted backgroundColor?: string | Gradient; // Hex or gradient, default: "#000000" masterVolume?: number; // 0-2, default: 1 // Captions (optional, auto-added when TTS segment present) captions?: { source: "tts" | "transcribe" | "inline" | "url"; trackId?: string; // Auto-set to "tts" when using segments format settings?: CaptionSettings; }; // Audio (optional) backgroundAudio?: BackgroundAudio; // Output (optional) outputSettings?: OutputSettings; // Metadata (optional) metadata?: Record; // Custom data for your application } // Flat segment: asset + segment fields merged at top level. // Visual types (video, image, color, text, shape, luma, html, waveform, caption) → single video track. // TTS/audio each get their own audio track automatically. // `start` is auto-calculated for sequential visual segments when omitted. interface FlatSegment { type: Asset["type"]; // REQUIRED: asset type discriminator // Asset fields (vary by type - use any field from the matching asset interface) url?: string; // For video, image, audio text?: string; // For text, tts color?: string; // For color voice?: string; // For tts: Kokoro ID (e.g., "af_bella") for Standard, or name (e.g., "Rachel") for Premium provider?: "elevenlabs" | "kokoro"; // For tts (auto-detected from voice name) fit?: "cover" | "contain" | "fill" | "none"; // For video, image trim?: { start?: number; end?: number }; // For video, audio speed?: number; // For video, audio, tts mute?: boolean; // For video reverse?: boolean; // For video chromaKey?: object; // For video kenBurns?: object; // For image shape?: Shape; // For shape html?: string; // For html css?: string; // For html // ... any other asset-specific fields // Segment fields (all optional) id?: string; // Segment identifier duration?: number; // Segment duration in seconds start?: number; // Start time (auto-calculated for visual segments when omitted) volume?: number; // Audio volume 0-1 loop?: boolean; // Loop segment fadeIn?: number; // Audio fade in seconds fadeOut?: number; // Audio fade out seconds // Positioning (optional) position?: Position; transform?: Transform; crop?: Crop; // Transitions (optional) transition?: Transition; // Applies to both in and out transitionIn?: Transition; transitionOut?: Transition; // Animations (optional) animationIn?: AnimationType; animationOut?: AnimationType; animation?: AnimationType | Keyframe[]; // Effects (optional) effectChain?: { // Visual effects combination?: string; // Preset: "cinematic", "viral", "noir", etc. effects?: Effect[]; // Individual effects array }; blendMode?: BlendMode; mask?: object; zIndex?: number; // Stack order } interface BackgroundAudio { url: string; // REQUIRED: audio file URL volume?: number; // 0-2, default: 1 fadeIn?: number; // Fade in duration in seconds fadeOut?: number; // Fade out duration in seconds loop?: boolean; // Loop to fill duration, default: true trim?: { start?: number; end?: number }; } // Track interface is internal — use segments format for all API requests interface Segment { asset: Asset; // REQUIRED: content definition start: number; // REQUIRED: start time in seconds duration?: number; // Auto-calculated for video/audio if omitted // Identification (optional) id?: string; zIndex?: number; // Stack order within track // Positioning (optional) position?: Position; transform?: Transform; crop?: Crop; // Animation (optional) animationIn?: AnimationType; animationOut?: AnimationType; animation?: AnimationType | Keyframe[]; // Complex animation with keyframes // Transitions (optional) transitionIn?: Transition; transitionOut?: Transition; transition?: Transition; // Applies to both in and out // Effects (optional) effectChain?: { // Visual effects combination?: string; // Preset: "cinematic", "viral", "noir", etc. effects?: Effect[]; // Individual effects }; blendMode?: BlendMode; } interface Position { x?: number | string; // Pixels or percentage string, e.g., "50%" y?: number | string; // Pixels or percentage string anchor?: "top-left" | "top-center" | "top-right" | "center-left" | "center" | "center-right" | "bottom-left" | "bottom-center" | "bottom-right"; } interface Transform { scale?: number | { x?: number; y?: number }; rotation?: number; // Degrees skew?: { x?: number; y?: number }; opacity?: number; // 0-1 } interface Crop { x?: number; y?: number; width?: number; height?: number; } interface Transition { type: TransitionType; // REQUIRED duration?: number; // 0-10 seconds, default: 0.5 easing?: Easing; lumaUrl?: string; // For lumaMatte transition type inverted?: boolean; } interface Effect { type: string; // REQUIRED: effect type (see EFFECTS REFERENCE below) preset?: "subtle" | "medium" | "strong" | "extreme"; intensity?: number; // 0-2 value?: number; // Effect-specific value // Additional properties vary by effect type } interface Keyframe { time: number; // REQUIRED: time in seconds value: number | string | object; // REQUIRED: property value at this time easing?: Easing; } type BlendMode = "normal" | "multiply" | "screen" | "overlay" | "darken" | "lighten" | "color-dodge" | "color-burn" | "hard-light" | "soft-light" | "difference" | "exclusion"; type Easing = "linear" | "ease" | "ease-in" | "ease-out" | "ease-in-out" | "easeInQuad" | "easeOutQuad" | "easeInOutQuad" | "easeInCubic" | "easeOutCubic" | "easeInOutCubic" | "easeInBounce" | "easeOutBounce" | "easeInElastic" | "easeOutElastic"; // === ASSETS (11 types) === type Asset = | VideoAsset | ImageAsset | ColorAsset | TextAsset | AudioAsset | TTSAsset | ShapeAsset | LumaAsset | HTMLAsset | CaptionAsset | WaveformAsset; // NOTE: For assets that support templates, provide EITHER url/text OR binding, not both. // - url/text: Direct value for immediate use // - binding: Template variable name (e.g., "product_video") that gets substituted when using blueprints interface VideoAsset { type: "video"; // REQUIRED url?: string; // Public URL (required if no binding) binding?: string; // Template variable (required if no url) volume?: number; // 0-1, default: 1 trim?: { start?: number; end?: number }; fit?: "cover" | "contain" | "fill" | "none"; // default: "cover" speed?: number; // 0.25-4.0, default: 1 loop?: boolean; // default: false mute?: boolean; // default: false reverse?: boolean; // default: false chromaKey?: { color: string; similarity?: number; blend?: number }; } interface ImageAsset { type: "image"; // REQUIRED url?: string; // Public URL (required if no binding) binding?: string; // Template variable (required if no url) fit?: "cover" | "contain" | "fill" | "none"; // default: "cover" kenBurns?: { startScale: number; endScale: number; startPosition?: Position; endPosition?: Position }; } interface ColorAsset { type: "color"; // REQUIRED color: string | Gradient; // REQUIRED: "#RRGGBB", "#RRGGBBAA", or Gradient object } interface Gradient { type: "linear" | "radial"; // REQUIRED colors: Array<{ color: string; position?: number }>; // REQUIRED: at least 2 color stops angle?: number; // For linear: degrees, default: 0 centerX?: number; // For radial: 0-1, default: 0.5 centerY?: number; // For radial: 0-1, default: 0.5 } interface TextAsset { type: "text"; // REQUIRED text?: string; // Text content (required if no binding) binding?: string; // Template variable (required if no text) fontSize?: number; // default: 48 fontColor?: string; // default: "#ffffff" fontFamily?: string; // default: "Inter" fontWeight?: "normal" | "bold" | "100" | "200" | "300" | "400" | "500" | "600" | "700" | "800" | "900"; fontStyle?: "normal" | "italic"; textAlign?: "left" | "center" | "right" | "justify"; verticalAlign?: "top" | "middle" | "bottom"; backgroundColor?: string; backgroundPadding?: number; backgroundRadius?: number; padding?: number; maxWidth?: number; maxHeight?: number; lineHeight?: number; letterSpacing?: number; shadow?: { color?: string; blur?: number; offsetX?: number; offsetY?: number }; stroke?: { color?: string; width?: number }; } interface AudioAsset { type: "audio"; // REQUIRED url?: string; // Public URL (required if no binding) binding?: string; // Template variable (required if no url) volume?: number; // 0-1, default: 1 fadeIn?: number; // Fade in duration in seconds fadeOut?: number; // Fade out duration in seconds speed?: number; // 0.5-2.0, default: 1 pitch?: number; // Pitch adjustment pan?: number; // -1 (left) to 1 (right), default: 0 trim?: { start?: number; end?: number }; loop?: boolean; // default: false normalize?: boolean; // Normalize audio levels ducking?: { enabled?: boolean; threshold?: number; reduction?: number }; } // TTS has two tiers. Voice name determines routing automatically: // - Standard (Kokoro): IDs like "af_bella", "am_adam", "bf_emma" -> 3 cr/1K chars, 46 voices, 9 languages // - Premium (ElevenLabs): Names like "Sarah", "Rachel", "Liam" -> 13 cr/1K chars, 52 voices, 29+ languages interface TTSAsset { type: "tts"; // REQUIRED text?: string; // Text to speak (required if no binding) binding?: string; // Template variable (required if no text) provider?: "elevenlabs" | "kokoro"; // Auto-detected from voice name; optional explicit override voice?: string; // Kokoro ID (e.g., "af_bella") -> Standard, ElevenLabs name (e.g., "Sarah") -> Premium language?: string; // Language code, e.g., "en-US" speed?: number; // Kokoro: 0.5-2.0, ElevenLabs: 0.7-1.2. Default 1.0 pitch?: number; // -20 to 20 volume?: number; // 0-1, default: 1 // ElevenLabs Premium only: stability?: number; // 0-1, default 0.5 similarity_boost?: number; // 0-1, default 0.75 style?: number; // 0-1, default 0 ssml?: string; // SSML markup for advanced control } interface ShapeAsset { type: "shape"; // REQUIRED shape: Shape; // REQUIRED: shape definition } interface Shape { type: "rectangle" | "roundedRectangle" | "circle" | "ellipse" | "triangle" | "polygon" | "star" | "line" | "arrow" | "custom"; // REQUIRED width?: number; height?: number; radius?: number; // For circle cornerRadius?: number | { topLeft?: number; topRight?: number; bottomLeft?: number; bottomRight?: number }; points?: number; // For polygon/star innerRadius?: number; // For star path?: string; // SVG path for custom shape fill?: string | Gradient; stroke?: { color?: string; width?: number; dashArray?: number[] }; shadow?: { color?: string; blur?: number; offsetX?: number; offsetY?: number }; opacity?: number; // 0-1 } interface LumaAsset { type: "luma"; // REQUIRED url: string; // REQUIRED: URL to grayscale luma matte inverted?: boolean; // Invert the matte, default: false } interface HTMLAsset { type: "html"; // REQUIRED html: string; // REQUIRED: HTML content width: number; // REQUIRED: render width in pixels height: number; // REQUIRED: render height in pixels css?: string; // Optional CSS styles } interface CaptionAsset { type: "caption"; // REQUIRED source?: "tts" | "transcribe" | "inline" | "url"; // default: "tts" if trackId provided trackId?: string; // For tts/transcribe: which audio track to use url?: string; // For url source: SRT/VTT file URL captions?: Array<{ // For inline source start: number; end: number; text: string; words?: Array<{ word: string; start: number; end: number }>; }>; style?: CaptionStyle; // default: "default" position?: "top" | "center" | "bottom"; // default: "bottom" maxWordsPerLine?: number; // 1-20 maxCharsPerLine?: number; // 10-100 highlightColor?: string; // Color for active word highlighting animation?: AnimationType; } interface WaveformAsset { type: "waveform"; // REQUIRED trackId: string; // REQUIRED: audio track ID to visualize style?: "bars" | "line" | "wave" | "points" | "mirror" | "circular"; // default: "bars" preset?: "compact" | "medium" | "prominent" | "full_width"; // default: "prominent" color?: string | Gradient; // default: "#FFFFFF" opacity?: number; // 0-1, default: 0.85 barWidth?: number; // pixels barGap?: number; // pixels smoothing?: number; height?: number; // pixels } // === TYPES === type ResolutionPreset = // Vertical 9:16 (1080x1920) | "youtube_short" | "instagram_reel" | "instagram_story" | "tiktok" | "snapchat" // Square 1:1 (1080x1080) | "instagram_feed" | "facebook_square" // Landscape 16:9 | "youtube_landscape" | "full_hd" // 1920x1080 | "hd" // 1280x720 | "4k" // 3840x2160 | "facebook_video" | "twitter_video" | "linkedin_video"; type CaptionStyle = | "default" | "minimal" | "bold" | "tiktok" | "instagram" | "youtube" | "viral" | "viral_highlight" | "viral_bounce" | "viral_pop" | "karaoke" | "wordByWord" | "outline" | "boxed" | "highlight" | "typewriter" | "bounce"; type AnimationType = | "fadeIn" | "fadeOut" | "fadeInOut" | "slideInLeft" | "slideInRight" | "slideInUp" | "slideInDown" | "slideOutLeft" | "slideOutRight" | "slideOutUp" | "slideOutDown" | "zoomIn" | "zoomOut" | "bounceIn" | "bounceOut" | "flipInX" | "flipInY" | "shake" | "wobble" | "pulse"; type TransitionType = | "fade" | "fadeSlow" | "fadeFast" | "crossfade" | "dissolve" | "wipeLeft" | "wipeRight" | "wipeUp" | "wipeDown" | "slideLeft" | "slideRight" | "slideUp" | "slideDown" | "zoomIn" | "zoomOut" | "circleIn" | "circleOut" | "boxIn" | "boxOut"; interface OutputSettings { format?: "mp4" | "webm" | "mov" | "gif" | "png" | "jpg" | "mp3" | "wav"; // default: "mp4" codec?: "h264" | "h265" | "vp9" | "av1" | "prores"; // default: "h264" quality?: "low" | "medium" | "high" | "ultra" | "lossless"; // default: "high" fps?: number; // 1-120, overrides canvas fps bitrate?: number; // Video bitrate in kbps crf?: number; // 0-51, lower = better quality audioCodec?: "aac" | "mp3" | "opus" | "pcm"; // default: "aac" audioBitrate?: number; // Audio bitrate in kbps sampleRate?: 44100 | 48000 | 96000; thumbnail?: { time?: number; // Capture time in seconds format?: "jpg" | "png"; width?: number; height?: number; }; destinations?: Array<{ // Upload to external storage type: "s3" | "r2" | "gcs" | "azure" | "url"; url?: string; bucket?: string; key?: string; credentials?: Record; }>; } // === RESPONSE === // API responses use snake_case field names // POST /productions → 202 Accepted interface CreateProductionResponse { id: string; status: "pending" | "processing"; priority: "low" | "normal" | "high"; estimated_wait_seconds: number; created_at: string; // ISO 8601 credits_used: number; credits_remaining: number; credits_breakdown: { base_fee: number; video_render: number; tts: number; // Standard (Kokoro) 3 cr/1K chars, Premium (ElevenLabs) 13 cr/1K chars effects_processing: number; }; concurrent_jobs: number; max_concurrent: number; } // GET /productions/{id} interface Production { id: string; status: "pending" | "processing" | "completed" | "failed" | "cancelled"; created_at: string; // ISO 8601 // When completed: output_url?: string; hls_url?: string | null; output_duration?: number; // seconds thumbnail_url?: string; processing_time_ms?: number; // Absolute ISO-8601 expiry of every presigned URL in this response. // null when there are no signed URLs yet (queued/processing). url_expires_at?: string | null; // Per-production cost tracking (populated after the queue consumer // completes). Null on in-flight rows and on pre-cost-tracking rows. compute_tier?: "cpu" | "gpu_light" | "gpu_heavy" | null; compute_cost_usd?: number | null; tts_cost_usd?: number | null; tts_characters_used?: number | null; transcription_cost_usd?: number | null; transcription_seconds_used?: number | null; storage_cost_usd?: number | null; total_cost_usd?: number | null; // "admin" means the owner was not charged (ADMIN_USER_IDS allowlist). // In that case credits_used is 0 and implied_credits_used is the // display-only integer a non-exempt user would have been billed. pricing_mode: "user" | "admin"; implied_credits_used?: number | null; // When failed: error?: string; credits_used: number; priority: string; processing_started_at?: string; completed_at?: string; } // Every response, including 4xx/5xx, carries an `x-request-id` header // so you can correlate failures against server logs. Treat it as opaque // — the middleware mints a UUIDv4 by default but also accepts a client- // supplied value matching [A-Za-z0-9_\-.]{1,128} so distributed tracers // can thread their own ID through. Safe to log, never a secret. // X-RateLimit-* and Retry-After are emitted on 2xx responses and on 429; // they are not guaranteed on 401/404/500 (log your own counter there). // Error responses: { error: { code: string, message: string, details?: object } } ``` ## Credit Costs | Component | Cost | |-----------|------| | Base fee | 3 credits per production | | Video render | 2 credits per minute (up to 1080p), 20 credits per minute (4K) | | TTS Standard (Kokoro) | 3 credits per 1K characters | | TTS Premium (ElevenLabs) | 13 credits per 1K characters | | Effects processing | 3 credits per production (flat) | 1 credit = $0.01 ## TTS Voice Tiers Two tiers of text-to-speech. Voice name auto-determines tier — no explicit `provider` field needed. **Standard (Kokoro):** 46 voices, 9 languages (en-US, en-GB, fr, ja, zh, hi, it, es, pt-BR), 3 cr/1K chars. Speed 0.5-2.0. Word-level timestamps for English voices only (American + British). Voice IDs follow pattern `{lang}{gender}_{name}`: - `af_heart` (Heart, female, en-US) — default Standard voice - `af_bella` (Bella, female, en-US), `af_sarah` (Sarah, female, en-US) - `am_adam` (Adam, male, en-US), `am_liam` (Liam, male, en-US) - `bf_emma` (Emma, female, en-GB), `bm_george` (George, male, en-GB) - `jf_alpha` (Alpha, female, ja), `ff_siwis` (Siwis, female, fr) **Premium (ElevenLabs):** 52 voices, 29+ languages, 13 cr/1K chars. Speed 0.7-1.2. Full voice control (stability, similarity_boost, style). Word-level timestamps for all languages. Voice names: Sarah, Liam, Rachel, Jessica, Chris, Brian, etc. Use `GET /api/v1/voices` to list all available voices with tier and cost info. Supports `?tier=standard` or `?tier=premium` filtering. ## How `segments` Works Use `segments` for all API requests. The API auto-routes content by type: | Segment Type | Routing | Start Default | |-------------|---------|---------------| | video, image, color, luma | Single sequential track (auto-calculated start times) | Auto-calculated | | text, shape, html, waveform | Each renders ON TOP of base content | 0 | | audio | Each gets its own audio track | 0 | | tts | Each gets its own TTS track (Standard Kokoro or Premium ElevenLabs) | 0 | | caption | Merged into canvas-level `captions` config | N/A | **Key behaviors:** - Base content auto-sequences — no manual `start` time calculation needed - Text/shape overlays render on top of video — just add them alongside base content - Captions auto-link to TTS — no need to set up track IDs - Audio/TTS automatically get separate channels **Text overlay example:** ```json { "canvas": { "preset": "youtube_short", "segments": [ { "type": "video", "url": "VIDEO_URL", "duration": 10 }, { "type": "text", "text": "HELLO", "fontSize": 64, "position": "center", "start": 1, "duration": 3 } ] } } ``` The text appears ON TOP of the video at 1 second, not after the video ends. --- ## Common Patterns ### 1. Single Video Clip ```json { "canvas": { "preset": "youtube_short", "segments": [ { "type": "video", "url": "VIDEO_URL", "duration": 10 } ] } } ``` ### 2a. TTS with Auto-Captions — Premium (ElevenLabs) Captions auto-link to TTS when using segments format. ```json { "canvas": { "preset": "youtube_short", "segments": [ { "type": "video", "url": "VIDEO_URL", "duration": 30 }, { "type": "tts", "text": "Your narration text here...", "voice": "Sarah" } ], "captions": { "source": "tts", "settings": { "style": "viral_highlight", "position": "center" } } } } ``` ### 2b. TTS with Auto-Captions — Standard (Kokoro) Kokoro voice IDs (af_*, am_*, bf_*, bm_*, ff_*, etc.) auto-route to Standard tier. No `provider` field needed. ```json { "canvas": { "preset": "youtube_short", "segments": [ { "type": "video", "url": "VIDEO_URL", "duration": 30 }, { "type": "tts", "text": "Your narration text here...", "voice": "af_bella" } ], "captions": { "source": "tts", "settings": { "style": "viral_highlight", "position": "center" } } } } ``` ### 3. Image Slideshow with Transitions and Background Music Visual segments auto-sequence. Transitions, effects, and animations work in `segments` format. ```json { "canvas": { "preset": "instagram_feed", "segments": [ { "type": "image", "url": "IMAGE_1_URL", "duration": 3, "kenBurns": { "startScale": 1.0, "endScale": 1.3 }, "transitionOut": { "type": "fade", "duration": 0.5 } }, { "type": "image", "url": "IMAGE_2_URL", "duration": 3, "effectChain": { "combination": "cinematic" }, "transitionOut": { "type": "wipeRight", "duration": 0.4 } }, { "type": "image", "url": "IMAGE_3_URL", "duration": 3, "animationIn": "zoomIn" }, { "type": "audio", "url": "AUDIO_URL", "volume": 0.3, "loop": true } ] } } ``` ### 4. Video with Text Overlay Text segments automatically render on top of base content (video, image, color). ```json { "canvas": { "preset": "tiktok", "segments": [ { "type": "video", "url": "VIDEO_URL", "duration": 10 }, { "type": "text", "text": "Your Text Here", "fontSize": 64, "fontColor": "#FFFFFF", "fontWeight": "bold", "start": 1, "duration": 3, "position": { "x": "50%", "y": "80%" }, "animationIn": "fadeIn", "animationOut": "fadeOut" } ] } } ``` ### 5. Waveform Visualization ```json { "canvas": { "preset": "youtube_short", "backgroundColor": "#1a1a2e", "segments": [ { "type": "audio", "url": "AUDIO_URL" }, { "type": "waveform", "style": "bars", "color": "#00ff88", "position": { "y": "50%" } } ] } } ``` ### 6. Template with Bindings ```json { "templateId": "blueprint-uuid", "bindings": { "headline": "Summer Sale", "product_video": "https://example.com/product.mp4", "price": "$29.99" } } ``` --- ## EFFECTS REFERENCE Add effects to any segment via the `effectChain` field. Two approaches: **A) Preset combination** — applies a curated set of effects: ```json { "type": "video", "url": "...", "duration": 10, "effectChain": { "combination": "cinematic" } } ``` Available combinations: `viral`, `cinematic`, `high_energy`, `professional`, `vintage`, `noir`, `minimalist`, `podcast`, `music_visualizer`, `cool_tech`, `dreamy` **B) Individual effects array** — fine-grained control: ```json { "type": "video", "url": "...", "duration": 10, "effectChain": { "effects": [ { "type": "cinematic", "look": "high_contrast", "intensity": 0.8 }, { "type": "vignette", "preset": "subtle" } ] } } ``` **Cinematic Looks** (use in `effectChain.effects`): | Look | Description | |------|-------------| | `warm_sunset` | Orange tones, boosted saturation (lifestyle, travel) | | `cool_teal` | Blue/teal tones, high contrast (tech, modern) | | `desaturated` | Muted colors, high contrast (documentary) | | `high_contrast` | Punchy contrast, vibrant (viral content) | | `vintage` | Sepia tint, heavy grain, vignette (nostalgic) | | `noir` | Desaturated, crushed blacks (dramatic, thriller) | ```json // Individual cinematic effects { "type": "cinematic", "look": "warm_sunset", "intensity": 1.0 } { "type": "cinematic", "look": "cool_teal", "intensity": 0.7 } { "type": "cinematic", "look": "noir", "intensity": 0.85 } ``` **Glitch Effects** (use in `effectChain.effects`): | Type | Parameters | |------|------------| | `rgbShift` | preset, offsetH (0-50), offsetV (0-50) | | `vhs` | preset, noiseStrength (0-100), scanlineSpacing (2-10), colorShift (0-0.2) | | `screenShake` | preset, amplitude, frequency | | `datamosh` | preset, strength | | `colorGlitch` | preset, speed, saturation | | `mirrorGlitch` | preset, opacity | ```json { "type": "rgbShift", "preset": "medium" } { "type": "vhs", "preset": "strong" } ``` **Motion Effects** (use in `effectChain.effects`): | Type | Parameters | |------|------------| | `zoom` | preset, direction (in/out), maxZoom (1.0-4.0) | | `pan` | preset, direction (left/right/up/down), speed (0.1-10) | | `rotate` | preset, angle (-360 to 360), continuous (bool) | | `speed` | preset (slow_motion_4x/slow_motion_2x/normal/fast_2x/fast_4x), value (0.1-10) | | `reverse` | (none) | | `boomerang` | preset, loopCount (1-10) | ```json { "type": "zoom", "direction": "in", "preset": "medium" } { "type": "speed", "preset": "slow_motion_2x" } { "type": "reverse" } ``` ### INCOMPATIBLE EFFECT COMBINATIONS Do NOT combine: - `grayscale` with `saturate`, `cinematic` - `invert` with `brightness`, `contrast` - `sepia` with `grayscale` --- ## Custom Effects (AI-Generated) Generate custom FFmpeg filter effects from natural language descriptions. POST /api/v1/custom-effects - Auth: API key (production:create scope) - Plan: Available on every tier - Cost: 1 credit for AI-generated results; library and cached matches are free - Body: { "description": "dreamy warm glow" } - Response: { "filter": "...", "description": "...", "confidence": 0.9, "source": "library|cached|generated" } Use in productions: { "effectChain": { "effects": [{ "type": "customFilter", "filter": "gblur=sigma=5,eq=brightness=0.1" }] } } Common descriptions (instant, free, from library): warm, cool, sepia, cinematic, noir, vintage, dreamy, underwater, golden hour, vhs, film grain, soft glow, rgb glitch, horror, neon, pastel --- ## TRANSITIONS REFERENCE Transitions go between segments via `transitionIn` or `transitionOut`. ### Transition Structure (segments format) ```json { "canvas": { "preset": "youtube_short", "segments": [ { "type": "video", "url": "CLIP_1", "duration": 5, "transitionOut": { "type": "fade", "duration": 0.5 } }, { "type": "video", "url": "CLIP_2", "duration": 5, "transitionIn": { "type": "wipeRight", "duration": 0.4 } } ] } } ``` ### Available Transitions | Category | Types | |----------|-------| | **Fade** | `fade`, `fadeSlow`, `fadeFast`, `crossfade`, `dissolve`, `fadeBlack`, `fadeWhite` | | **Wipe** | `wipeLeft`, `wipeRight`, `wipeUp`, `wipeDown` | | **Wipe Diagonal** | `wipeDiagonalLeftUp`, `wipeDiagonalRightUp`, `wipeDiagonalLeftDown`, `wipeDiagonalRightDown` | | **Slide** | `slideLeft`, `slideRight`, `slideUp`, `slideDown`, `slideLeftSlow`, `slideRightSlow` | | **Zoom** | `zoomIn`, `zoomOut` | | **Circle** | `circleIn`, `circleOut` | | **Box** | `boxIn`, `boxOut` | | **Cover** | `shuffleLeft`, `shuffleRight`, `shuffleUp`, `shuffleDown` | | **Special** | `pixelize`, `radial`, `hblur`, `squeezeH`, `squeezeV` | | **None** | `none` (hard cut) | ```json // Examples { "type": "fade", "duration": 1.0 } { "type": "wipeRight", "duration": 0.5 } { "type": "zoomIn", "duration": 0.7 } { "type": "circleOut", "duration": 0.8 } { "type": "slideUp", "duration": 0.4 } ``` ### Viral Timing Presets - Hook (attention): 0.3s - Fast-paced: 0.4s - Standard viral: 0.5s - Smooth storytelling: 0.7s - Emotional/dramatic: 0.8s --- ## ANIMATIONS REFERENCE Animations apply to segment enter/exit via `animationIn` and `animationOut`. ### Animation Structure (segments format) ```json { "type": "image", "url": "PHOTO_URL", "duration": 3, "animationIn": "zoomIn", "animationOut": "fadeOut" } ``` ### Available Animations | Category | Types | |----------|-------| | **Fade** | `fadeIn`, `fadeOut`, `fadeInOut` | | **Slide In** | `slideInLeft`, `slideInRight`, `slideInUp`, `slideInDown` | | **Slide Out** | `slideOutLeft`, `slideOutRight`, `slideOutUp`, `slideOutDown` | | **Zoom** | `zoomIn`, `zoomOut`, `zoomInOut` | | **Rotate** | `rotateIn`, `rotateOut` | | **Bounce** | `bounceIn`, `bounceOut` | | **Flip** | `flipInX`, `flipInY`, `flipOutX`, `flipOutY` | | **Pulse** | `pulseIn`, `pulseOut` | | **Ken Burns** | `kenBurns`, `kenBurnsZoomIn`, `kenBurnsZoomOut`, `kenBurnsPanLeft`, `kenBurnsPanRight` | | **Special** | `typewriter`, `reveal`, `shake`, `wobble`, `swing`, `rubberBand` | | **None** | `none` | ```json // Common combinations { "animationIn": "fadeIn", "animationOut": "fadeOut" } { "animationIn": "slideInLeft", "animationOut": "slideOutRight" } { "animationIn": "zoomIn", "animationOut": "zoomOut" } { "animationIn": "bounceIn", "animationOut": "fadeOut" } ``` --- ## CAPTION STYLES REFERENCE Captions are auto-configured when using `segments` format with TTS. For advanced control, use canvas-level `captions`. ### Caption with segments format Captions auto-link to TTS — just add a TTS segment and set `captions` on the canvas: ```json { "canvas": { "preset": "youtube_short", "segments": [ { "type": "video", "url": "VIDEO_URL", "duration": 15 }, { "type": "tts", "text": "Your script here...", "provider": "elevenlabs", "voice": "Rachel" } ], "captions": { "source": "tts", "settings": { "style": "viral_highlight", "position": "center" } } } } ``` ### Caption Sources | Source | Description | |--------|-------------| | `tts` | Auto-generate from TTS track (uses word timestamps from ElevenLabs or Kokoro English voices) | | `transcribe` | Transcribe audio from track | | `inline` | Provide captions array manually | | `url` | Load from SRT/VTT file URL | ### Platform Styles | Style | Best For | Font Size | |-------|----------|-----------| | `tiktok` | TikTok | 150px | | `instagram` | Instagram Reels | 145px | | `youtube` | YouTube Shorts | 140px | | `tiktok_viral` | TikTok viral content | 150px | | `instagram_viral` | Instagram viral | 145px | | `youtube_viral` | YouTube viral | 140px | ### Viral Styles (2026 Trending) | Style | Effect | Use Case | |-------|--------|----------| | `viral_highlight` | Gold word-by-word karaoke with glow | Maximum engagement | | `viral_pop` | Words pop in with scale | Attention-grabbing | | `viral_zoom` | Text zooms in | Dynamic reveals | | `viral_shake` | Shaking text | Controversial/emphasis | | `viral_wave` | Wave animation | Trendy aesthetic | | `viral_bounce` | Bouncing text | Playful, energetic | ### Basic Styles | Style | Description | |-------|-------------| | `default` | Standard with outline + shadow | | `minimal` | Clean, no shadow | | `bold` | Heavy weight, strong presence | | `outline` | Strong outline, no background | | `boxed` | Opaque background box | | `highlight` | Yellow highlight marker effect | ### Animated Styles | Style | Effect | |-------|--------| | `karaoke` | Word-by-word highlight (cyan/white) | | `wordByWord` | One word at a time | | `typewriter` | Character-by-character reveal | | `bounce` | Bouncing animation | ```json // Examples { "type": "caption", "source": "tts", "trackId": "narration", "style": "viral_highlight" } { "type": "caption", "source": "tts", "trackId": "narration", "style": "tiktok", "position": "bottom" } { "type": "caption", "source": "tts", "trackId": "narration", "style": "karaoke", "position": "center" } { "type": "caption", "source": "inline", "captions": [ { "start": 0, "end": 2, "text": "First caption" }, { "start": 2, "end": 4, "text": "Second caption" } ], "style": "default" } ``` ### Caption Position - `top` - Top of frame - `center` - Middle of frame - `bottom` - Bottom of frame (default) --- ## WAVEFORM REFERENCE Waveforms visualize audio from a referenced track. ### Waveform Structure ```json { "id": "audio-track", "segments": [{ "asset": { "type": "audio", "url": "AUDIO_URL" }, "start": 0 }] }, { "segments": [{ "asset": { "type": "waveform", "trackId": "audio-track", "style": "bars", "color": "#00ff88", "preset": "prominent" }, "start": 0, "position": { "y": "50%" } }] } ``` ### Waveform Styles | Style | Description | |-------|-------------| | `bars` | Vertical bars (DEFAULT, most popular) | | `line` | Vertical lines from baseline | | `wave` | Connected waveform line | | `points` | Individual dots | | `mirror` | Mirrored top and bottom | | `circular` | Circular layout | ### Waveform Presets (for 9:16 video) | Preset | Size | Use Case | |--------|------|----------| | `compact` | 600x80px | Minimal footprint | | `medium` | 800x120px | Balanced | | `prominent` | 960x160px | High visibility (DEFAULT) | | `full_width` | 1020x180px | Maximum impact | ### Waveform Parameters | Parameter | Type | Range | Default | |-----------|------|-------|---------| | `color` | hex | #RRGGBB | #FFFFFF | | `opacity` | number | 0.0-1.0 | 0.85 | | `barWidth` | number | pixels | auto | | `barGap` | number | pixels | auto | ```json // Examples { "type": "waveform", "trackId": "audio", "style": "bars", "color": "#00ff88" } { "type": "waveform", "trackId": "audio", "style": "line", "color": "#ff00ff", "preset": "full_width" } { "type": "waveform", "trackId": "audio", "style": "mirror", "opacity": 0.7 } ``` --- ## COMPLETE EXAMPLE: Viral Video with Everything Using the recommended `segments` format — no manual track management needed: ```json { "canvas": { "preset": "youtube_short", "segments": [ { "type": "video", "url": "CLIP_1_URL", "duration": 5, "effectChain": { "effects": [{ "type": "cinematic", "look": "high_contrast", "intensity": 0.8 }] }, "transitionOut": { "type": "fade", "duration": 0.4 } }, { "type": "video", "url": "CLIP_2_URL", "duration": 5, "effectChain": { "effects": [{ "type": "saturation", "preset": "strong" }, { "type": "vignette", "preset": "subtle" }] } }, { "type": "tts", "text": "This is going to blow your mind. Here's the secret nobody talks about.", "provider": "elevenlabs", "voice": "Rachel" } ], "captions": { "source": "tts", "settings": { "style": "viral_highlight", "position": "center" } }, "backgroundAudio": { "url": "BACKGROUND_MUSIC_URL", "volume": 0.15, "fadeOut": 1 } } } ``` --- ## Error Codes | Code | HTTP | Meaning | Fix | |------|------|---------|-----| | `VALIDATION_ERROR` | 400 | Invalid request body | Check required fields, types, ranges | | `INVALID_URL` | 400 | Media URL inaccessible | Verify URL is public, returns 200 | | `UNSUPPORTED_FORMAT` | 400 | File type not supported | Use MP4/WebM/MOV/MP3/WAV/PNG/JPG | | `UNAUTHORIZED` | 401 | Missing/invalid API key | Check `Authorization: Bearer sk_live_...` | | `FORBIDDEN` | 403 | Insufficient credits/plan | Upgrade plan or purchase credits | | `NOT_FOUND` | 404 | Production/resource missing | Verify ID exists | | `RATE_LIMITED` | 429 | Too many requests | Wait and retry with exponential backoff | | `PROCESSING_ERROR` | 500 | Render failed | Check media URLs, retry once | | `CAPACITY_EXCEEDED` | 503 | Server overloaded | Retry after 30s | ## Status Flow ``` pending → processing → completed ↘ failed ↘ cancelled (via DELETE) ``` Poll interval recommendation: 2 seconds ## Rate Limits | Plan | Requests/min | Concurrent Productions | |------|--------------|------------------------| | Free | 60 | 1 | | Starter | 120 | 3 | | Creator | 120 | 3 | | Pro | 300 | 5 | | Scale | 1000 | 10 | ## Webhooks Include `webhookUrl` in request. Payload on completion: ```json { "event": "production.completed", "timestamp": "2026-01-15T10:30:00Z", "production": { "id": "uuid", "output_url": "https://assets.stratakit.io/outputs/uuid.mp4", "duration_seconds": 10.5, "processing_time_ms": 12000 } } ``` Headers: `X-Webhook-Event`, `X-StrataKit-Production-Id`, `X-Webhook-Signature` (internal use; user-configurable webhook secrets coming soon). Retry schedule: 1s, 5s, 30s, 2min, 10min (5 retries total). Events: `production.completed`, `production.failed` ## Media Upload 1. Get presigned URL: ```bash curl -X POST https://stratakit.io/api/v1/media/upload-url \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{"filename": "video.mp4", "contentType": "video/mp4", "fileSize": 10485760}' ``` 2. PUT file to `uploadUrl` from response 3. Use `publicUrl` in productions Limits: Video 5GB, Image 50MB, Audio 500MB ## Canvas Wizard (AI Theme Applicator) Apply a cohesive visual theme to an existing canvas using AI. The wizard modifies effectChain, transitions, and caption styles while preserving all assets, timing, and structure. **Cost:** 1 credit per wizard call. Direct-create mode adds production credits on top. ### Themes | Theme | Description | |-------|-------------| | `cyberpunk` | Neon glitch effects, RGB shifts, high contrast | | `noir` | Black and white, film grain, heavy vignette | | `retro` | VHS look, warm tones, sepia, scan lines | | `high_energy` | Fast cuts, zoom effects, bold captions | | `cinematic` | Film-like color grading, slow crossfades | | `minimal` | Clean and simple, subtle adjustments | | `documentary` | Natural tones, Ken Burns motion | | `viral` | TikTok-optimized punchy effects | ### Preview mode (default) ```bash curl -X POST https://stratakit.io/api/v1/canvas-wizard \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "canvas": { "preset": "tiktok", "tracks": [{"segments": [{"start": 0, "duration": 5, "asset": {"type": "image", "url": "https://assets.stratakit.io/samples/image/sample-vertical-9x16.jpg"}}]}] }, "theme": "cyberpunk" }' ``` Response: `{ "canvas": {...}, "diff": { "effects_added": 4, "transitions_added": 0, ... }, "ai_generated": true, "credits_used": 1 }` ### Direct-create mode ```bash curl -X POST https://stratakit.io/api/v1/canvas-wizard \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "canvas": { "preset": "tiktok", "tracks": [{"segments": [{"start": 0, "duration": 5, "asset": {"type": "image", "url": "https://assets.stratakit.io/samples/image/sample-vertical-9x16.jpg"}}]}] }, "theme": "viral", "createProduction": true, "name": "My Viral Short" }' ``` ### Custom guidance (no theme) ```bash curl -X POST https://stratakit.io/api/v1/canvas-wizard \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "canvas": { "preset": "youtube_short", "tracks": [...] }, "guidance": "Make it look like a horror movie trailer with dark grading" }' ``` You can combine `theme` + `guidance` for themed customization. ### Auto-publish to social platforms Add `deploy` to auto-publish when the production completes. Title and description are auto-generated from canvas content (TTS text, theme, guidance) if not provided. ```bash curl -X POST https://stratakit.io/api/v1/canvas-wizard \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "canvas": { "preset": "tiktok", "tracks": [...] }, "theme": "viral", "createProduction": true, "name": "Summer Campaign", "deploy": { "use_defaults": true } }' ``` Or specify connections explicitly with custom metadata: ```bash "deploy": { "connection_ids": ["uuid-1", "uuid-2"], "title": "Custom Title", "description": "Custom description for social", "tags": ["summer", "campaign"], "visibility": "public" } ``` Response includes `"deploy": { "targets": 2, "status": "pending_production_completion" }`. Publishing happens automatically when the production finishes processing. --- ## COMPLETE JSON SCHEMA REFERENCE This section shows ALL possible fields with their types. Fields marked `// optional` can be omitted. ### Full Canvas Schema — segments format (RECOMMENDED) Use `segments` for most requests. Base content (video/image/color) auto-sequences, overlays (text/shape/html/waveform) render on top, TTS/audio are routed automatically. ```json { "canvas": { "preset": "youtube_short", "fps": 30, "backgroundColor": "#000000", "masterVolume": 1.0, "metadata": {}, "segments": [ { "type": "video", "url": "https://example.com/clip1.mp4", "duration": 5, "fit": "cover", "trim": { "start": 0, "end": 5 }, "speed": 1.0, "mute": false, "position": { "x": "50%", "y": "50%" }, "transform": { "scale": 1.0, "rotation": 0, "opacity": 1.0 }, "transitionOut": { "type": "fade", "duration": 0.5, "easing": "ease-out" }, "animationIn": "fadeIn", "effectChain": { "effects": [{ "type": "cinematic", "look": "high_contrast", "intensity": 0.8 }] } }, { "type": "image", "url": "https://example.com/photo.jpg", "duration": 3, "kenBurns": { "startScale": 1.0, "endScale": 1.3 }, "transitionIn": { "type": "fade", "duration": 0.5 } }, { "type": "tts", "text": "Your narration text here.", "voice": "Rachel" }, { "type": "audio", "url": "https://example.com/music.mp3", "volume": 0.3, "loop": true, "fadeOut": 2 } ], "captions": { "source": "tts", "settings": { "style": "viral_highlight", "position": "center" } }, "backgroundAudio": { "url": "AUDIO_URL", "volume": 0.3, "fadeIn": 1, "fadeOut": 2, "loop": true, "trim": { "start": 0, "end": 30 } }, "outputSettings": { "format": "mp4", "codec": "h264", "quality": "high", "fps": 30, "bitrate": 8000, "crf": 23, "audioCodec": "aac", "audioBitrate": 192, "sampleRate": 48000, "thumbnail": { "time": 1, "format": "jpg", "width": 1080, "height": 1920 } } }, "name": "My Video", "webhookUrl": "https://example.com/webhook", "testMode": false, "idempotencyKey": "unique-key-123" } ``` ### All Asset Types (Full Schema) Each asset type shown below with ALL possible fields. Only `type` and fields marked "REQUIRED" are mandatory. **VideoAsset** - Video clip ```json { "type": "video", "url": "https://example.com/video.mp4", "volume": 1.0, "trim": { "start": 0, "end": 10 }, "fit": "cover", "speed": 1.0, "loop": false, "mute": false, "reverse": false, "chromaKey": { "color": "#00FF00", "similarity": 0.3, "blend": 0.1 } } ``` **ImageAsset** - Static image ```json { "type": "image", "url": "https://example.com/image.jpg", "fit": "cover", "kenBurns": { "startScale": 1.0, "endScale": 1.3 } } ``` **ColorAsset** - Solid color or gradient ```json { "type": "color", "color": "#4F46E5" } ``` **ColorAsset with Gradient** ```json { "type": "color", "color": { "type": "linear", "angle": 90, "colors": [ { "color": "#FF0000", "position": 0 }, { "color": "#0000FF", "position": 1 } ] } } ``` **TextAsset** - Text overlay ```json { "type": "text", "text": "Hello World", "fontSize": 64, "fontColor": "#FFFFFF", "fontFamily": "Inter", "fontWeight": "bold", "fontStyle": "normal", "textAlign": "center", "verticalAlign": "middle", "backgroundColor": "#000000", "backgroundPadding": 10, "backgroundRadius": 8, "maxWidth": 800, "maxHeight": 200, "lineHeight": 1.2, "letterSpacing": 0, "shadow": { "color": "#000000", "blur": 10, "offsetX": 2, "offsetY": 2 }, "stroke": { "color": "#000000", "width": 2 } } ``` **AudioAsset** - Audio file ```json { "type": "audio", "url": "https://example.com/audio.mp3", "volume": 1.0, "fadeIn": 1, "fadeOut": 1, "speed": 1.0, "pitch": 0, "pan": 0, "trim": { "start": 0, "end": 30 }, "loop": false, "normalize": true, "ducking": { "enabled": true, "threshold": -20, "reduction": -10 } } ``` **TTSAsset** - Text-to-speech (two tiers: Standard Kokoro 3 cr/1K, Premium ElevenLabs 13 cr/1K) Standard (Kokoro) example: ```json { "type": "tts", "text": "Your narration text here", "voice": "af_bella", "speed": 1.2 } ``` Premium (ElevenLabs) example: ```json { "type": "tts", "text": "Your narration text here", "voice": "Rachel", "speed": 1.0, "volume": 1.0, "stability": 0.5, "similarity_boost": 0.75, "style": 0 } ``` **CaptionAsset** - Animated captions ```json { "type": "caption", "source": "tts", "trackId": "narration", "style": "viral_highlight", "position": "center", "maxWordsPerLine": 5, "maxCharsPerLine": 40, "highlightColor": "#FFD700", "animation": "fadeIn" } ``` **WaveformAsset** - Audio visualization ```json { "type": "waveform", "trackId": "audio-track", "style": "bars", "preset": "prominent", "color": "#00FF88", "opacity": 0.85, "barWidth": 4, "barGap": 2, "smoothing": 0.5, "height": 160 } ``` **ShapeAsset** - Vector shape ```json { "type": "shape", "shape": { "type": "roundedRectangle", "width": 200, "height": 100, "cornerRadius": 16, "fill": "#4F46E5", "stroke": { "color": "#FFFFFF", "width": 2, "dashArray": [5, 5] }, "shadow": { "color": "#000000", "blur": 10, "offsetX": 2, "offsetY": 2 }, "opacity": 1.0 } } ``` **LumaAsset** - Luma matte for compositing ```json { "type": "luma", "url": "https://example.com/luma-matte.mp4", "inverted": false } ``` **HTMLAsset** - Rendered HTML content ```json { "type": "html", "html": "
Hello
", "css": "div { font-size: 24px; }", "width": 400, "height": 200 } ``` ### Shape Types Reference Each shape type with its specific properties: | Shape Type | Required Properties | Optional Properties | |------------|---------------------|---------------------| | `rectangle` | width, height | fill, stroke, shadow, opacity | | `roundedRectangle` | width, height | cornerRadius, fill, stroke, shadow, opacity | | `circle` | radius | fill, stroke, shadow, opacity | | `ellipse` | width, height | fill, stroke, shadow, opacity | | `triangle` | width, height | fill, stroke, shadow, opacity | | `polygon` | radius, points | fill, stroke, shadow, opacity | | `star` | radius, points | innerRadius, fill, stroke, shadow, opacity | | `line` | width | stroke | | `arrow` | width | stroke | | `custom` | path (SVG path) | fill, stroke, shadow, opacity | **Examples:** ```json { "type": "rectangle", "width": 200, "height": 100, "fill": "#4F46E5" } ``` ```json { "type": "roundedRectangle", "width": 200, "height": 100, "cornerRadius": 16, "fill": "#4F46E5" } ``` ```json { "type": "circle", "radius": 50, "fill": "#FF0000" } ``` ```json { "type": "polygon", "radius": 50, "points": 6, "fill": "#00FF00" } ``` ```json { "type": "star", "radius": 50, "innerRadius": 25, "points": 5, "fill": "#FFD700" } ``` ```json { "type": "custom", "path": "M 0 0 L 100 0 L 50 100 Z", "fill": "#4F46E5" } ``` --- ## Tag Mix & Match (FREE -- 0 Credits) Apply curated visual effects by selecting up to 5 tags with individual intensity control. Tags resolve to concrete FFmpeg filters at render time. No AI, no credits, instant. ### Available Tags (40 total, 5 groups) **Mood (8):** cinematic, dreamy, moody, energetic, calm, dramatic, playful, mysterious **Color (8):** warm, cool, neon, pastel, muted, vibrant, golden, teal-orange **Texture (6):** grain, soft-focus, sharp, noisy, smooth, gritty **Style (10):** vintage, retro, noir, vhs, horror, underwater, foggy, summer, winter, professional **Enhancement (8):** high-contrast, low-contrast, bloom, vignette, desaturated, saturated, bright, dark ### Intensity (0-100) Each tag accepts an intensity from 0 (minimum effect) to 100 (maximum effect). Default is 50. Conflicting tags are auto-resolved: higher intensity wins. Equal intensity: first tag wins. ### Usage in Canvas Wizard ```bash curl -X POST https://stratakit.io/api/v1/canvas-wizard \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "canvas": { "preset": "youtube_short", "segments": [ { "type": "video", "url": "VIDEO_URL", "duration": 10 } ] }, "tags": [ { "tag": "cinematic", "intensity": 70 }, { "tag": "warm", "intensity": 40 }, { "tag": "grain", "intensity": 30 } ] }' ``` ### List All Tags ```bash curl https://stratakit.io/api/v1/tags ``` Returns all 40 tags grouped by category with descriptions and conflict info. No auth required. Cached. --- ### Required vs Optional Fields Summary | Schema | Required Fields | All Others Optional | |--------|-----------------|---------------------| | **Canvas** | `segments` | preset, width, height, fps, duration, backgroundColor, masterVolume, captions, backgroundAudio, outputSettings, metadata | | **FlatSegment** | `type` | All asset-specific fields + start, duration, position, transform, crop, transition, animation, effectChain, blendMode, zIndex | | **VideoAsset** | `type` | url OR binding (one required), volume, trim, fit, speed, loop, mute, reverse, chromaKey | | **ImageAsset** | `type` | url OR binding (one required), fit, kenBurns | | **ColorAsset** | `type`, `color` | (none) | | **TextAsset** | `type` | text OR binding (one required), fontSize, fontColor, fontFamily, fontWeight, textAlign, etc. | | **AudioAsset** | `type` | url OR binding (one required), volume, fadeIn, fadeOut, trim, loop, etc. | | **TTSAsset** | `type` | text OR binding (one required), voice (determines Standard/Premium tier), provider, speed, volume, stability (Premium only), similarity_boost (Premium only), style (Premium only), etc. | | **CaptionAsset** | `type` | source, trackId, url, captions, style, position, etc. | | **WaveformAsset** | `type`, `trackId` | style, preset, color, opacity, barWidth, barGap, etc. | | **ShapeAsset** | `type`, `shape` | (shape properties vary by shape type) | | **LumaAsset** | `type`, `url` | inverted | | **HTMLAsset** | `type`, `html`, `width`, `height` | css | | **Transition** | `type` | duration, easing, lumaUrl, inverted | | **Effect** | `type` | preset, intensity, value, (other properties vary by effect type) | --- ## Links - OpenAPI: https://stratakit.io/openapi.yaml - Docs: https://stratakit.io/docs - Dashboard: https://stratakit.io/dashboard