# Publish to several accounts

> Publish one post to several connected accounts at once.

Canonical: <https://www.tryadeli.com/docs/api/posts/create-publication>

`POST https://app.tryadeli.com/api/v1/publications`

Authorization: `Bearer <API key>` — see [Authentication](https://www.tryadeli.com/docs/authentication)

Publish one post to several connected accounts in a single request. Shared
`content` and `media` go to every account in `platforms`; each entry can
override them and add that platform's own options. Adeli validates every
account's post exactly as [the single-platform endpoints](https://www.tryadeli.com/docs/api/posts)
would, accepts the publication durably, and publishes to every account in the
background.

**Body**

| Name                    | Type     | Required | Description                                                                                                                                                                                                 |
| ----------------------- | -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `profileId`             | `uuid`   |          | The profile. Optional: every accountId names its profile, and they must all agree.                                                                                                                          |
| `content`               | `string` |          | The post's text: each platform's caption, message, text, or commentary. YouTube's title defaults to its first line and TikTok photo posts' title to its first 90 characters.                                |
| `media`                 | `array`  |          | Shared media, in order: { upload\_id } from Prepare media uploads (name every target platform in its platforms), or { url } for a public HTTPS video.                                                       |
| `platforms`             | `array`  | Yes      | 1–20 targets.                                                                                                                                                                                               |
| `platforms[].platform`  | `string` | Yes      | instagram, facebook, tiktok, youtube, x, bluesky, or linkedin.                                                                                                                                              |
| `platforms[].accountId` | `uuid`   | Yes      | The connected account to post from.                                                                                                                                                                         |
| `platforms[].kind`      | `string` |          | image, carousel, video, reel, or story. Inferred from the media when omitted: one video is a Reel on Instagram and Facebook and a video elsewhere.                                                          |
| `platforms[].content`   | `string` |          | Replaces content for this account, for example a shorter caption for X.                                                                                                                                     |
| `platforms[].media`     | `array`  |          | Replaces media for this account. Items may carry the platform's per-item fields, such as Instagram altText and userTags.                                                                                    |
| `platforms[].options`   | `object` |          | This platform's create-post fields other than its text and media: TikTok's music\_usage\_confirmed and privacy\_level, YouTube's privacy\_status and made\_for\_kids, Instagram's collaborators, and so on. |

Every target is validated before anything is written. An invalid target answers
`400` with each problem's path under `platforms[i]`; an account that is not in
the profile answers `404`. Nothing is published in either case. Scheduling,
queues, and drafts are not supported yet and answer `422 unsupported_feature`.

Send an `Idempotency-Key` header to make retries safe. Repeating a key with the
same body returns the original publication with `200` and publishes nothing new;
the same key with a different body returns `409 idempotency_conflict`.

The `202` response is the publication. Poll its `statusUrl` with
[Publication status](https://www.tryadeli.com/docs/api/posts/get-publication) until `status` is
`published`, `partial`, or `failed`. You can stop polling at any time: the
platforms keep publishing.

## Request examples

**cURL**

```bash
curl -X POST "https://app.tryadeli.com/api/v1/publications" \
  -H "Authorization: Bearer $ADELI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 8f6d2b1e-6a1f-4c55-9d0a-5d7c0a2f1e11" \
  -d '{
  "profileId": "00000000-0000-4000-8000-000000000001",
  "content": "Morning chorus over the pond",
  "media": [
    {
      "upload_id": "shared/staging/opaque.mp4"
    }
  ],
  "platforms": [
    {
      "platform": "instagram",
      "accountId": "00000000-0000-0000-0000-000000000010",
      "kind": "reel",
      "options": {
        "shareToFeed": true
      }
    },
    {
      "platform": "tiktok",
      "accountId": "00000000-0000-0000-0000-000000000011",
      "options": {
        "post_mode": "MEDIA_UPLOAD",
        "music_usage_confirmed": true
      }
    },
    {
      "platform": "youtube",
      "accountId": "00000000-0000-0000-0000-000000000012",
      "options": {
        "privacy_status": "private",
        "made_for_kids": false
      }
    },
    {
      "platform": "x",
      "accountId": "00000000-0000-0000-0000-000000000013",
      "content": "Morning chorus 🦆"
    }
  ]
}'
```

**JavaScript**

```javascript
const response = await fetch("https://app.tryadeli.com/api/v1/publications", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.ADELI_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": "8f6d2b1e-6a1f-4c55-9d0a-5d7c0a2f1e11",
  },
  body: JSON.stringify({
    profileId: "00000000-0000-4000-8000-000000000001",
    content: "Morning chorus over the pond",
    media: [
      {
        upload_id: "shared/staging/opaque.mp4",
      },
    ],
    platforms: [
      {
        platform: "instagram",
        accountId: "00000000-0000-0000-0000-000000000010",
        kind: "reel",
        options: {
          shareToFeed: true,
        },
      },
      {
        platform: "tiktok",
        accountId: "00000000-0000-0000-0000-000000000011",
        options: {
          post_mode: "MEDIA_UPLOAD",
          music_usage_confirmed: true,
        },
      },
      {
        platform: "youtube",
        accountId: "00000000-0000-0000-0000-000000000012",
        options: {
          privacy_status: "private",
          made_for_kids: false,
        },
      },
      {
        platform: "x",
        accountId: "00000000-0000-0000-0000-000000000013",
        content: "Morning chorus 🦆",
      },
    ],
  }),
});
console.log(await response.json());
```

**Python**

```python
import os

import requests

response = requests.post(
    "https://app.tryadeli.com/api/v1/publications",
    headers={"Authorization": f"Bearer {os.environ['ADELI_API_KEY']}", "Idempotency-Key": "8f6d2b1e-6a1f-4c55-9d0a-5d7c0a2f1e11"},
    json={
        "profileId": "00000000-0000-4000-8000-000000000001",
        "content": "Morning chorus over the pond",
        "media": [
            {
                "upload_id": "shared/staging/opaque.mp4",
            },
        ],
        "platforms": [
            {
                "platform": "instagram",
                "accountId": "00000000-0000-0000-0000-000000000010",
                "kind": "reel",
                "options": {
                    "shareToFeed": True,
                },
            },
            {
                "platform": "tiktok",
                "accountId": "00000000-0000-0000-0000-000000000011",
                "options": {
                    "post_mode": "MEDIA_UPLOAD",
                    "music_usage_confirmed": True,
                },
            },
            {
                "platform": "youtube",
                "accountId": "00000000-0000-0000-0000-000000000012",
                "options": {
                    "privacy_status": "private",
                    "made_for_kids": False,
                },
            },
            {
                "platform": "x",
                "accountId": "00000000-0000-0000-0000-000000000013",
                "content": "Morning chorus 🦆",
            },
        ],
    },
)
print(response.json())
```

## Responses

### 202

```json
{
  "id": "00000000-0000-4000-8000-000000000020",
  "profileId": "00000000-0000-4000-8000-000000000001",
  "status": "queued",
  "progress": 0,
  "statusUrl": "/api/v1/publications/00000000-0000-4000-8000-000000000020",
  "createdAt": "2026-11-03T12:00:00.000Z",
  "updatedAt": "2026-11-03T12:00:00.000Z",
  "completedAt": null,
  "targets": [
    { "id": "00000000-0000-4000-8000-000000000021", "platform": "instagram", "accountId": "00000000-0000-0000-0000-000000000010", "status": "queued", "attempts": 0, "result": null, "error": null },
    { "id": "00000000-0000-4000-8000-000000000022", "platform": "tiktok", "accountId": "00000000-0000-0000-0000-000000000011", "status": "queued", "attempts": 0, "result": null, "error": null }
  ]
}
```

### 400

```json
{
  "error": {
    "code": "invalid_request",
    "message": "Invalid publication",
    "details": [{ "code": "invalid_value", "path": ["platforms", 2, "privacy_status"], "message": "Invalid option: expected one of \"public\"|\"unlisted\"|\"private\"" }]
  }
}
```
