Posts
Create, schedule, update, and delete social media posts across multiple platforms via the Late API
List posts visible to the authenticated user
Getting Post URLs:
For published posts, each platform entry includes platformPostUrl with the public URL.
Use status=published filter to fetch only published posts with their URLs.
Notes and constraints by platform when interpreting the response:
- YouTube: posts always include at least one video in mediaItems.
- Instagram/TikTok: posts always include media; drafts may omit media until finalized in client.
- TikTok: mediaItems will not mix photos and videos in the same post.
API key authentication - use your Late API key as a Bearer token
In: header
Query Parameters
Page number (1-based)
11 <= valuePage size
101 <= value <= 100"draft" | "scheduled" | "published" | "failed"datedatefalseResponse Body
application/json
application/json
curl -X GET "https://getlate.dev/api/v1/posts"{
"posts": [
{
"_id": "65f1c0a9e2b5af0012ab34cd",
"title": "Launch post",
"content": "We just launched!",
"status": "scheduled",
"scheduledFor": "2024-11-01T10:00:00Z",
"timezone": "UTC",
"platforms": [
{
"platform": "twitter",
"accountId": {
"_id": "64e1f0...",
"platform": "twitter",
"username": "@acme",
"displayName": "Acme Corp",
"isActive": true
},
"status": "pending"
}
],
"tags": [
"launch"
],
"createdAt": "2024-10-01T12:00:00Z",
"updatedAt": "2024-10-01T12:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 1,
"pages": 1
}
}{
"error": "Unauthorized"
}Create a draft, scheduled, or immediate post
Getting Post URLs:
- For immediate posts (
publishNow: true): The response includesplatformPostUrlin each platform entry underpost.platforms[]. - For scheduled posts: Fetch the post via
GET /v1/posts/{postId}after the scheduled time;platformPostUrlwill be populated once published.
Content/Caption requirements:
content(caption/description) is optional when:- Media is attached (
mediaItemsor per-platformcustomMedia) - All platforms have
customContentset - Posting only to YouTube (title is used instead)
- Media is attached (
- Text-only posts (no media) require
content - Stories do not use captions (content is ignored)
- Reels, feed posts, and other media posts can have optional captions
Platform constraints:
- YouTube requires a video in mediaItems; optional custom thumbnail via MediaItem.thumbnail.
- Instagram and TikTok require media; do not mix videos and images for TikTok.
- Instagram carousels support up to 10 items; Stories publish as 'story'.
- Threads carousels support up to 10 images (no videos in carousels); single posts support one image or video.
- Facebook Stories require media (single image or video); set contentType to 'story' in platformSpecificData.
- LinkedIn multi-image supports up to 20 images; single PDF documents supported (max 100MB, ~300 pages, cannot mix with other media).
- Pinterest supports single image via image_url or a single video per Pin; boardId is required.
- Bluesky supports up to 4 images per post. Images may be automatically recompressed to ≤ ~1MB to satisfy Bluesky's blob limit. When no media is attached, a link preview may be generated for URLs in the text.
- Snapchat requires media (single image or video); set contentType to 'story', 'saved_story', or 'spotlight' in platformSpecificData. Stories are ephemeral (24h), Saved Stories are permanent, Spotlight is for video content.
Multi-page/multi-location posting: Some platforms allow posting to multiple pages, organizations, or locations from a single account connection. Use the same accountId multiple times with different targets in platformSpecificData:
- Facebook:
pageId- post to multiple Facebook Pages (list via GET /v1/accounts/{id}/facebook-page) - LinkedIn:
organizationUrn- post to multiple organizations (list via GET /v1/accounts/{id}/linkedin-organizations) - Google Business:
locationId- post to multiple locations (list via GET /v1/accounts/{id}/gmb-locations) - Reddit:
subreddit- post to multiple subreddits from the same account
API key authentication - use your Late API key as a Bearer token
In: header
Post caption/text content. Optional when media is attached (images, videos, etc.). Required for text-only posts. Can also be omitted if all platforms have customContent set.
date-timefalsefalse"UTC"Tags/keywords for the post. YouTube-specific constraints:
- No count limit; duplicates are automatically removed
- Each tag must be ≤ 100 characters
- Combined total across all tags ≤ 500 characters (YouTube's limit)
trueRoot-level TikTok settings applied to all TikTok platforms in the request. This is a convenience shorthand. Settings here are merged into each TikTok platform's platformSpecificData, with platform-specific settings taking precedence.
Profile ID to schedule via queue.
When provided (without scheduledFor), the post will be automatically assigned
to the next available slot from the profile's queue. The system uses distributed
locking to prevent race conditions when multiple posts are scheduled concurrently.
Do not call /v1/queue/next-slot and then use that time in scheduledFor.
That bypasses the queue system and can cause duplicate slot assignments.
Specific queue ID to use when scheduling via queue. Only used when queuedFromProfile is also provided. If omitted, uses the profile's default queue.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://getlate.dev/api/v1/posts" \ -H "Content-Type: application/json" \ -d '{}'{
"post": {
"_id": "65f1c0a9e2b5af0012ab34cd",
"title": "Launch post",
"content": "We just launched!",
"status": "scheduled",
"scheduledFor": "2024-11-01T10:00:00Z",
"timezone": "UTC",
"platforms": [
{
"platform": "twitter",
"accountId": {
"_id": "64e1f0...",
"platform": "twitter",
"username": "@acme",
"displayName": "Acme Corp",
"isActive": true
},
"status": "pending"
}
]
},
"message": "Post scheduled successfully"
}{
"error": "string"
}{
"error": "Unauthorized"
}{
"error": "string"
}{
"error": "This exact content was already posted to this account within the last 24 hours.",
"details": {
"accountId": "string",
"platform": "string",
"existingPostId": "string"
}
}{
"error": "string",
"details": {}
}Get a single post
Fetch a single post by ID. For published posts, this returns platformPostUrl
for each platform - useful for retrieving post URLs after scheduled posts publish.
API key authentication - use your Late API key as a Bearer token
In: header
Path Parameters
Response Body
application/json
application/json
application/json
curl -X GET "https://getlate.dev/api/v1/posts/string"{
"post": {
"_id": "65f1c0a9e2b5af0012ab34cd",
"title": "Launch post",
"content": "We just launched!",
"status": "scheduled",
"scheduledFor": "2024-11-01T10:00:00Z",
"platforms": [
{
"platform": "twitter",
"accountId": {
"_id": "64e1f0...",
"platform": "twitter",
"username": "@acme",
"displayName": "Acme Corp",
"isActive": true
},
"status": "pending"
}
]
}
}{
"error": "Unauthorized"
}{
"error": "Not found"
}Delete a post
Delete a post. Published posts cannot be deleted. When deleting a scheduled or draft post that consumed upload quota, the quota will be automatically refunded.
API key authentication - use your Late API key as a Bearer token
In: header
Path Parameters
Response Body
application/json
application/json
application/json
curl -X DELETE "https://getlate.dev/api/v1/posts/string"{
"message": "Post deleted successfully"
}{
"error": "Unauthorized"
}{
"error": "Not found"
}Update a post
Update an existing post. Only draft, scheduled, failed, and partial posts can be edited. Published, publishing, and cancelled posts cannot be modified.
API key authentication - use your Late API key as a Bearer token
In: header
Path Parameters
Response Body
application/json
application/json
application/json
curl -X PUT "https://getlate.dev/api/v1/posts/string" \ -H "Content-Type: application/json" \ -d '{ "content": "Updated content for our launch post!", "scheduledFor": "2024-11-02T14:00:00Z" }'{
"message": "Post updated successfully",
"post": {
"_id": "65f1c0a9e2b5af0012ab34cd",
"content": "Updated content for our launch post!",
"status": "scheduled",
"scheduledFor": "2024-11-02T14:00:00Z"
}
}{
"error": "Unauthorized"
}{
"error": "Not found"
}Validate and schedule multiple posts from CSV
API key authentication - use your Late API key as a Bearer token
In: header
Query Parameters
falsebinaryResponse Body
application/json
application/json
application/json
curl -X POST "https://getlate.dev/api/v1/posts/bulk-upload"{
"success": true,
"totalRows": 10,
"created": 8,
"failed": 2,
"errors": [
{
"row": 3,
"error": "Invalid date format"
},
{
"row": 7,
"error": "Account not found"
}
],
"posts": [
{
"_id": "65f1c0a9e2b5af0012ab34cd",
"content": "First bulk post",
"status": "scheduled",
"scheduledFor": "2024-11-01T10:00:00Z"
}
]
}{
"error": "Unauthorized"
}{
"error": "string",
"details": {}
}Retry publishing a failed or partial post
API key authentication - use your Late API key as a Bearer token
In: header
Path Parameters
Response Body
application/json
application/json
application/json
application/json
curl -X POST "https://getlate.dev/api/v1/posts/string/retry"{
"message": "Post published successfully",
"post": {
"_id": "65f1c0a9e2b5af0012ab34cd",
"content": "Check out our new product!",
"status": "published",
"publishedAt": "2024-11-01T10:00:05Z",
"platforms": [
{
"platform": "twitter",
"accountId": {
"_id": "64e1f0...",
"platform": "twitter",
"username": "@acme",
"displayName": "Acme Corp",
"isActive": true
},
"status": "published",
"platformPostId": "1234567890",
"platformPostUrl": "https://twitter.com/acme/status/1234567890"
}
]
}
}{
"error": "Unauthorized"
}{
"error": "Not found"
}{
"error": "string",
"details": {}
}