> ## Documentation Index
> Fetch the complete documentation index at: https://docs.postiz.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API Overview

> Getting started with the Postiz Public API

<Warning>
  For N8N, check out this video:

  [https://www.youtube.com/watch?v=c50u3K3xsCI](https://www.youtube.com/watch?v=c50u3K3xsCI)
</Warning>

## SDKs & Integrations

<CardGroup cols={2}>
  <Card title="NodeJS SDK" icon="node-js" href="https://www.npmjs.com/package/@postiz/node">
    Official Postiz NodeJS SDK
  </Card>

  <Card title="n8n Node" icon="n" href="https://www.npmjs.com/package/n8n-nodes-postiz">
    Custom n8n node for Postiz
  </Card>
</CardGroup>

## Authentication

There are two ways to authenticate with the Postiz API:

### API Key

Get your API key from **Settings > Developers > Public API**. Include it in the `Authorization` header:

```bash theme={null}
curl -H "Authorization: your-api-key" https://api.postiz.com/public/v1/integrations
```

### OAuth2 Token

If you're building an app for other Postiz users, use [OAuth2 Authentication](/public-api/oauth) to get tokens that act on behalf of users. OAuth tokens start with `pos_` and are used the same way:

```bash theme={null}
curl -H "Authorization: pos_your-oauth-token" https://api.postiz.com/public/v1/integrations
```

## Base URL

| Environment  | Base URL                                      |
| ------------ | --------------------------------------------- |
| Postiz Cloud | `https://api.postiz.com/public/v1`            |
| Self-hosted  | `https://{NEXT_PUBLIC_BACKEND_URL}/public/v1` |

## Rate Limits

<Info>
  **90 requests per hour** (100 for the cloud) limit applies to only the create post endpoint.

  This doesn't mean you can only post 90 times per hour—each API call counts as one request. Schedule multiple posts in a single request to maximize throughput.
</Info>

The rate limit is a single global value for the whole instance — it doesn't tier by subscription plan. Plans tier on channel and post-per-month quotas instead. Self-hosters can adjust the per-hour limit with the `API_LIMIT` env var (see [Configuration Reference](/configuration/reference)).

## Errors

| Status                  | Meaning                                                                                                                                                                     |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400 Bad Request`       | The request body or path parameter is malformed (wrong shape, unknown enum, missing required field).                                                                        |
| `401 Unauthorized`      | `Authorization` header is missing or the API key is unrecognised.                                                                                                           |
| `403 Forbidden`         | The API key is valid but doesn't own the resource (e.g. you tried to delete a post in another organisation).                                                                |
| `404 Not Found`         | The endpoint doesn't exist, or the path parameter (integration ID, post ID) was correct format but no row matched.                                                          |
| `413 Payload Too Large` | Your request body exceeded 50 MB on `/posts` — usually because images were base64-inlined instead of pre-uploaded. See [Uploads troubleshooting](/troubleshooting/uploads). |
| `429 Too Many Requests` | You exceeded `API_LIMIT` per hour on the create-post endpoint.                                                                                                              |
| `5xx`                   | Server error — retry with exponential backoff.                                                                                                                              |

For `DELETE` endpoints, `404` always means "already deleted" and is safe to ignore. A `500` *can* mean the same thing today because of a [known issue](/troubleshooting/known-issues) where a missing post ID surfaces as 500 instead of 404 — but only if the error matches that specific signature. Treat other `500` responses as real server errors: log them, retry with exponential backoff, and don't silently suppress them.

## Terminology

<Note>
  The Postiz UI uses the term **channel**, while the API uses **integration**. They refer to the same thing—a connected social media account.
</Note>

## Generate Output

The easiest way to generate your post payloads is by using this wizard.
It's the same wizard to schedule posts in the Postiz app, however instead of scheduling posts, it generates the JSON payload for you to use in your API requests.

* For cloud, make sure you are logged in.
* For local, make sure your Postiz server is running and your are logged in.

<Tabs>
  <Tab title="Cloud">
    <iframe src="https://platform.postiz.com/modal/dark/all" style={{zoom: 0.5, height: 1000, width: '100%'}} />

    <a href="https://platform.postiz.com/modal/dark/all" target="_blank" rel="noopener noreferrer" style={{display: 'block', marginTop: '10px', textAlign: 'center'}}>
      Open in full screen
    </a>
  </Tab>

  <Tab title="Local (Make sure your local server is running)">
    <iframe src="http://localhost:4200/modal/dark/all" style={{zoom: 0.5, height: 1000, width: '100%'}} />

    <a href="http://localhost:4200/modal/dark/all" target="_blank" rel="noopener noreferrer" style={{display: 'block', marginTop: '10px', textAlign: 'center'}}>
      Open in full screen
    </a>

    <p style={{fontSize: '0.85em', textAlign: 'center', marginTop: '6px'}}>
      Source-mode default. If you're running the bundled Docker image (<code>ghcr.io/gitroomhq/postiz-app</code>), the official compose maps to <code>[http://localhost:4007](http://localhost:4007)</code>.
    </p>
  </Tab>
</Tabs>

## Supported Platforms (32 total)

When creating posts, each social media platform has its own settings schema. The `settings` object must include a `__type` field matching the provider.

### Platforms with custom settings (25)

<Tabs>
  <Tab title="Social">
    | Platform              | `__type`               | Key settings                      |
    | --------------------- | ---------------------- | --------------------------------- |
    | X (Twitter)           | `x`                    | `who_can_reply_post`, `community` |
    | LinkedIn              | `linkedin`             | `post_as_images_carousel`         |
    | LinkedIn Page         | `linkedin-page`        | `post_as_images_carousel`         |
    | Facebook              | `facebook`             | `url` (optional)                  |
    | Instagram (FB-linked) | `instagram`            | `post_type`, `collaborators`      |
    | Instagram Standalone  | `instagram-standalone` | `post_type`, `collaborators`      |
    | Warpcast (Farcaster)  | `warpcast`             | `subreddit[]` (channels)          |
  </Tab>

  <Tab title="Video">
    | Platform | `__type`  | Key settings                                                                                                                           |
    | -------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------- |
    | YouTube  | `youtube` | `title`, `type`, `selfDeclaredMadeForKids`, `thumbnail`, `tags`                                                                        |
    | TikTok   | `tiktok`  | `privacy_level`, `duet`, `stitch`, `comment`, `autoAddMusic`, `brand_content_toggle`, `brand_organic_toggle`, `content_posting_method` |
  </Tab>

  <Tab title="Community">
    | Platform | `__type`  | Key settings                                |
    | -------- | --------- | ------------------------------------------- |
    | Reddit   | `reddit`  | `subreddit[]` with `title`, `type`, `flair` |
    | Lemmy    | `lemmy`   | `subreddit[]` with `id`, `title`, `url`     |
    | Discord  | `discord` | `channel`                                   |
    | Slack    | `slack`   | `channel`                                   |
    | Skool    | `skool`   | `group`, `label`, `title`                   |
    | Whop     | `whop`    | `company`, `experience`, `title`            |
  </Tab>

  <Tab title="Design">
    | Platform  | `__type`    | Key settings                               |
    | --------- | ----------- | ------------------------------------------ |
    | Pinterest | `pinterest` | `board`, `title`, `link`, `dominant_color` |
    | Dribbble  | `dribbble`  | `title`, `team`                            |
  </Tab>

  <Tab title="Blogging">
    | Platform  | `__type`    | Key settings                                               |
    | --------- | ----------- | ---------------------------------------------------------- |
    | Medium    | `medium`    | `title`, `subtitle`, `canonical`, `publication`, `tags`    |
    | Dev.to    | `devto`     | `title`, `main_image`, `canonical`, `organization`, `tags` |
    | Hashnode  | `hashnode`  | `title`, `subtitle`, `main_image`, `publication`, `tags`   |
    | WordPress | `wordpress` | `title`, `main_image`, `type`                              |
  </Tab>

  <Tab title="Business">
    | Platform           | `__type`   | Key settings                                                           |
    | ------------------ | ---------- | ---------------------------------------------------------------------- |
    | Google My Business | `gmb`      | `topicType`, `callToActionType`, `callToActionUrl`, event/offer fields |
    | Listmonk           | `listmonk` | `subject`, `preview`, `list`, `template`                               |
  </Tab>

  <Tab title="Streaming">
    | Platform | `__type` | Key settings                       |
    | -------- | -------- | ---------------------------------- |
    | Twitch   | `twitch` | `messageType`, `announcementColor` |
  </Tab>
</Tabs>

### Platforms without custom settings (7)

These platforms only require `{ "__type": "platform-name" }`:

| Platform | `__type`   |
| -------- | ---------- |
| Threads  | `threads`  |
| Mastodon | `mastodon` |
| Bluesky  | `bluesky`  |
| Telegram | `telegram` |
| Nostr    | `nostr`    |
| VK       | `vk`       |
| Kick     | `kick`     |

<Card title="View Provider Settings Reference" icon="code" href="/public-api/providers/x">
  See detailed settings schemas with examples for each platform
</Card>

## Quick Examples

### Schedule a post to X (Twitter)

```json theme={null}
{
  "type": "schedule",
  "date": "2024-12-14T10:00:00.000Z",
  "shortLink": false,
  "tags": [],
  "posts": [
    {
      "integration": { "id": "your-integration-id" },
      "value": [
        {
          "content": "Hello from the Postiz API! 🚀",
          "image": []
        }
      ],
      "settings": {
        "__type": "x",
        "who_can_reply_post": "everyone"
      }
    }
  ]
}
```

### Post immediately to LinkedIn

```json theme={null}
{
  "type": "now",
  "date": "2024-12-14T10:00:00.000Z",
  "shortLink": false,
  "tags": [],
  "posts": [
    {
      "integration": { "id": "your-linkedin-id" },
      "value": [
        {
          "content": "Exciting announcement! 🎉",
          "image": []
        }
      ],
      "settings": {
        "__type": "linkedin"
      }
    }
  ]
}
```

### Upload an image and post to Instagram

```bash theme={null}
# Step 1: Upload the image
curl -X POST "https://api.postiz.com/public/v1/upload" \
  -H "Authorization: your-api-key" \
  -F "file=@photo.jpg"

# Response: { "id": "img-123", "path": "https://uploads.postiz.com/photo.jpg", ... }

# Step 2: Create the post with the uploaded image
curl -X POST "https://api.postiz.com/public/v1/posts" \
  -H "Authorization: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "schedule",
    "date": "2024-12-14T10:00:00.000Z",
    "shortLink": false,
    "tags": [],
    "posts": [{
      "integration": { "id": "your-instagram-id" },
      "value": [{
        "content": "Beautiful sunset 🌅 #photography",
        "image": [{ "id": "img-123", "path": "https://uploads.postiz.com/photo.jpg" }]
      }],
      "settings": {
        "__type": "instagram",
        "post_type": "post"
      }
    }]
  }'
```

### Publish a Medium article

```json theme={null}
{
  "type": "now",
  "date": "2024-12-14T10:00:00.000Z",
  "shortLink": false,
  "tags": [],
  "posts": [
    {
      "integration": { "id": "your-medium-id" },
      "value": [
        {
          "content": "# Introduction\n\nThis is my article in markdown...",
          "image": []
        }
      ],
      "settings": {
        "__type": "medium",
        "title": "My Amazing Article",
        "subtitle": "A deep dive into something interesting",
        "tags": [
          { "value": "programming", "label": "Programming" }
        ]
      }
    }
  ]
}
```

### Create a Google My Business offer

```json theme={null}
{
  "type": "schedule",
  "date": "2024-12-14T10:00:00.000Z",
  "shortLink": false,
  "tags": [],
  "posts": [
    {
      "integration": { "id": "your-gmb-id" },
      "value": [
        {
          "content": "🎉 Holiday Sale! 20% off everything!",
          "image": []
        }
      ],
      "settings": {
        "__type": "gmb",
        "topicType": "OFFER",
        "callToActionType": "GET_OFFER",
        "callToActionUrl": "https://example.com/sale",
        "offerCouponCode": "HOLIDAY20"
      }
    }
  ]
}
```
