← All posts

Build an Automated Content Pipeline: Generate → Render → Score → Post

Wire Wavemaker into a fully automated video pipeline — generate on a schedule, render to MP4, gate on an engagement score, and auto-post to social or a scheduler. With copy-paste code and a GitHub Action.

The real unlock of a video API isn’t making one video faster — it’s never touching the process again. This guide wires Wavemaker into a fully automated pipeline: generate → render → score → post, on a schedule, with a quality gate so only good videos ship. Everything here is built on the REST API.

The pipeline

Schedule / data file / event
  → POST /api/v1/videos        (generate)
  → POST /api/v1/renders       (render to MP4)
  → predict_engagement         (quality gate)
       ├─ score ≥ bar  → post to Buffer / webhook / YouTube
       └─ below bar    → refine and re-score, or skip

Four stages: generate the video, render it to a downloadable MP4, score it before posting, and post only if it clears your bar.

Prerequisites

  • An API key: export WAVEMAKR_API_KEY=mcp_... (create at /keys).
  • A destination: Buffer credentials, a Zapier/Make catch-hook URL, or the YouTube Data API.

Step 1–2: Generate and render

Same flow as the API guide — POST /api/v1/videos, poll to complete for a composition_id, POST /api/v1/renders, poll to done for a download_url. For an auto-poster, bias the brief toward a strong hook:

const { job_id } = await api("POST", "/api/v1/videos", {
  prompt: `${brief}\n\nThis will be auto-posted to social — keep the first 2 seconds a hard visual hook.`,
  aspect_ratio: "9:16",
  duration_seconds: 15,
});

Step 3: Score before posting (the gate that keeps your feed good)

This is the step that makes full automation safe. Run predict_engagement in a workspace and fail closed — never publish ungated:

const ws = await api("POST", "/api/v1/workspaces", { label: "auto-post" });
const run = await api("POST", `/api/v1/workspaces/${ws.workspace_id}/tools/predict_engagement`, {
  input: { assetKey: `exports/${compositionId}/${render_id}.mp4`, targetPlatform: "reels" },
});
const verdict = run.result ?? {};

const scoreUsable =
  typeof verdict.overallScore === "number" && verdict.confidence && verdict.confidence !== "none";
if (!scoreUsable) {
  console.log("Scoring unavailable — NOT posting.");
  process.exit(2);
}
if (verdict.overallScore < MIN_SCORE) {
  console.log(`Below the ${MIN_SCORE} bar — NOT posting.`);
  for (const rec of verdict.recommendations ?? []) console.log(`  - ${rec}`);
  process.exit(2);
}

If it’s below the bar, you can stop — or auto-refine and re-score: POST /api/v1/videos/:composition_id/refine with one of the returned recommendations as the instruction.

Step 4: Post it

Pick your destination. Buffer (fans out to connected accounts):

await fetch("https://api.bufferapp.com/1/updates/create.json", {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: new URLSearchParams({
    access_token: process.env.BUFFER_ACCESS_TOKEN,
    "profile_ids[]": process.env.BUFFER_PROFILE_ID,
    text: caption,
    "media[video]": downloadUrl,
    now: "true",
  }),
});

Or POST to any webhook (Zapier, Make, Slack) with the download_url + caption and let that tool handle the platform. Or upload a YouTube Short directly via the Data API. The same download_url works everywhere.

Run it on a schedule (GitHub Actions)

Turn “video content” into CI. A scheduled workflow generates from a weekly data file and posts the result:

name: Weekly Recap Video
on:
  schedule:
    - cron: "0 14 * * MON" # Mondays
  workflow_dispatch: {}
jobs:
  make-video:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v5
        with: { node-version: "20" }
      - run: node pipeline.mjs
        env:
          WAVEMAKR_API_KEY: ${{ secrets.WAVEMAKR_API_KEY }}
          POST_WEBHOOK_URL: ${{ secrets.POST_WEBHOOK_URL }}

Prefer webhooks over polling

In a long-running service, pass webhook_url (+ webhook_secret) on the generate and render calls instead of polling — you’ll get a signed video.completed / render.completed POST. Verify the X-Webhook-Signature before trusting it.

Patterns this unlocks

  • Data → video: a metrics or sales CSV becomes a weekly animated recap.
  • Report → video: a changelog or release note becomes a narrated summary.
  • Catalog → ads: loop over product URLs to generate a per-product ad set.
  • Long → short: repurpose_video cuts a long recording into captioned vertical clips.

Copy-out starters

Wavemaker ships runnable starter templates for exactly these (chart→video, report→video, auto-post to Buffer, YouTube upload, GitHub Action) — set WAVEMAKR_API_KEY and run. Pair them with the API guide and MCP setup and you’ve got an end-to-end content engine.

Get an API key and automate →

Frequently asked questions

Can I fully automate video creation and posting?
Yes. With the Wavemaker API you can generate a video, render it to MP4, score it with predict_engagement, and post it to Buffer or any webhook/scheduler — on a schedule (e.g., a GitHub Action) with no manual step. Gate posting on the engagement score so only good videos go out.
How do I stop an automated pipeline from posting bad videos?
Gate on predict_engagement before posting and fail closed: if the score is below your bar, or the scorer couldn't run, don't post (and optionally auto-refine). This keeps a fully automated feed from publishing weak content.
How do I run video generation on a schedule?
Use a scheduled GitHub Action (or any cron) that calls the API: generate from a data file or prompt, render, score, and post. A weekly metrics file becoming a recap video is a common pattern.
Can it post to TikTok / Reels / YouTube automatically?
Yes, via the platform's API or a scheduler. Examples: post to Buffer (which fans out to connected accounts), POST to a Zapier/Make webhook, or upload a Short directly with the YouTube Data API.