POST Posts
POST /brands/{brandId}/collections/{collectionId}/postsCreates a post in the given collection. The post is published to every channel in the collection, subject to publishMode.
Path parameters
Section titled “Path parameters”| Parameter | Type | Description |
|---|---|---|
| brandId | integer | ID from the brands list. |
| collectionId | integer | ID from the collections list. |
Request body fields
Section titled “Request body fields”| Field | Type | Required? | Description |
|---|---|---|---|
| publishMode | string | ✅ | QUEUE, SCHEDULE, IMMEDIATE, or DRAFT. |
| caption | string | ✅ (unless poll is set) | Main post text. 1-3000 characters. |
| poll | object | ⚠️ (required if no caption) | Poll configuration. See below. |
| title | string | No | Optional title (used by YouTube, Pinterest, etc.). Max 255 chars. |
| alt | string | No | Alt text for accessibility. Max 255 chars. |
| link | string | No | URL to attach to the post. Max 1000 chars. |
| scheduledAt | string | ✅ (if publishMode = SCHEDULE) | Future timestamp in format Y-m-d H:i:s (e.g. “2026-10-10 12:12:00”). Interpreted in the brand’s timezone (see timezone field on the brand). |
| postAsStory | boolean | No | If true, publish as a Story on channels that support Stories (Instagram and Facebook). Channels on other platforms in the collection will publish the post as a regular feed post. |
| comment | object | No | Auto-comment posted after publish. See below. |
| media | array | No | Media attachments: use id from /media upload or a direct url. See below. |
| platforms | object | No | Platform-specific overrides, see Platform-specific options. |
ℹ️ scheduledAt timezone: Timestamps are interpreted in the brand’s timezone, which you can read from the timezone field returned by GET /brands. For example, if the brand’s timezone is America/New_York and you send “2026-10-10 12:12:00”, the post will publish at 12:12 PM Eastern Time.
ℹ️ publishMode values: Nuelink has a built-in Queue System per brand that manages scheduled posts (with pause, resume, and shuffle controls in the dashboard). QUEUE adds the post to that queue using the next available time slot; SCHEDULE places the post at an exact scheduledAt time; IMMEDIATE publishes now; DRAFT saves the post without publishing or scheduling.
Poll object
Section titled “Poll object”| Field | Type | Required? | Description |
|---|---|---|---|
| question | string | ✅ | Poll question. Max 280 chars. |
| options | array | ✅ | 2-4 option strings. Each option max 30 chars. |
| period | string | ✅ | How long the poll is open: 1d, 3d, or 7d. |
| correctOptionIndex | integer | No | Zero-based index of the “correct” answer (quiz mode). |
| explanation | string | No | Shown after voting. Max 512 chars. |
ℹ️ Platforms that support polls: Polls and quizzes are supported on LinkedIn, X, Telegram, Threads, Mastodon, and Bluesky. Channels on other platforms in the collection will ignore the poll (or fall back to a caption-only post).
Comment object
Section titled “Comment object”| Field | Type | Required? | Description |
|---|---|---|---|
| comment | string | ✅ | Comment text. Max 1000 chars. |
| delay | integer | ✅ | Seconds to wait after publishing before posting the comment. |
Media array
Section titled “Media array”Each element must have either id (from /media upload) or url (direct public URL), but not both.
"media": [ { "id": "bWVkaWEvWThQT0NxWWFRcEtIRXZYMW16U0hsZFRnN0hFdEpYVzIubXA0" }, { "url": "https://example.com/hero.jpg" }]ℹ️ Docs-only clarification: The OpenAPI schema marks both
idandurlas optional with no mutual-exclusion rule. Documenting the intended behavior here — worth tightening the schema usingoneOf.
Examples
Section titled “Examples”Example 1: Simple immediate text post
Section titled “Example 1: Simple immediate text post”curl -X POST https://nuelink.com/api/public/v1/brands/13493/collections/40656/posts \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "caption": "New drop alert 🌿 The Rosewater Mist is back in stock — shop now at fernwoodbotanicals.example.com", "publishMode": "IMMEDIATE" }'Response: 201 Created
{ "status": "success", "data": { "id": 4364709, "message": "Post created successfully" }}Example 2: Scheduled post with a single image
Section titled “Example 2: Scheduled post with a single image”curl -X POST https://nuelink.com/api/public/v1/brands/13493/collections/40656/posts \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "caption": "Something new is coming to the garden next week 🌱 Stay tuned.", "alt": "Close-up of dew on a fern leaf at sunrise.", "publishMode": "SCHEDULE", "scheduledAt": "2026-10-10 12:12:00", "media": [ { "id": "bWVkaWEvcmo2dzRhSVY4YUJOMWJoU3c4U2t6VEJOenVXcjRoTmsuanBn" } ] }'Response: 201 Created:
{ "status": "success", "data": { "id": 4364710, "message": "Post created successfully" }}Example 3: Poll post
Section titled “Example 3: Poll post”curl -X POST https://nuelink.com/api/public/v1/brands/13493/collections/40656/posts \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "publishMode": "IMMEDIATE", "poll": { "question": "Which scent should we bring back for summer?", "options": ["Rosewater & Oak", "Wild Fig", "Jasmine Honey"], "period": "3d" } }'Example 4: Full example with every option
Section titled “Example 4: Full example with every option”This mirrors the Postman collection’s example. Most real requests will use a small subset of these fields.
curl -X POST https://nuelink.com/api/public/v1/brands/13493/collections/40656/posts \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "title": "Spring Collection Launch", "caption": "Our new Spring Collection is live 🌿 Hand-formulated with botanicals from our own garden. Link in bio to shop.", "alt": "Flat lay of Spring Collection skincare bottles on a bed of fresh herbs.", "link": "https://fernwoodbotanicals.example.com/spring", "publishMode": "SCHEDULE", "scheduledAt": "2026-10-10 12:12:00", "postAsStory": true, "comment": { "comment": "Tap the link above to see the full collection 🌱", "delay": 30 }, "media": [ { "id": "bWVkaWEvWThQT0NxWWFRcEtIRXZYMW16U0hsZFRnN0hFdEpYVzIubXA0" }, { "url": "https://media.nuelink.com/media/bWVkaWEvanNadVY5Rm8xODdMUWJLZ2wzUmRyd2gzTkNRbHdZVE1TdUpR" } ], "platforms": { "instagram": { "collab": "harperandvine", "location": { "id": "abc123", "name": "Brooklyn, NY" }, "trialReel": "MANUAL", "shareToFeed": true }, "facebook": { "collab": "harperandvine", "location": { "id": "abc123", "name": "Brooklyn, NY" } }, "tiktok": { "sendToInbox": true }, "youtube": { "tags": ["skincare", "botanicals", "spring-collection"], "playlists": [ { "channelId": 60107, "playlistIds": ["PL123", "PL456"] } ] } } }'Error Examples
Section titled “Error Examples”Missing caption and no poll - 422:
{ "status": "error", "message": "The given data was invalid.", "errors": { "caption": [ "The caption field is required when poll is not present." ] }}Invalid scheduledAt (past date) - 422:
{ "status": "error", "message": "The given data was invalid.", "errors": { "scheduledAt": [ "The scheduled at must be a future date." ] }}Unknown YouTube channel referenced in playlists - 404:
{ "status": "error", "message": "Channel not found or does not belong to the brand", "errors": { "platforms.youtube.playlists.0.channelId": "Channel not found or does not belong to the brand" }}Collection doesn’t exist — 404:
{ "status": "error", "message": "Collection not found.", "errors": { "collection": "Collection not found." }}