Postspread API

Automate social media publishing, upload media, manage accounts, and pull analytics — all via a simple REST API.

BASE URL https://postspread.com/api/v1

Authentication

All API requests must be authenticated using a Bearer token in the Authorization header.

You can generate your API key from Settings → Developer API inside your Postspread dashboard.
# Include this header with every request
Authorization: Bearer YOUR_API_KEY
# Example curl
curl https://postspread.com/api/v1/workspaces \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"

Errors

Postspread uses standard HTTP status codes. All errors return a JSON body with an error or message key.

CodeMeaning
200Success
400Bad request — invalid parameters
401Unauthorized — invalid or missing token
403Forbidden — insufficient permissions or plan
404Resource not found
422Validation error — check the errors object
500Server error

Workspaces WORKSPACE

Retrieve workspaces you own. Most other endpoints scope their data to your active workspace.

GET /api/v1/workspaces List all workspaces

Returns all workspaces the authenticated user owns.

{
  "success": true,
  "workspaces": [
    {
      "id": 1,
      "name": "My Brand",
      "slug": "my-brand",
      "is_owner": true
    }
  ]
}

Posts POSTS

Create, schedule, list, update, and delete social media posts.

POST /api/v1/posts Create a post

Creates a new post. Publishes immediately or schedules it. Pass media IDs from the /media/create-upload-url endpoint.

⚠️ X (Twitter) Notes:

  • X requires the Forest plan to connect
  • Links in posts are automatically converted to plain text (e.g., https://example.com → example.com) because the X API charges significantly more for posts containing links

Parameters
NameTypeDescription
caption required string The text content of the post.
social_accounts required integer[] Array of social account IDs from GET /social-accounts. The workspace is resolved automatically — no workspace_id needed.
scheduled_at optional datetime ISO 8601 datetime. If omitted and is_draft is false, publishes immediately.
is_draft optional boolean Set to true to save as a draft without publishing.
media_urls optional string[] Array of public media URLs to attach. The server will download and attach them.
media_ids optional integer[] Array of Media IDs returned from <code>POST /media/create-upload-url</code>.
platform_configurations optional object Per-platform overrides keyed by platform name. E.g. <code>{"tiktok": {"draft": true}, "instagram": {"placement": "story"}}</code>.
{
  "caption": "Exciting news from our team! 🚀",
  "social_accounts": [321, 456],
  "scheduled_at": "2025-09-01T09:00:00Z",
  "platform_configurations": {
    "instagram": { "placement": "story" },
    "tiktok": { "title": "Big news!" }
  }
}
{
  "success": true,
  "post_id": 187,
  "message": "Post scheduled successfully!"
}
GET /api/v1/posts List posts

Returns a paginated list of posts in your workspace.

Parameters
NameTypeDescription
limit optional integer Items per page (default 10).
status optional string Filter by status: draft, scheduled, published, failed.
platform optional string Filter by platform (e.g. twitter).
{
  "data": [
    {
      "id": 187,
      "content": "Exciting news from our team! 🚀",
      "platforms": ["twitter", "linkedin"],
      "status": "scheduled",
      "scheduled_at": "2025-09-01T09:00:00Z",
      "media_urls": ["https://postspread.com/storage/uploads/photo.jpg"]
    }
  ],
  "meta": { "total": 1, "offset": 0, "limit": 10, "next": null }
}
GET /api/v1/posts/{id} Get a post

Returns the full details of a single post.

Parameters
NameTypeDescription
id required integer Post ID.
{
  "id": 187,
  "content": "Exciting news from our team! 🚀",
  "platforms": ["twitter"],
  "status": "published",
  "published_at": "2025-09-01T09:00:00Z"
}
PATCH /api/v1/posts/{id} Update a post

Update the content or schedule of an existing draft or scheduled post.

Parameters
NameTypeDescription
caption optional string New post content.
scheduled_at optional datetime New scheduled time.
social_accounts optional integer[] Array of social account IDs from GET /social-accounts. The workspace is resolved automatically — no workspace_id needed.
media_ids optional integer[] Updated media IDs.
platform_configurations optional object Updated per-platform overrides.
{
  "caption": "Updated caption text.",
  "scheduled_at": "2025-09-02T10:00:00Z"
}
{
  "id": 187,
  "content": "Updated caption text.",
  "status": "scheduled"
}
DELETE /api/v1/posts/{id} Delete a post

Deletes a draft or scheduled post. Published posts cannot be deleted.

Parameters
NameTypeDescription
id required integer Post ID.
{ "success": true }

Media MEDIA

Upload images or videos and attach them to posts using the returned media_id. Uploaded media expires after 24 hours if not attached to a post.

24-hour expiry: Unattached media is automatically deleted after 24 hours. Always attach the returned media_id to a post promptly.
POST /api/v1/media/create-upload-url Upload media

Register a new media file. Returns a media_id and upload_url. Upload the binary file to the upload_url, then pass media_id to POST /posts.

Parameters
NameTypeDescription
name required string Filename including extension. E.g. photo.jpg
mime_type required string MIME type. E.g. image/jpeg, video/mp4
size_bytes required integer File size in bytes.
{
  "name": "campaign-photo.jpg",
  "mime_type": "image/jpeg",
  "size_bytes": 204800
}
{
  "media_id": 42,
  "upload_url": "https://postspread.com/upload?media_id=42"
}
POST /api/v1 (Use the returned upload_url) Execute file upload (Step 2)

Send the actual binary file to the upload_url received from Step 1. The request MUST be sent as multipart/form-data with the file attached to the file field.

Parameters
NameTypeDescription
file required file The physical binary file to upload.
curl -X POST "https://postspread.com/api/v1/media/upload?media_id=42" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -F "file=@/path/to/your/photo.jpg"
{
  "success": true,
  "media_id": 42
}
GET /api/v1/media List media

Returns all media files uploaded by the authenticated user.

Parameters
NameTypeDescription
limit optional integer Items per page (default 10).
{
  "data": [
    {
      "id": 42,
      "original_name": "campaign-photo.jpg",
      "public_url": "https://postspread.com/storage/uploads/2025/08/photo.jpg",
      "mime_type": "image/jpeg",
      "size": 204800,
      "created_at": "2025-08-28T14:30:00Z"
    }
  ],
  "meta": { "total": 1, "offset": 0, "limit": 10, "next": null }
}
GET /api/v1/media/{id} Get media by ID

Returns the details and public URL for a single media file.

Parameters
NameTypeDescription
id required integer Media ID.
{
  "id": 42,
  "original_name": "campaign-photo.jpg",
  "public_url": "https://postspread.com/storage/uploads/photo.jpg",
  "mime_type": "image/jpeg",
  "size": 204800
}
DELETE /api/v1/media/{id} Delete media

Permanently deletes a media file and removes it from storage.

Parameters
NameTypeDescription
id required integer Media ID.
{ "success": true }

Social Accounts ACCOUNTS

Retrieve social accounts connected to your workspace. Use the account IDs when creating posts with per-account targeting.

GET /api/v1/social-accounts List connected accounts

Returns all connected social accounts across all your workspaces.

Parameters
NameTypeDescription
platform optional string Filter by platform: twitter, instagram, linkedin, facebook, tiktok, threads, bluesky, pinterest, youtube, telegram
limit optional integer Items per page (default 10).
{
  "data": [
    {
      "id": 12,
      "workspace_id": 199,
      "platform": "instagram",
      "name": "@mybrand",
      "avatar": "https://..."
    },
    {
      "id": 7,
      "workspace_id": 1,
      "platform": "linkedin",
      "name": "My Brand",
      "avatar": "https://..."
    }
  ],
  "meta": { "total": 2, "offset": 0, "limit": 10, "next": null }
}
GET /api/v1/social-accounts/{id} Get account by ID

Returns details for a single connected social account.

Parameters
NameTypeDescription
id required integer Social account ID.
{
  "id": 12,
  "platform": "instagram",
  "name": "@mybrand"
}

Post Results RESULTS

Retrieve the publishing results and platform responses for published posts.

GET /api/v1/post-results List post results

Returns paginated publishing results for posts that have been processed.

Parameters
NameTypeDescription
post_id optional integer Filter results for a specific post ID.
limit optional integer Items per page (default 10).
{
  "data": [
    {
      "id": 187,
      "post_id": 187,
      "status": "published",
      "results": { "twitter": "success", "linkedin": "success" },
      "published_at": "2025-09-01T09:00:05Z"
    }
  ],
  "meta": { "total": 1, "offset": 0, "limit": 10, "next": null }
}
GET /api/v1/post-results/{id} Get result by ID

Returns the full publish result for a single post.

Parameters
NameTypeDescription
id required integer Post ID.
{
  "id": 187,
  "post_id": 187,
  "status": "published",
  "results": { "twitter": "success" },
  "published_at": "2025-09-01T09:00:05Z"
}

Analytics ANALYTICS

Retrieve engagement analytics and daily performance snapshots for your published posts.

GET /api/v1/analytics List analytics

Returns paginated analytics data for posts in your workspace.

Parameters
NameTypeDescription
limit optional integer Items per page (default 10).
{
  "data": [],
  "meta": { "total": 0, "offset": 0, "limit": 10, "next": null }
}
POST /api/v1/analytics/sync Sync analytics

Triggers a fresh sync of analytics data from connected platforms.

{ "success": true, "message": "Sync queued." }
GET /api/v1/analytics/{id} Get analytics by ID

Returns aggregate analytics for a single post.

Parameters
NameTypeDescription
id required integer Post ID.
{ "id": 187, "likes": 142, "comments": 18, "shares": 6 }
GET /api/v1/analytics/{id}/daily Get daily snapshots

Returns a day-by-day breakdown of analytics for a single post.

Parameters
NameTypeDescription
id required integer Post ID.
{
  "post_id": 187,
  "daily": [
    { "date": "2025-09-01", "likes": 120, "comments": 14 },
    { "date": "2025-09-02", "likes": 22, "comments": 4 }
  ]
}