Postpone Logo
Scheduling Posts

Video Covers

Set the cover image (thumbnail) of a video from a frame of the video or from your own image.

A video's cover is the still image people see before they press play. Use setVideoCover to choose a video's cover in one of two ways:

  • A frame of the video: pass offsetMs, the position of the frame in milliseconds.
  • Your own image: pass imageUrl to use an image at a public URL, or imageMediaId to use an image from your Content Library.

The cover belongs to the video in your Content Library, not to a single post. Every post that uses the video gets the cover, including posts that are already scheduled, as long as the cover is set before the post publishes. This is the same cover you can pick in the Postpone web app.

Supported Platforms

PlatformPost typesFrame of the video (offsetMs)Your own image (imageUrl, imageMediaId)
InstagramReels✅✅
TikTokVideos✅❌ Uses the first frame instead
FacebookReels✅✅
LinkedInVideos✅✅
PinterestVideo Pins✅✅

Covers are ignored everywhere else, including Instagram Stories and carousels, Facebook Stories, and platforms not listed above, such as YouTube, X (Twitter), and Threads. On those, the platform picks the cover itself.

Prefer offsetMs when you post the same video to several platforms. It's the only option that works on TikTok, and Instagram and TikTok pick the frame from the video themselves at that offset. For Facebook, LinkedIn, and Pinterest, Postpone captures the frame at that offset as an image and uploads it as the cover.

Setting a Cover

mutation setVideoCover(
  $mediaId: ID!
  $offsetMs: Int
  $imageUrl: String
  $imageMediaId: ID
) {
  setVideoCover(
    mediaId: $mediaId
    offsetMs: $offsetMs
    imageUrl: $imageUrl
    imageMediaId: $imageMediaId
  ) {
    success
    media {
      id
      name
      coverImage {
        url
        offsetMs
      }
    }
    errors {
      field
      code
      message
    }
  }
}
mediaId
ID required
ID of the video in your Content Library. Only videos can have a cover.
offsetMs
Int
Use the frame at this position in the video as the cover, in milliseconds. Must be 0 or more, and at least 100 ms before the end of the video's duration, since the last frame starts before the video ends. For example, 2500 uses the frame 2.5 seconds into the video.
imageUrl
String
Public URL of a JPEG, PNG, or WebP image to use as the cover. Other formats, such as GIF and SVG, aren't supported. Must be publicly accessible and link directly to the file.
imageMediaId
ID
ID of a JPEG, PNG, or WebP image in your Content Library to use as the cover. The image stays in your Content Library, and the video gets its own copy as its cover.

Pass exactly one of offsetMs, imageUrl, or imageMediaId. Setting a cover replaces the video's existing cover, if it has one.

The returned coverImage.url is always an image you can show as a preview. For offsetMs covers, it's the frame captured at that offset.

Using an Image from a URL

{
  "mediaId": "1002",
  "imageUrl": "https://example.com/images/launch-cover.jpg"
}

The image doesn't need to match the video's size, but platforms crop covers that don't match the video's aspect ratio. Use an image with the same aspect ratio as the video for the best results.

Using a Local Image

To use an image file on disk as a cover, first add it to your Content Library with a direct upload, then pass the returned media id as imageMediaId:

{
  "mediaId": "1002",
  "imageMediaId": "1003"
}

Removing a Cover

removeVideoCover removes the video's cover. Posts that use the video go back to the cover each platform picks by default. Calling it on a video without a cover is a no-op that succeeds.

mutation removeVideoCover($mediaId: ID!) {
  removeVideoCover(mediaId: $mediaId) {
    success
    media {
      id
      coverImage {
        url
      }
    }
    errors {
      field
      code
      message
    }
  }
}
mediaId
ID required
ID of the video in your Content Library.

Reading a Video's Cover

The coverImage field of MediaType returns the video's current cover, or null when it has none:

query media($ids: [ID]) {
  media(ids: $ids) {
    objects {
      id
      duration
      coverImage {
        url
        offsetMs
      }
    }
  }
}

offsetMs is set for covers chosen from a frame of the video and null for covers made from your own image.

Scheduling a Reel with a Cover

Covers are set on Content Library videos, so the video has to be in your Content Library before you set its cover.

Upload the video

Upload the video with uploadMediaFromUrl or a direct upload, and keep the returned media id. If the video is already in your Content Library, find its id with the media query instead.

Set the cover

Call setVideoCover with the video's id as mediaId:

{
  "mediaId": "1002",
  "offsetMs": 2500
}

Schedule the post

Pass the video's id in media when you schedule the post. For example, an Instagram Reel:

{
  "input": {
    "username": "myhandle",
    "caption": "Our new collection is here ✨",
    "media": [{ "id": "1002" }],
    "submissions": [
      {
        "postAt": "2026-12-01T15:30:00Z",
        "mediaType": "REEL"
      }
    ]
  }
}

See Instagram for the full scheduleInstagramPost mutation.

The post publishes with the cover. You can also change the cover after scheduling, as long as you do it before the post publishes.

If you attach a video by url when scheduling, Postpone adds it to your Content Library at that point. To give it a cover, find it with the media query and call setVideoCover before the post publishes, or upload it first as shown above.

Rate Limits

Each setVideoCover call that passes validation uploads an image, so it counts against the media upload rate limit, along with the general API rate limit. removeVideoCover only counts against the general API rate limit.

Common Errors

ErrorCause
Provide exactly one of: offsetMs, imageUrl, imageMediaId.None or more than one cover option was passed.
Media not found.mediaId doesn't match a file in your Content Library.
Covers can only be set on videos.mediaId is an image or a GIF.
offsetMs cannot be negative.offsetMs is below 0.
offsetMs must be … or less for this video.offsetMs is at or too close to the end of the video. Check the video's duration, in milliseconds, and pick an earlier frame.
Cover image media not found.imageMediaId doesn't match a file in your Content Library.
The cover image must be a JPEG, PNG, or WebP image.imageUrl or imageMediaId points to a video, a GIF, an SVG, or a file that isn't an image.
Invalid cover image URL.imageUrl isn't a valid public http or https URL.
Failed to upload the cover image.The image at imageUrl couldn't be downloaded, or the frame couldn't be captured. Check that the URL is public, then try again.
Media upload rate limit exceededYou've hit the media upload rate limit.