RelayAPI

Snapchat API

Schedule and automate Snapchat posts with RelayAPI — stories, saved stories, Spotlight videos, and Public Profile publishing.

Quick Reference

PropertyValue
Platform keysnapchat
Auth methodOAuth 2.0
Title limit45 characters (Saved Stories)
Description limit160 characters (Spotlight, including hashtags)
Media per post1 (single image or video only)
Image formatsJPEG, PNG
Image max size5 MB
Video formatMP4 only
Video max size32 MB
Video duration5 - 60 seconds
Post typesStory, Saved Story, Spotlight
SchedulingYes
AnalyticsYes (views, viewers, screenshots, shares, completion rate)

SDK sourceTypeScript · Python · Go · Java · REST API

Before You Start

Snapchat requires a Public Profile (Person, Business, or Official) — regular accounts cannot use the API. Only 1 media item per post is allowed, making Snapchat the most restrictive platform for content format. There are no text-only posts. Vertical orientation (9:16) is practically required for all content types. Stories are ephemeral and disappear after 24 hours. Regular Stories do not support captions.

Quick Start

Post a story to Snapchat:

import Relay from '@relayapi/sdk';
const client = new Relay();

const post = await client.posts.create({
  targets: ['snapchat'],
  media: [
    { url: 'https://cdn.example.com/photo.jpg', type: 'image' }
  ],
  scheduled_at: 'now',
  target_options: {
    snapchat: {
      content_type: 'story'
    }
  }
});

console.log(post.id); // post_abc123
from relay import Relay
client = Relay()

post = client.posts.create(
    targets=['snapchat'],
    media=[
        {'url': 'https://cdn.example.com/photo.jpg', 'type': 'image'}
    ],
    scheduled_at='now',
    target_options={
        'snapchat': {
            'content_type': 'story'
        }
    }
)

print(post.id)  # post_abc123
client := relaygo.NewClient()

post, err := client.Posts.New(context.TODO(), relaygo.PostNewParams{
    Targets:     relaygo.F([]string{"snapchat"}),
    Media: relaygo.F([]relaygo.PostNewParamsMedia{{
        URL:  relaygo.F("https://cdn.example.com/photo.jpg"),
        Type: relaygo.F(relaygo.PostNewParamsMediaTypeImage),
    }}),
    ScheduledAt: relaygo.F("now"),
    TargetOptions: relaygo.F(map[string]interface{}{
        "snapchat": map[string]interface{}{
            "content_type": "story",
        },
    }),
})
RelayClient client = RelayOkHttpClient.fromEnv();

PostCreateResponse post = client.posts().create(PostCreateParams.builder()
    .addTarget("snapchat")
    .addMedia(PostCreateParams.Media.builder()
        .url("https://cdn.example.com/photo.jpg")
        .type(PostCreateParams.Media.Type.IMAGE)
        .build())
    .scheduledAt("now")
    .targetOptions(PostCreateParams.TargetOptions.builder()
        .putAdditionalProperty("snapchat", JsonValue.from(Map.of(
            "content_type", "story"
        )))
        .build())
    .build());
curl -X POST https://api.relayapi.dev/v1/posts \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "targets": ["snapchat"],
    "media": [
      {"url": "https://cdn.example.com/photo.jpg", "type": "image"}
    ],
    "scheduled_at": "now",
    "target_options": {
      "snapchat": {
        "content_type": "story"
      }
    }
  }'

Content Types

Story (Ephemeral, 24 Hours)

Basic story that disappears after 24 hours. No caption or text is supported on regular stories.

const post = await client.posts.create({
  targets: ['snapchat'],
  media: [
    { url: 'https://cdn.example.com/image.jpg', type: 'image' }
  ],
  scheduled_at: 'now',
  target_options: {
    snapchat: {
      content_type: 'story'
    }
  }
});
post = client.posts.create(
    targets=['snapchat'],
    media=[
        {'url': 'https://cdn.example.com/image.jpg', 'type': 'image'}
    ],
    scheduled_at='now',
    target_options={
        'snapchat': {
            'content_type': 'story'
        }
    }
)
post, err := client.Posts.New(context.TODO(), relaygo.PostNewParams{
    Targets:     relaygo.F([]string{"snapchat"}),
    Media: relaygo.F([]relaygo.PostNewParamsMedia{{
        URL:  relaygo.F("https://cdn.example.com/image.jpg"),
        Type: relaygo.F(relaygo.PostNewParamsMediaTypeImage),
    }}),
    ScheduledAt: relaygo.F("now"),
    TargetOptions: relaygo.F(map[string]interface{}{
        "snapchat": map[string]interface{}{
            "content_type": "story",
        },
    }),
})
PostCreateResponse post = client.posts().create(PostCreateParams.builder()
    .addTarget("snapchat")
    .addMedia(PostCreateParams.Media.builder()
        .url("https://cdn.example.com/image.jpg")
        .type(PostCreateParams.Media.Type.IMAGE)
        .build())
    .scheduledAt("now")
    .targetOptions(PostCreateParams.TargetOptions.builder()
        .putAdditionalProperty("snapchat", JsonValue.from(Map.of(
            "content_type", "story"
        )))
        .build())
    .build());
curl -X POST https://api.relayapi.dev/v1/posts \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "targets": ["snapchat"],
    "media": [
      {"url": "https://cdn.example.com/image.jpg", "type": "image"}
    ],
    "scheduled_at": "now",
    "target_options": {
      "snapchat": {
        "content_type": "story"
      }
    }
  }'

Saved Story (Permanent on Public Profile)

Saved stories are permanent and displayed on the user's Public Profile. The content field becomes the title (max 45 characters).

const post = await client.posts.create({
  content: 'Behind the scenes look!',
  targets: ['snapchat'],
  media: [
    { url: 'https://cdn.example.com/video.mp4', type: 'video' }
  ],
  scheduled_at: 'now',
  target_options: {
    snapchat: {
      content_type: 'saved_story'
    }
  }
});
post = client.posts.create(
    content='Behind the scenes look!',
    targets=['snapchat'],
    media=[
        {'url': 'https://cdn.example.com/video.mp4', 'type': 'video'}
    ],
    scheduled_at='now',
    target_options={
        'snapchat': {
            'content_type': 'saved_story'
        }
    }
)
post, err := client.Posts.New(context.TODO(), relaygo.PostNewParams{
    Content:     relaygo.F("Behind the scenes look!"),
    Targets:     relaygo.F([]string{"snapchat"}),
    Media: relaygo.F([]relaygo.PostNewParamsMedia{{
        URL:  relaygo.F("https://cdn.example.com/video.mp4"),
        Type: relaygo.F(relaygo.PostNewParamsMediaTypeVideo),
    }}),
    ScheduledAt: relaygo.F("now"),
    TargetOptions: relaygo.F(map[string]interface{}{
        "snapchat": map[string]interface{}{
            "content_type": "saved_story",
        },
    }),
})
PostCreateResponse post = client.posts().create(PostCreateParams.builder()
    .content("Behind the scenes look!")
    .addTarget("snapchat")
    .addMedia(PostCreateParams.Media.builder()
        .url("https://cdn.example.com/video.mp4")
        .type(PostCreateParams.Media.Type.VIDEO)
        .build())
    .scheduledAt("now")
    .targetOptions(PostCreateParams.TargetOptions.builder()
        .putAdditionalProperty("snapchat", JsonValue.from(Map.of(
            "content_type", "saved_story"
        )))
        .build())
    .build());
curl -X POST https://api.relayapi.dev/v1/posts \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Behind the scenes look!",
    "targets": ["snapchat"],
    "media": [
      {"url": "https://cdn.example.com/video.mp4", "type": "video"}
    ],
    "scheduled_at": "now",
    "target_options": {
      "snapchat": {
        "content_type": "saved_story"
      }
    }
  }'

Spotlight (Entertainment Feed)

Spotlight is Snapchat's entertainment feed, similar to TikTok. Video only. The content field becomes the description (max 160 chars, supports hashtags).

const post = await client.posts.create({
  content: 'Amazing sunset! #sunset #nature #viral',
  targets: ['snapchat'],
  media: [
    { url: 'https://cdn.example.com/sunset.mp4', type: 'video' }
  ],
  scheduled_at: 'now',
  target_options: {
    snapchat: {
      content_type: 'spotlight'
    }
  }
});
post = client.posts.create(
    content='Amazing sunset! #sunset #nature #viral',
    targets=['snapchat'],
    media=[
        {'url': 'https://cdn.example.com/sunset.mp4', 'type': 'video'}
    ],
    scheduled_at='now',
    target_options={
        'snapchat': {
            'content_type': 'spotlight'
        }
    }
)
post, err := client.Posts.New(context.TODO(), relaygo.PostNewParams{
    Content:     relaygo.F("Amazing sunset! #sunset #nature #viral"),
    Targets:     relaygo.F([]string{"snapchat"}),
    Media: relaygo.F([]relaygo.PostNewParamsMedia{{
        URL:  relaygo.F("https://cdn.example.com/sunset.mp4"),
        Type: relaygo.F(relaygo.PostNewParamsMediaTypeVideo),
    }}),
    ScheduledAt: relaygo.F("now"),
    TargetOptions: relaygo.F(map[string]interface{}{
        "snapchat": map[string]interface{}{
            "content_type": "spotlight",
        },
    }),
})
PostCreateResponse post = client.posts().create(PostCreateParams.builder()
    .content("Amazing sunset! #sunset #nature #viral")
    .addTarget("snapchat")
    .addMedia(PostCreateParams.Media.builder()
        .url("https://cdn.example.com/sunset.mp4")
        .type(PostCreateParams.Media.Type.VIDEO)
        .build())
    .scheduledAt("now")
    .targetOptions(PostCreateParams.TargetOptions.builder()
        .putAdditionalProperty("snapchat", JsonValue.from(Map.of(
            "content_type", "spotlight"
        )))
        .build())
    .build());
curl -X POST https://api.relayapi.dev/v1/posts \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Amazing sunset! #sunset #nature #viral",
    "targets": ["snapchat"],
    "media": [
      {"url": "https://cdn.example.com/sunset.mp4", "type": "video"}
    ],
    "scheduled_at": "now",
    "target_options": {
      "snapchat": {
        "content_type": "spotlight"
      }
    }
  }'

Spotlight only accepts video content. Use vertical 9:16 format for best results. The description (max 160 characters) supports hashtags for discoverability.

Story with Video

const post = await client.posts.create({
  targets: ['snapchat'],
  media: [
    { url: 'https://cdn.example.com/clip.mp4', type: 'video' }
  ],
  scheduled_at: 'now',
  target_options: {
    snapchat: {
      content_type: 'story'
    }
  }
});
post = client.posts.create(
    targets=['snapchat'],
    media=[
        {'url': 'https://cdn.example.com/clip.mp4', 'type': 'video'}
    ],
    scheduled_at='now',
    target_options={
        'snapchat': {
            'content_type': 'story'
        }
    }
)
post, err := client.Posts.New(context.TODO(), relaygo.PostNewParams{
    Targets:     relaygo.F([]string{"snapchat"}),
    Media: relaygo.F([]relaygo.PostNewParamsMedia{{
        URL:  relaygo.F("https://cdn.example.com/clip.mp4"),
        Type: relaygo.F(relaygo.PostNewParamsMediaTypeVideo),
    }}),
    ScheduledAt: relaygo.F("now"),
    TargetOptions: relaygo.F(map[string]interface{}{
        "snapchat": map[string]interface{}{
            "content_type": "story",
        },
    }),
})
PostCreateResponse post = client.posts().create(PostCreateParams.builder()
    .addTarget("snapchat")
    .addMedia(PostCreateParams.Media.builder()
        .url("https://cdn.example.com/clip.mp4")
        .type(PostCreateParams.Media.Type.VIDEO)
        .build())
    .scheduledAt("now")
    .targetOptions(PostCreateParams.TargetOptions.builder()
        .putAdditionalProperty("snapchat", JsonValue.from(Map.of(
            "content_type", "story"
        )))
        .build())
    .build());
curl -X POST https://api.relayapi.dev/v1/posts \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "targets": ["snapchat"],
    "media": [
      {"url": "https://cdn.example.com/clip.mp4", "type": "video"}
    ],
    "scheduled_at": "now",
    "target_options": {
      "snapchat": {
        "content_type": "story"
      }
    }
  }'

Media Requirements

Images

PropertyRequirement
Max per post1
FormatsJPEG, PNG
Max file size20 MB
Recommended1080 x 1920 px
Aspect ratio9:16 (portrait)

Videos

PropertyRequirement
Max per post1
FormatMP4 only
Max file size500 MB
Duration5 - 60 seconds
Min resolution540 x 960 px
Recommended1080 x 1920 px, 9:16 vertical

target_options Fields

All fields go inside target_options.snapchat on your post request.

FieldTypeDefaultDescription
contentstringOverride content for Snapchat specifically
mediaobject[]Override media for Snapchat specifically
content_typestring"story"Post type: "story" (ephemeral 24h), "saved_story" (permanent), or "spotlight" (entertainment feed, video only)

Common Errors

ErrorCauseFix
Public Profile requiredAccount does not have a Public ProfileSet up a Public Profile (Person, Business, or Official) in the Snapchat app.
Media is requiredNo media was providedAdd an image or video. Snapchat does not support text-only posts.
Only one media itemMultiple media items were attachedRemove extras. Snapchat only allows 1 image or 1 video per post.
Video rejectedDuration, format, or resolution does not meet requirementsCheck: 5-60 seconds, MP4 only, minimum 540 x 960 px resolution.
Title too longSaved Story title exceeds 45 charactersShorten the content to 45 characters or less.
Description too longSpotlight description exceeds 160 charactersShorten the content including hashtags to 160 characters or less.

Known Quirks

  • Most restrictive platform — only 1 media item per post, no text-only posts, no carousels.
  • Public Profile required — must be Person, Business, or Official type. Regular accounts cannot use the API.
  • Media is encrypted with AES-256-CBC before upload — RelayAPI handles this internally.
  • Stories are ephemeral — they disappear after 24 hours. No caption or text is displayed.
  • Saved Stories are permanent — displayed on the Public Profile with a title limited to 45 characters.
  • Spotlight is video-only — description limited to 160 characters (including hashtags).
  • 9:16 vertical is practically required for all content types.
  • No multi-image or carousel support — unlike Instagram or Threads.

Found something wrong? Help us improve this page.

On this page

Submit an Issue
Requires a GitHub account.View repo