SuperAPI AI Directory

publora-api

Marketing & growth

View repository

Updated 10-23 22:56

About this skill

Publora API Skill

This skill provides complete documentation for the Publora social media scheduling API.

When to Use This Skill

  • Scheduling posts to social media platforms
  • Creating, updating, or deleting social media posts
  • Uploading media (images/videos) for posts
  • Retrieving LinkedIn analytics (impressions, reactions, followers)
  • Adding reactions and comments to LinkedIn posts
  • Setting up webhooks for post status notifications
  • Managing workspace team members
  • Cross-platform posting workflows

API Overview

Base URL: https://api.publora.com/api/v1

Prerequisites (User Must Complete)

Important: You cannot programmatically create accounts or obtain API keys. The user must:

  1. Create account at publora.com (free tier available)
  2. Connect social accounts via OAuth in the dashboard (Channels → Add Channel)
  3. Generate API key at API in sidebar, then provide it to you

Pricing

Plan Monthly Yearly −33% Posts/Month Platforms
Starter Free Free 15 All platforms, except X
Pro, per account 1–5 · $5.996–20 · $2.9921+ · $0.99 $3.99$1.99$0.66 Unlimited All platforms
Agency Custom Custom Unlimited All platforms

Pro is priced per connected account and the tiers combine automatically — e.g. 10 accounts = 5 × $5.99 + 5 × $2.99 = $44.90/mo ($29.90/mo billed yearly).

Authentication

Publora uses API keys (not OAuth tokens). Keys never expire and don't require refresh.

Header: x-publora-key: sk_YOUR_API_KEY

const response = await fetch('https://api.publora.com/api/v1/platform-connections', {
  headers: { 'x-publora-key': 'sk_YOUR_API_KEY' }
});

Note: The MCP server uses Authorization: Bearer sk_... instead. Same key, different header format.

Quick Reference

Agency client posts

Use Company context and exact Workspace IDs for Agency work. The Agency platform settings guide covers Stories, reply controls, reposts, disclosure and YouTube metadata/thumbnails. Check the current formats and settings through GET /company/platforms.

Endpoint Method Description
/company/platforms GET Current Company publishing formats and settings
/company/post-groups POST Create an Agency draft with registered platform settings
/company/post-groups/:postGroupId PATCH Update a Company draft (settings replace the map)
/company/post-groups/:postGroupId/media/reservations POST Reserve a post attachment or auxiliary youtube_thumbnail
/company/post-groups/:postGroupId/media/:mediaFileId/complete POST Complete the same Company upload reservation

Posts

Endpoint Method Description
/list-posts GET List posts with filters
/create-post POST Create a draft, schedule a post, or publish now (publishNow: true)
/get-post/:postGroupId GET Get post details
/update-post/:postGroupId PUT Edit content, targets, timing, or status of a draft/scheduled post
/delete-post/:postGroupId DELETE Delete a post
/get-upload-url POST Get presigned URL for media
/attach-media/:postGroupId POST Attach one file by reference (download_url + file_id, e.g. from ChatGPT); leaves the post in draft
/upload-instagram-cover POST Upload a custom Instagram Reel cover (multipart)
/upload-youtube-thumbnail POST Upload a custom YouTube thumbnail (multipart)
/platform-limits GET Get live per-platform limits (no params)
/account-context GET Plan, features, publishing quotas and schedule horizon (optional scheduledTime query)
/post-logs/:postGroupId GET Get publishing logs for a post

Connections

Endpoint Method Description
/platform-connections GET List connected accounts
/test-connection/:platformId POST Test if a connection is valid

Mastodon & Bluesky Analytics

Endpoint Method Description
/post-statistics POST Get engagement for up to 50 published posts
/profile-statistics POST Get followers/following/post count for a connection

LinkedIn Analytics & Engagement

Endpoint Method Description
/linkedin-post-statistics POST Get post metrics
/linkedin-account-statistics POST Get account metrics
/linkedin-followers POST Get follower count/growth
/linkedin-profile-summary POST Get profile overview
/linkedin-reactions POST Add reaction to a post
/linkedin-reactions DELETE Remove reaction from a post
/linkedin-comments POST Post a comment
/linkedin-comments DELETE Delete a comment
/linkedin-reshare POST Reshare an existing post
/linkedin-mentionables GET List mentionable people (paid plans)

Webhooks

Endpoint Method Description
/webhooks GET List all webhooks
/webhooks POST Create a webhook
/webhooks/:id PATCH Update a webhook
/webhooks/:id DELETE Delete a webhook
/webhooks/:id/regenerate-secret POST Regenerate webhook secret

Workspace

Note: Workspace access requires approval. Contact support@publora.com to enable.

Endpoint Method Description
/workspace/users GET List team members
/workspace/users POST Add team member
/workspace/users/attach POST Attach an existing Publora user (needs the user's consent token)
/workspace/users/:userId DELETE Remove team member

Common Patterns

Schedule a Post

const response = await fetch('https://api.publora.com/api/v1/create-post', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-publora-key': 'sk_YOUR_API_KEY'
  },
  body: JSON.stringify({
    content: 'Hello world!',
    platforms: ['linkedin-ABC123', 'twitter-456'],
    scheduledTime: '2026-03-01T14:00:00.000Z'
  })
});

Publish Now

Send publishNow: true instead of scheduledTime to publish immediately at server time. It uses the monthly post allowance but no scheduled-queue slot; a future scheduledTime or status: "draft" alongside it returns 400 PUBLISH_NOW_CONFLICT. PUT /update-post/:postGroupId with { "publishNow": true } publishes an existing draft or scheduled post.

await fetch('https://api.publora.com/api/v1/create-post', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-publora-key': 'sk_YOUR_API_KEY',
    'Idempotency-Key': 'launch-2026-03-01'
  },
  body: JSON.stringify({
    content: 'Hello world!',
    platforms: ['linkedin-ABC123'],
    publishNow: true
  })
});

Check Limits Before a Batch

GET /account-context returns the plan, features, monthly and queue quotas (limit: null = unlimited), maxScheduledDate and allowedPlatforms. It is an advisory snapshot; writes are still checked.

Get Connected Platforms

const response = await fetch('https://api.publora.com/api/v1/platform-connections', {
  headers: { 'x-publora-key': 'sk_YOUR_API_KEY' }
});
const { connections } = await response.json();
// Use connections[].platformId for posting

Get LinkedIn Analytics

const response = await fetch('https://api.publora.com/api/v1/linkedin-post-statistics', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-publora-key': 'sk_YOUR_API_KEY'
  },
  body: JSON.stringify({
    postedId: 'urn:li:share:7123456789',
    platformId: 'linkedin-ABC123',
    queryTypes: 'ALL'
  })
});

Comment on LinkedIn Post

const response = await fetch('https://api.publora.com/api/v1/linkedin-comments', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-publora-key': 'sk_YOUR_API_KEY'
  },
  body: JSON.stringify({
    postedId: 'urn:li:ugcPost:7123456789',
    platformId: 'linkedin-ABC123',
    message: 'Great insights! Thanks for sharing.'
  })
});

Create Webhook

const response = await fetch('https://api.publora.com/api/v1/webhooks', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-publora-key': 'sk_YOUR_API_KEY'
  },
  body: JSON.stringify({
    name: 'Production Notifications',
    url: 'https://your-server.com/webhook',
    events: ['post.published', 'post.failed']
  })
});

Key Concepts

Platform IDs

Platform IDs follow the format platform-id:

  • twitter-123456789
  • linkedin-Tz9W5i6ZYG
  • instagram-17841412345678

Get platform IDs from the /platform-connections endpoint.

Scheduled Time Format

Use ISO 8601 UTC format:

2026-03-15T14:00:00.000Z  // Correct
2026-03-15T14:00:00Z      // Also correct

Time must be in the future. A past time is never silently accepted:

  • Less than 5 min in the past (clock skew): clamped to server time, and the 200 response carries warnings: [{ code: "SCHEDULED_TIME_COERCED", requested, effective }]. This tolerance is permanent.
  • 5 min or more in the past: clamped + warned today; scheduled to become 400 SCHEDULED_TIME_IN_PAST on 2026-08-25, unless production configuration overrides the date either way.

A 200 can still mean the API adjusted your request — read warnings, don't discard it. GET /get-post returns the effective stored scheduledTime to confirm what was actually kept.

Retry Safety (Idempotency-Key)

Send an optional Idempotency-Key header on create-post / update-post / attach-media. A timeout never tells you whether the request landed — without a key, the retry creates a second post (and on update-post with mediaUrls, or on attach-media, appends the media twice). On attach-media the key matches the post, file_id and file name, so a refreshed download_url still replays.

const key = crypto.randomUUID();  // one key per logical operation — reuse it for every retry
await fetch('https://api.publora.com/api/v1/create-post', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-publora-key': 'sk_YOUR_API_KEY',
    'Idempotency-Key': key
  },
  body: JSON.stringify({ content: 'Hello', platforms: ['twitter-123456789'] })
});
  • Same key + same body → the original response is replayed (no second post).
  • Same key + different body → 422 / IDEMPOTENCY_KEY_CONFLICT.
  • Same key still processing → 409 / IDEMPOTENCY_IN_FLIGHT — wait and retry the identical call, don't switch keys.
  • Keys are per-user and expire after 24h. Opt-in: without the header, behaviour is unchanged.

Post Statuses

  • draft - Not scheduled
  • scheduled - Waiting to publish
  • published - Successfully posted
  • failed - Publishing failed
  • partially_published - Some platforms failed

LinkedIn Query Types

Available metrics: IMPRESSION, MEMBERS_REACHED, RESHARE, REACTION, COMMENT

Use queryTypes: 'ALL' to get all metrics at once.

Webhook Events

Available events:

  • post.scheduled - Post was scheduled
  • post.published - Post was successfully published
  • post.failed - Post failed to publish
  • post.demoted - Scheduled post returned to draft. reason is media_changed (changeType attach, detach, prune_reference or reorder), media_backstop (changeType scheduler_media_backstop, with errorCode) or state_mismatch (changeType scheduler_state_repair); tolerate unknown values. Not emitted by attach-media
  • token.expiring - Defined and subscribable, but not currently dispatched; do not depend on it

Error Handling

Always check response status:

if (!response.ok) {
  const error = await response.json();
  console.error(error.error); // Error message
}

Common errors:

  • 401: Invalid API key
  • 400: Invalid parameters
  • 404: Resource not found

Machine-readable code values (branch on code, not on the message text):

  • SCHEDULED_TIME_IN_PAST (400) — scheduledTime 5+ min in the past; body carries serverTime
  • PLATFORM_SETTING_UNKNOWN (400) — unknown platformSettings path; body carries the exact field
  • FIRST_COMMENT_INVALID / FIRST_COMMENT_PLATFORM_UNKNOWN / FIRST_COMMENT_TOO_LONG (400) — firstComment or firstComments[] shape (up to three ordered entries with optional integer delaySeconds 0–86,400), platform type (never connection IDs) or per-platform length; body carries field and, for length, platform, limit, count, unit. Use one input field, not both.
  • INVALID_MEDIA_FILE (400) — attach-media body is not { file, fileName? }, the file reference is malformed, download_url fails the URL checks, or the file name is unusable
  • IDEMPOTENCY_KEY_CONFLICT (422) — key reused with a different body
  • IDEMPOTENCY_IN_FLIGHT (409) — same key still processing; retry the identical call

Successful responses may carry a warnings array (e.g. SCHEDULED_TIME_COERCED) — surface it. Full reference: Error Handling.

Resources

See the docs/ directory for:

  • docs/endpoints/ - Detailed endpoint documentation
  • docs/guides/ - How-to guides
  • docs/examples/ - Code examples in multiple languages
  • docs/platforms/ - Platform-specific information

For agent-facing skills built on this API, see publora/skills.

Agency Workspace webhooks

Agency managers use Company /webhooks or company_webhooks, with an explicit Workspace and stable mutation idempotency keys. See Agency webhooks; personal webhook endpoints do not access Company subscriptions.