RelayAPI

Reddit API

Schedule and automate Reddit posts with RelayAPI — text posts, link posts, image posts, galleries, subreddit targeting, and flair support.

Quick Reference

PropertyValue
Platform keyreddit
Auth methodOAuth 2.0
Title limit300 characters (required, cannot edit after posting)
Body text limit40,000 characters
Images per post1 (single), multiple (gallery)
Videos per postNot supported via third-party API
Image formatsJPEG, PNG, GIF
Image max size20 MB
Post typesText/Self, Link, Image, Gallery
SchedulingYes
AnalyticsLimited (upvotes, comments only)

SDK sourceTypeScript · Python · Go · Java · REST API

Before You Start

Reddit is fundamentally different from every other platform. Each subreddit is independently moderated with its own rules. What works in one subreddit may get you banned in another. Always check subreddit rules before posting. The post title is permanent and cannot be edited after posting. Many subreddits require flair — posts without it will be rejected. Video uploads are not supported for third-party API apps. New accounts are heavily restricted by karma and account age requirements.

Quick Start

Post to a subreddit:

import Relay from '@relayapi/sdk';

const client = new Relay();

const post = await client.posts.create({
  content: 'Tips for learning a new programming language\n\n1. Start with the official tutorial\n2. Build a small project immediately\n3. Read other people\'s code',
  targets: ['reddit'],
  scheduled_at: 'now',
  target_options: {
    reddit: {
      subreddit: 'learnprogramming'
    }
  }
});

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

client = Relay()

post = client.posts.create(
    content='Tips for learning a new programming language\n\n1. Start with the official tutorial\n2. Build a small project immediately\n3. Read other people\'s code',
    targets=['reddit'],
    scheduled_at='now',
    target_options={
        'reddit': {
            'subreddit': 'learnprogramming'
        }
    }
)

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

post, err := client.Posts.New(context.TODO(), relaygo.PostNewParams{
    Content:     relaygo.F("Tips for learning a new programming language\n\n1. Start with the official tutorial\n2. Build a small project immediately\n3. Read other people's code"),
    Targets:     relaygo.F([]string{"reddit"}),
    ScheduledAt: relaygo.F("now"),
    TargetOptions: relaygo.F(map[string]interface{}{
        "reddit": map[string]interface{}{
            "subreddit": "learnprogramming",
        },
    }),
})
RelayClient client = RelayOkHttpClient.fromEnv();

PostCreateResponse post = client.posts().create(PostCreateParams.builder()
    .content("Tips for learning a new programming language\n\n1. Start with the official tutorial\n2. Build a small project immediately\n3. Read other people's code")
    .addTarget("reddit")
    .scheduledAt("now")
    .targetOptions(PostCreateParams.TargetOptions.builder()
        .putAdditionalProperty("reddit", JsonValue.from(Map.of(
            "subreddit", "learnprogramming"
        )))
        .build())
    .build());
curl -X POST https://api.relayapi.dev/v1/posts \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Tips for learning a new programming language\n\n1. Start with the official tutorial\n2. Build a small project immediately\n3. Read other people'\''s code",
    "targets": ["reddit"],
    "scheduled_at": "now",
    "target_options": {
      "reddit": {
        "subreddit": "learnprogramming"
      }
    }
  }'

Content Types

Text/Self Post

The first line of content becomes the title, and the rest becomes the body. Reddit Markdown is supported in the body text.

const post = await client.posts.create({
  content: 'Tips for learning a new programming language\n\n1. Start with the official tutorial\n2. Build a small project immediately\n3. Read other people\'s code',
  targets: ['reddit'],
  scheduled_at: 'now',
  target_options: {
    reddit: {
      subreddit: 'learnprogramming'
    }
  }
});
post = client.posts.create(
    content='Tips for learning a new programming language\n\n1. Start with the official tutorial\n2. Build a small project immediately\n3. Read other people\'s code',
    targets=['reddit'],
    scheduled_at='now',
    target_options={
        'reddit': {
            'subreddit': 'learnprogramming'
        }
    }
)
post, err := client.Posts.New(context.TODO(), relaygo.PostNewParams{
    Content:     relaygo.F("Tips for learning a new programming language\n\n1. Start with the official tutorial\n2. Build a small project immediately\n3. Read other people's code"),
    Targets:     relaygo.F([]string{"reddit"}),
    ScheduledAt: relaygo.F("now"),
    TargetOptions: relaygo.F(map[string]interface{}{
        "reddit": map[string]interface{}{
            "subreddit": "learnprogramming",
        },
    }),
})
PostCreateResponse post = client.posts().create(PostCreateParams.builder()
    .content("Tips for learning a new programming language\n\n1. Start with the official tutorial\n2. Build a small project immediately\n3. Read other people's code")
    .addTarget("reddit")
    .scheduledAt("now")
    .targetOptions(PostCreateParams.TargetOptions.builder()
        .putAdditionalProperty("reddit", JsonValue.from(Map.of(
            "subreddit", "learnprogramming"
        )))
        .build())
    .build());
curl -X POST https://api.relayapi.dev/v1/posts \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Tips for learning a new programming language\n\n1. Start with the official tutorial\n2. Build a small project immediately\n3. Read other people'\''s code",
    "targets": ["reddit"],
    "scheduled_at": "now",
    "target_options": {
      "reddit": {
        "subreddit": "learnprogramming"
      }
    }
  }'

You can also provide the title explicitly using target_options.reddit.title. If not provided, the first line of content is used as the title.

Link Post

Share a URL. The title is the first line of content, and the url field creates a link post instead of a text post.

const post = await client.posts.create({
  content: 'Interesting article about modern API design patterns',
  targets: ['reddit'],
  scheduled_at: 'now',
  target_options: {
    reddit: {
      subreddit: 'programming',
      url: 'https://example.com/api-design-article'
    }
  }
});
post = client.posts.create(
    content='Interesting article about modern API design patterns',
    targets=['reddit'],
    scheduled_at='now',
    target_options={
        'reddit': {
            'subreddit': 'programming',
            'url': 'https://example.com/api-design-article'
        }
    }
)
post, err := client.Posts.New(context.TODO(), relaygo.PostNewParams{
    Content:     relaygo.F("Interesting article about modern API design patterns"),
    Targets:     relaygo.F([]string{"reddit"}),
    ScheduledAt: relaygo.F("now"),
    TargetOptions: relaygo.F(map[string]interface{}{
        "reddit": map[string]interface{}{
            "subreddit": "programming",
            "url":       "https://example.com/api-design-article",
        },
    }),
})
PostCreateResponse post = client.posts().create(PostCreateParams.builder()
    .content("Interesting article about modern API design patterns")
    .addTarget("reddit")
    .scheduledAt("now")
    .targetOptions(PostCreateParams.TargetOptions.builder()
        .putAdditionalProperty("reddit", JsonValue.from(Map.of(
            "subreddit", "programming",
            "url", "https://example.com/api-design-article"
        )))
        .build())
    .build());
curl -X POST https://api.relayapi.dev/v1/posts \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Interesting article about modern API design patterns",
    "targets": ["reddit"],
    "scheduled_at": "now",
    "target_options": {
      "reddit": {
        "subreddit": "programming",
        "url": "https://example.com/api-design-article"
      }
    }
  }'

Image Post

Single image post with a title.

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

Gallery Post (Multiple Images)

Upload multiple images as a gallery. Not all subreddits support gallery posts.

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

Post with Flair

Many subreddits require flair on every post. You can list available flairs for a subreddit via the RelayAPI accounts endpoint.

const post = await client.posts.create({
  content: 'What is your favorite programming language?',
  targets: ['reddit'],
  scheduled_at: 'now',
  target_options: {
    reddit: {
      subreddit: 'socialmedia',
      flair_id: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
    }
  }
});
post = client.posts.create(
    content='What is your favorite programming language?',
    targets=['reddit'],
    scheduled_at='now',
    target_options={
        'reddit': {
            'subreddit': 'socialmedia',
            'flair_id': 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
        }
    }
)
post, err := client.Posts.New(context.TODO(), relaygo.PostNewParams{
    Content:     relaygo.F("What is your favorite programming language?"),
    Targets:     relaygo.F([]string{"reddit"}),
    ScheduledAt: relaygo.F("now"),
    TargetOptions: relaygo.F(map[string]interface{}{
        "reddit": map[string]interface{}{
            "subreddit": "socialmedia",
            "flair_id":  "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        },
    }),
})
PostCreateResponse post = client.posts().create(PostCreateParams.builder()
    .content("What is your favorite programming language?")
    .addTarget("reddit")
    .scheduledAt("now")
    .targetOptions(PostCreateParams.TargetOptions.builder()
        .putAdditionalProperty("reddit", JsonValue.from(Map.of(
            "subreddit", "socialmedia",
            "flair_id", "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
        )))
        .build())
    .build());
curl -X POST https://api.relayapi.dev/v1/posts \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "What is your favorite programming language?",
    "targets": ["reddit"],
    "scheduled_at": "now",
    "target_options": {
      "reddit": {
        "subreddit": "socialmedia",
        "flair_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
      }
    }
  }'

To get available flairs for a subreddit, use GET /v1/accounts/{id}/reddit-flairs?subreddit=NAME. Many subreddits reject posts without flair.

Media Requirements

Images

PropertyRequirement
Max per post1 (single), multiple (gallery)
FormatsJPEG, PNG, GIF
Max file size20 MB
Recommended1200 x 628 px
Aspect ratiosFlexible (16:9, 4:3, 1:1, 9:16 all work)

Videos

PropertyRequirement
SupportNot supported via third-party API
WorkaroundUpload to YouTube or Imgur, then create a link post

target_options Fields

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

FieldTypeDescription
contentstringOverride content for Reddit specifically
mediaobject[]Override media for Reddit specifically
subredditstringTarget subreddit without the r/ prefix. Required.
titlestringPost title (max 300 chars). Falls back to first line of content. Cannot be edited after posting.
urlstringURL for link posts. If provided, creates a link post instead of a text post.
flair_idstringPost flair ID. Required by some subreddits.
force_selfbooleanForce a text/self post even when media or a URL is provided

Auto-Retry Behavior

RelayAPI automatically retries failed Reddit posts in certain scenarios:

  • Link post in text-only subreddit — automatically retries as a text/self post with the URL included in the body.
  • Missing required flair — automatically tries the first available flair for the subreddit.

Common Errors

ErrorCauseFix
SUBREDDIT_NOTALLOWED: only trusted membersSubreddit restricts posting to trusted membersBuild karma, engage with the community, or choose a different subreddit.
NO_SELFS: doesn't allow text postsSubreddit only accepts links or imagesProvide a url or attach an image instead.
SUBMIT_VALIDATION_FLAIR_REQUIREDFlair is required by the subredditFetch available flairs and provide a flair_id.
SUBREDDIT_NOEXISTTypo in subreddit name or subreddit is privateCheck spelling. Do not include the r/ prefix.
AI-generated content not allowedSubreddit bans AI-generated contentWrite original content or choose a different subreddit.
Rate limitedReddit rate limit hitNew accounts are limited to ~10 posts/day. Space posts further apart.

Known Quirks

  • Title is permanent — the post title cannot be edited after posting. Double-check before submitting.
  • Video uploads not supported for third-party apps. Upload to YouTube/Imgur and create a link post.
  • Each subreddit has unique, independent rules — moderation varies wildly between communities.
  • New accounts are heavily restricted — karma requirements and account age gates apply.
  • Reddit Markdown supported in body text for formatting.
  • Gallery posts not supported by all subreddits — check subreddit rules.
  • Auto-retry behavior — link posts that fail in text-only subreddits are automatically retried as self posts.
  • Flair auto-retry — if flair is required but not provided, RelayAPI tries the first available flair.

Automations

Commercial use of Reddit's API requires explicit written approval via the Responsible Builder Policy. OAuth clients are rate-limited to ~100 QPM. Polling-based (no webhooks).

Triggers

TypeFires on
reddit_commentComment on your post / reply to your comment
reddit_mentionu/username mention
reddit_new_postNew post in a watched subreddit
reddit_modmailModmail conversation
reddit_dmDirect private message

Send nodes

Base: https://oauth.reddit.com. All endpoints expect form-encoded bodies + a custom User-Agent.

NodeEndpointRequired fields
reddit_reply_to_commentPOST /api/commenttext, thing_id (fullname, e.g. t1_xyz)
reddit_send_pmPOST /api/composeto, text, optional subject
reddit_reply_modmailPOST /api/mod/conversations/{id}body, conversation_id
reddit_submit_postPOST /api/submitsubreddit, title, either text (self) or url (link)

Found something wrong? Help us improve this page.

On this page

Submit an Issue
Requires a GitHub account.View repo