---
title: "Create Post"
method: POST
path: "/api/reddit/submit"
tags: ["Write"]
---

# Create Post

`POST /api/reddit/submit`

## Request

- Base URL: `https://api.redditapis.com`
- URL: `https://api.redditapis.com/api/reddit/submit`
- Auth: HTTP bearer

Create a Reddit post as the authenticated caller. Serves kind "self" (text), "link", "poll", "image", "video" and "videogif". An unsupported kind is refused by NAME with a 400 rather than silently downgraded to a text post. For image and video you supply a URL we fetch: the media is uploaded to Reddit and the request is held open until Reddit confirms the post, so a media post behaves the same as every other kind. NOT YET VERIFIED END TO END against a real Reddit account: the route is unit-tested and the request shape is derived from the live router, but no post has been created through it, and an unverified write fails under YOUR account in a real subreddit. Talk to support before building on it. Cost: $0.012 per call.

## Request body

- object
  - `subreddit` string, required: Target subreddit name, without the r/ prefix
  - `kind` string, required: Post kind: "self" for a text post, "link" for a URL post, "poll" for a poll, "image", "video" or "videogif" for a media post
  - `title` string, required: Post title
  - `text` string: Body text. Used when kind is "self", and optionally on a media post.
  - `url` string: Target URL. Used when kind is "link". Not accepted on a media post: an image URL here would create a LINK post pointing at the image, which is a different thing from an image post.
  - `image_url` string: Publicly readable https URL of the image. Required when kind is "image". We fetch it, so it must not need authentication. The Content-Type you serve decides the media type, so a URL with no file extension works.
  - `video_url` string: Publicly readable https URL of the video. Required when kind is "video" or "videogif". Same fetch rules as image_url.
  - `video_poster_url` string: Publicly readable https URL of a poster image for the video. REQUIRED when kind is "video" or "videogif": Reddit will not accept a video without one, and we do not invent a placeholder because it would be published under your name.
  - `options` string[]: Poll choices. Required when kind is "poll", at least two, distinct and non-empty. Reddit rules on the maximum, which is not enforced here.
  - `duration` integer: Poll length in whole days. Required when kind is "poll". Reddit rules on the accepted range, which is not enforced here.
  - `nsfw` boolean: Mark the post NSFW
  - `spoiler` boolean: Mark the post a spoiler
  - `sendreplies` boolean: Send reply notifications to the author inbox
  - `flair_id` string: Subreddit flair template id
  - `flair_text` string: Flair text, where the subreddit allows it
  - `reddit_session` string: Account session cookie (from /api/reddit/login)
  - `loid` string: Account loid cookie (from /api/reddit/login)
  - `token_v2` string: Reddit token_v2 cookie
  - `csrf_token` string: Reddit CSRF token cookie
  - `edgebucket` string: edgebucket cookie
  - `csv` string: csv cookie
  - `session_tracker` string: session_tracker cookie
  - `pc` string: pc cookie
  - `proxy` union: Sticky IP for this account — match the proxy used for /api/reddit/login, and send it on every call for that account. Object { server, username?, password? } or a proxy URL string. A bare host:port is accepted and treated as http. Schemes: http, https, socks4, socks5, socks5h (browser-backed endpoints support http, https, socks5). Pinned across internal retries; omit to use our shared pool.
    - object
      - `server` string, required
      - `username` string
      - `password` string
    - string
  - `locale` string: BCP-47 tag for the browser context, e.g. de-DE. Match it to the proxy's country. Default en-US.
  - `timezone` string: IANA zone for the browser context, e.g. Europe/Berlin. Match it to the proxy's country, or the account acts from your proxy's IP while reporting a New York clock. Casing and aliases are normalised (utc to UTC, europe/berlin to Europe/Berlin, GMT to UTC, Japan to Asia/Tokyo). A numeric offset such as +05:30 is not a timezone and is rejected. Default America/New_York.

## Response `200`

Successful response.

- object

## Other responses

- `400`: Bad request — missing or invalid parameters.
- `401`: Missing Bearer token.
- `402`: Your account balance does not cover this call, so nothing was charged and the request was not served. The response body is {"error":"Insufficient credits","top_up_url":"https://www.redditapis.com/dashboard/buy-credits","message":"..."}; error keeps that exact wording. This is a billing state, not a bad request: the same call succeeds once the balance is topped up, and retrying without topping up returns 402 again, which is why it carries Retry-After: 3600. Top up at the top_up_url, then call again at once; the header does not apply after a top-up. Read the remaining balance any time from GET /account/me, which is free and never returns this error. Distinct from the 402 on the monitoring endpoints, which is about plan entitlements rather than credits.
- `403`: Invalid Bearer token.
- `429`: Rate limit exceeded.
- `500`: Unexpected server error.
- `502`: Upstream (Reddit) rejected the request — cookies expired or account flagged.

---

[API](https://skmtc.dev/redditapis/apis/redditapis-api.md) · [All operations](https://skmtc.dev/redditapis/apis/redditapis-api/llms.txt) · [OpenAPI document](https://skmtc.dev/redditapis/apis/redditapis-api/revisions/9696482dfe9b?raw)
