# PostEverywhere Bulk Operations Guide > Create up to 50 posts in one call and bulk-retry failed destinations by filter, with the exact rate-limit cost of each. **Source:** https://posteverywhere.ai/docs/bulk-operations **Section:** Core concepts **API reference:** https://posteverywhere.ai/docs/api/reference --- Two endpoints for working with many posts in one call: - [`POST /v1/posts/bulk`](/docs/api/bulk-create-posts): create up to 50 posts in a single request - [`POST /v1/posts/retry-failed`](/docs/api/retry-failed-posts): retry every failed destination matching a filter The two differ in rate-limit cost. **Bulk create is not a single hit today:** the bulk endpoint charges your key once, then creates each post through the single-post path, which charges again per post, so a 50-post bulk consumes 51 of your 60-per-minute budget. **Bulk retry is one hit.** Per-post publishing limits still apply to each post individually. ## Create up to 50 posts in one request: `POST /v1/posts/bulk` ```bash curl -X POST https://app.posteverywhere.ai/api/v1/posts/bulk \ -H "Authorization: Bearer $POSTEVERYWHERE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "posts": [ { "content": "Morning post", "account_ids": [123, 456], "scheduled_for": "2026-08-01T09:00:00Z" }, { "content": "Afternoon post", "account_ids": [123, 456], "scheduled_for": "2026-08-01T14:00:00Z" }, { "content": "Evening post", "account_ids": [123, 456], "scheduled_for": "2026-08-01T19:00:00Z" } ] }' ``` ### Bulk create response ```json { "data": { "summary": { "total": 3, "succeeded": 2, "failed": 1 }, "results": [ { "index": 0, "ok": true, "post": { "post_id": "...", ... } }, { "index": 1, "ok": true, "post": { "post_id": "...", ... } }, { "index": 2, "ok": false, "error": { "code": "validation_error", "message": "scheduled_for must be in the future", "status": 400 } } ] }, "error": null, "meta": { "request_id": "a1b2c3d4", "timestamp": "2026-06-11T09:55:12.341Z" } } ``` ### Partial-success HTTP semantics - **All succeeded** → `201 Created` - **All failed** → `422 Unprocessable Entity` - **Mixed** → `207 Multi-Status` Always iterate `results`. Don't assume `200` means everything worked. ### Bulk request limits - **Max 50 posts per call.** Exceeding returns `400 bulk_limit_exceeded`. - Each post inside the array is validated independently: one bad entry doesn't kill the others. - Posts are processed **sequentially** (not in parallel) to keep posting-rate-limits deterministic. ## Retry every failed post at once: `POST /v1/posts/retry-failed` Retry every failed destination matching a filter. Avoids the "loop over N failed posts and retry each" anti-pattern. ```bash # Retry every TikTok failure from yesterday curl -X POST https://app.posteverywhere.ai/api/v1/posts/retry-failed \ -H "Authorization: Bearer $POSTEVERYWHERE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "platform": "tiktok", "failed_after": "2026-06-10T00:00:00Z", "failed_before":"2026-06-11T00:00:00Z" }' ``` ### Filter fields (at least one filter required) | Field | Type | Description | |-------|------|-------------| | `post_ids` | string[] | Up to 200 specific post UUIDs | | `account_id` | number | Only failures on this social account | | `platform` | string | One of `instagram`, `facebook`, `x`, `linkedin`, `youtube`, `tiktok`, `threads`, `pinterest`, `bluesky`, `telegram`, `discord` | | `failed_after` | ISO timestamp | Only failures with `updated_at >= this` | | `failed_before` | ISO timestamp | Only failures with `updated_at <= this` | | `max_attempts` | number | A modifier, not a filter: skip destinations whose attempt_count is already `>= this`. Sent on its own it returns `400 no_filter` | If **no filter** is supplied, the endpoint returns `400 no_filter`: refusing to retry the entire failure history is intentional. ### Bulk retry response ```json { "data": { "retried_count": 12, "destinations": [ { "destination_id": "...", "post_id": "...", "platform": "tiktok", "new_status": "queued" }, ... ], "message": "12 destinations queued for retry." }, "error": null, "meta": { "request_id": "a1b2c3d4", "timestamp": "2026-06-11T09:55:12.341Z" } } ``` Retried destinations have their `attempts` reset to 0, `last_error` cleared, and `scheduled_for` set to `NOW()` for immediate publish. ## When bulk operations are worth using ### Schedule a 30-day content calendar ```ts const posts = generateContentPlan(30); // 30 post objects const batches = chunk(posts, 50); // Split into 50-post batches for (const batch of batches) { await client.posts.bulkCreate(batch); } ``` ### Resurrect everything that failed during an outage ```ts const outageStart = "2026-05-29T08:00:00Z"; const outageEnd = "2026-05-29T20:30:00Z"; const result = await client.posts.retryFailed({ failed_after: outageStart, failed_before: outageEnd, }); console.log(`Retrying ${result.retried_count} destinations`); ``` ### Recover one account after reconnecting ```ts // User just reconnected their Instagram. Retry recent IG failures. await client.posts.retryFailed({ account_id: 5356, failed_after: "2026-06-08T00:00:00Z", }); ``` **Related:** [what bulk calls cost against your limit](/docs/rate-limits) · [dry-running a batch](/docs/testing) · [per-item error codes](/docs/errors) · [grouping a batch into a campaign](/docs/campaigns) · [automating social media posting with an API](/blog/automate-social-media-posting-api)