Skip to main content

What it checks

If media[0].kind === "video" and pinterest.coverImageUrl is missing or empty, preflight fails before any upload work runs.

Why

Pinterest mandates a still-frame URL on every video pin — it’s the poster shown before play. Without one, POST /v5/pins returns a vague 400 (“missing cover_image_url”) with no indication that the failure was preventable. Catching it locally surfaces a clear rule + a pinterest.coverImageUrl field to point at.

Failure response

{
  "error": {
    "code": "preflight_failed",
    "rule": "pinterest.video.cover_required",
    "platform": "pinterest",
    "message": "Pinterest video pins require a cover image — the still frame shown before play.",
    "remediation": "Pass `options.coverImageUrl` (with `options.platform: \"pinterest\"`) on the target.",
    "docUrl": "https://docs.letmepost.dev/errors/preflight_failed",
    "ruleUrl": "https://docs.letmepost.dev/preflight/pinterest-video-cover_required",
    "requestId": "req_..."
  }
}

Remediation

Generate a still frame and host it somewhere publicly reachable. Quick option with ffmpeg:
ffmpeg -i input.mp4 -ss 1 -vframes 1 -q:v 2 cover.jpg
Then upload the cover via POST /v1/media and reference its public URL — or pass any public CDN URL you already host:
video-pin.json
{
  "targets": [
    {
      "accountId": "00000000-0000-0000-0000-000000000000",
      "options": {
        "platform": "pinterest",
        "boardId": "<board id>",
        "coverImageUrl": "https://cdn.example.com/cover.jpg"
      }
    }
  ],
  "text": "Walkthrough",
  "media": [{ "kind": "video", "mediaId": "med_…" }]
}