Examples
Bulk-create posts from a CSV
Turn a content calendar spreadsheet into up to 50 posts in one request.
Scopes: posts:write, plus posts:publish if any row schedules.
POST /v1/posts/bulk accepts 1–50 items, each shaped exactly like a single
createPost body. Items are processed in order, and a failing item does not
abort the batch — you get a per-item result to check.
The CSV
channelId,content,schedule
123e4567-e89b-12d3-a456-426614174000,Monday motivation 💪,2026-08-03T09:00:00.000Z
123e4567-e89b-12d3-a456-426614174000,Midweek tips 🛠️,2026-08-05T09:00:00.000Z
123e4567-e89b-12d3-a456-426614174000,Friday recap 📋,2026-08-07T09:00:00.000ZConvert and send (Node)
import { readFileSync } from "node:fs";
const rows = readFileSync("calendar.csv", "utf8")
.trim()
.split("\n")
.slice(1) // skip header
.map((line) => {
const [channelId, content, schedule] = line.split(",");
return { channelIds: [channelId], content, schedule };
});
const results = await (
await fetch("https://api.nimply.io/v1/posts/bulk", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NIMPLY_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": "calendar-import-2026-08-w1",
},
body: JSON.stringify({ posts: rows }),
})
).json();
for (const r of results) {
if (r.success) {
console.log(`row ${r.index}: created ${r.posts.map((p) => p.id).join(", ")}`);
} else {
console.error(`row ${r.index}: FAILED — ${r.error}`);
}
}Or the equivalent curl with an inline body:
curl -X POST https://api.nimply.io/v1/posts/bulk \
-H "Authorization: Bearer $NIMPLY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: calendar-import-2026-08-w1" \
-d '{
"posts": [
{ "channelIds": ["123e4567-e89b-12d3-a456-426614174000"], "content": "Monday motivation 💪", "schedule": "2026-08-03T09:00:00.000Z" },
{ "channelIds": ["123e4567-e89b-12d3-a456-426614174000"], "content": "Midweek tips 🛠️", "schedule": "2026-08-05T09:00:00.000Z" }
]
}'The response — check every item
Results come back in input order, one per item:
[
{ "index": 0, "success": true, "posts": [{ "id": "7a245d46-…", "status": "SCHEDULED" }] },
{ "index": 1, "success": false, "error": "scheduledAt must be in the future" },
{ "index": 2, "success": true, "posts": [{ "id": "8b356e57-…", "status": "SCHEDULED" }] }
]Gotchas
- A 201 does not mean everything succeeded. Item 1 above failed while the batch as a whole returned normally — always iterate the results and handle
success: false. - Each item can target multiple channels, so
postsinside a result is an array (one post per channel id). - Maximum 50 items per request; split larger calendars into multiple batches.
- Scheduling rules and scopes are identical to single-post creation:
"draft"is the default, anything else needsposts:publish. - Naive
line.split(",")breaks on captions containing commas — use a real CSV parser for production imports.