Publora Media API

Upload media files

Operations 5

DELETE /media/{mediaId} Delete an uploaded media file #
POST /get-upload-url Get pre-signed URL for media upload #
POST /complete-media/{mediaFileId} Probe and finalize an uploaded media file #
POST /upload-instagram-cover Upload a custom Instagram Reel cover image #
POST /upload-youtube-thumbnail Upload a custom YouTube video thumbnail #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/publora-media-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

publora-media-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Publora Media API
  description: 'Affordable REST API for scheduling and publishing social media posts

    across X/Twitter, LinkedIn, Instagram, Threads, TikTok, YouTube,

    Facebook, Bluesky, Mastodon, and Telegram.


    All plans include full API access. Starting at $5.40/month (yearly) or $9/month.

    14-day free trial, no credit card needed.


    ## Workspace API

    The Workspace API allows you to manage multiple users under a single account.

    **To enable Workspace access, please contact Publora support at serge@publora.com.**'
  version: 1.0.0
  contact:
    email: serge@publora.com
    url: https://publora.com
servers:
- url: https://api.publora.com/api/v1
  description: Production
security:
- ApiKeyAuth: []
tags:
- name: Media
  description: Upload media files
paths:
  /media/{mediaId}:
    parameters:
    - $ref: '#/components/parameters/XPubloraClient'
    delete:
      summary: Delete an uploaded media file
      description: 'Delete a media record and its stored object. If the media belonged to a

        scheduled post, the post is demoted to draft and must be scheduled again.

        Media cannot be removed while its post is publishing or after the group

        has reached published or failed status.'
      operationId: deleteMedia
      tags:
      - Media
      parameters:
      - name: mediaId
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Media deleted
          content:
            application/json:
              schema:
                type: object
                required:
                - success
                properties:
                  success:
                    type: boolean
                    example: true
                  postGroupDemoted:
                    type: boolean
                  message:
                    type: string
                  groupAlreadyMissing:
                    type: boolean
                  mediaWasOrphan:
                    type: boolean
                  thumbnailCleared:
                    type: boolean
                  coverCleared:
                    type: boolean
        '400':
          description: Invalid media ID, or media belongs to a published or failed post
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Media file not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: Post is publishing or changed state concurrently; retry later
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Failed to delete media
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /get-upload-url:
    parameters:
    - $ref: '#/components/parameters/XPubloraClient'
    post:
      summary: Get pre-signed URL for media upload
      description: 'Get a pre-signed S3 URL to upload images, videos, or PDF documents.

        Upload the file directly to S3 via HTTP PUT, then create a post.

        Upload URLs expire in 1 hour. The image count per post is

        platform-specific (up to 4 for Twitter/X, Bluesky, Mastodon; up to 10

        for Instagram, LinkedIn, Facebook, Telegram; up to 20 for Threads), or 1 video per

        post. Attach multiple images to the same postGroupId to form a carousel;

        these post-media count rules do not apply to PDF document assets.'
      operationId: getUploadUrl
      tags:
      - Media
      parameters:
      - name: x-publora-user-id
        in: header
        required: false
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - fileName
              - contentType
              - postGroupId
              properties:
                fileName:
                  type: string
                  example: photo.jpg
                contentType:
                  type: string
                  description: MIME type. It must match an image/*, video/*, or application/pdf upload.
                  example: image/jpeg
                type:
                  type: string
                  enum:
                  - image
                  - video
                  - document
                  description: Optional media-type hint; inferred from contentType when omitted
                  example: image
                postGroupId:
                  type: string
                  description: Post group to attach media to
                  example: 507f1f77bcf86cd799439011
      responses:
        '200':
          description: Upload URL generated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  uploadUrl:
                    type: string
                    format: uri
                    description: Pre-signed S3 URL. PUT your file here.
                  fileUrl:
                    type: string
                    format: uri
                    description: Public URL after upload
                  mediaId:
                    type: string
                    description: Media record ID
        '400':
          description: Missing required fields
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                missingFields:
                  value:
                    error: fileName, contentType, and postGroupId are required
                invalidPostGroupId:
                  value:
                    error: Invalid postGroupId
                unsupportedContentType:
                  value:
                    error: Only video, image, and PDF files are allowed
        '401':
          description: Invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                serverError:
                  value:
                    error: Server error
  /complete-media/{mediaFileId}:
    parameters:
    - $ref: '#/components/parameters/XPubloraClient'
    post:
      summary: Probe and finalize an uploaded media file
      description: 'Optionally run the server-side media probe immediately after uploading

        bytes to the pre-signed URL. This call is not required: scheduling also

        probes media that is still uploading.'
      operationId: completeMedia
      tags:
      - Media
      parameters:
      - name: mediaFileId
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Media probe completed
          content:
            application/json:
              schema:
                type: object
                required:
                - success
                - mediaFile
                properties:
                  success:
                    type: boolean
                    example: true
                  mediaFile:
                    type: object
                    required:
                    - _id
                    properties:
                      _id:
                        type: string
                      type:
                        type:
                        - string
                        - 'null'
                      mimeType:
                        type:
                        - string
                        - 'null'
                      fileName:
                        type:
                        - string
                        - 'null'
                      url:
                        type:
                        - string
                        - 'null'
                        format: uri
                      status:
                        type:
                        - string
                        - 'null'
                      metadata:
                        type:
                        - object
                        - 'null'
                        additionalProperties: true
        '400':
          description: Invalid media ID or uploaded media failed validation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Media file not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: Media was deleted or failed concurrently while being probed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Failed to complete media upload
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: Media probe service or uploaded object is temporarily unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /upload-instagram-cover:
    parameters:
    - $ref: '#/components/parameters/XPubloraClient'
    post:
      summary: Upload a custom Instagram Reel cover image
      description: 'Upload a cover image for an Instagram Reel. The image is stored as a

        JPEG (PNG/WebP are transcoded server-side; transparency is flattened

        onto white) and a public URL is returned. Set that URL as

        platformSettings.instagram.coverUrl via update-post to use it as the

        Reel cover. The target post group must be an editable (draft or

        scheduled) post you own and not currently publishing.

        Covers apply to Reels only and are ignored for Stories and images.'
      operationId: uploadInstagramCover
      tags:
      - Media
      parameters:
      - name: x-publora-user-id
        in: header
        required: false
        description: Managed user ID (workspace only)
        schema:
          type: string
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
              - cover
              - postGroupId
              properties:
                cover:
                  type: string
                  format: binary
                  description: Cover image (JPEG, PNG, or WebP; 8 MB max). PNG/WebP are converted to JPEG.
                postGroupId:
                  type: string
                  description: Editable post group (draft or scheduled) to attach the cover to
                  example: 507f1f77bcf86cd799439011
      responses:
        '200':
          description: Cover uploaded
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  cover:
                    type: object
                    properties:
                      mediaId:
                        type: string
                        description: Cover media record ID
                        example: 665f8a1b2c3d4e5f6a7b8c9d
                      url:
                        type: string
                        format: uri
                        description: Public JPEG URL — set as platformSettings.instagram.coverUrl via update-post
                        example: https://media.publora.com/images/665f...-reel-cover.jpg
                  message:
                    type: string
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                missingPostGroupId:
                  value:
                    error: postGroupId is required
                invalidPostGroupId:
                  value:
                    error: Invalid postGroupId
                missingFile:
                  value:
                    error: cover file is required
                badType:
                  value:
                    error: Instagram covers must be JPEG, PNG, or WebP images
                tooLarge:
                  value:
                    error: Instagram covers must be 8 MB or smaller
                tooLargeAfterTranscode:
                  value:
                    error: Instagram cover exceeds 8 MB after JPEG conversion; use a smaller image
                nonEditable:
                  value:
                    error: Cannot upload Instagram cover for a non-editable post
        '401':
          description: Invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Post group not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Post group not found
        '409':
          description: Post group is currently publishing
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Post group is currently being published; cannot upload Instagram cover. Retry once publishing completes.
        '500':
          description: Server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Failed to upload Instagram cover
  /upload-youtube-thumbnail:
    parameters:
    - $ref: '#/components/parameters/XPubloraClient'
    post:
      summary: Upload a custom YouTube video thumbnail
      description: 'Upload a custom thumbnail for a YouTube video post. The image is stored

        as Publora-tracked media and a mediaId + url are returned; attach them

        via platformSettings.youtube.thumbnail on update-post. A thumbnail

        cannot be set on create-post — the upload requires an existing

        postGroupId (draft or scheduled) that is not currently publishing.

        JPEG or PNG, 2 MB max, minimum 640x360 px (1280x720 recommended).'
      operationId: uploadYouTubeThumbnail
      tags:
      - Media
      parameters:
      - name: x-publora-user-id
        in: header
        required: false
        description: Managed user ID (workspace only)
        schema:
          type: string
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
              - thumbnail
              - postGroupId
              properties:
                thumbnail:
                  type: string
                  format: binary
                  description: Thumbnail image (JPEG or PNG; 2 MB max; min 640x360 px, 1280x720 recommended).
                postGroupId:
                  type: string
                  description: Editable post group (draft or scheduled) to attach the thumbnail to
                  example: 507f1f77bcf86cd799439011
      responses:
        '200':
          description: Thumbnail uploaded
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  thumbnail:
                    type: object
                    properties:
                      mediaId:
                        type: string
                        description: Thumbnail media record ID — set as platformSettings.youtube.thumbnail.mediaId via update-post
                        example: 665f8a1b2c3d4e5f6a7b8c9d
                      url:
                        type: string
                        format: uri
                        description: Public thumbnail URL — set as platformSettings.youtube.thumbnail.url via update-post
                        example: https://media.publora.com/images/665f...-thumb.jpg
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                missingPostGroupId:
                  value:
                    error: postGroupId is required
                invalidPostGroupId:
                  value:
                    error: Invalid postGroupId
                missingFile:
                  value:
                    error: thumbnail file is required
                badType:
                  value:
                    error: YouTube thumbnails must be JPEG or PNG images
                tooLarge:
                  value:
                    error: YouTube thumbnails must be 2 MB or smaller
                tooSmall:
                  value:
                    error: YouTube thumbnails must be at least 640x360 pixels
                nonEditable:
                  value:
                    error: Cannot upload YouTube thumbnail for a non-editable post
        '401':
          description: Invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Post group not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Post group not found
        '409':
          description: Post group is currently publishing
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Post group is currently being published; cannot upload YouTube thumbnail. Retry once publishing completes.
        '500':
          description: Server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Failed to upload YouTube thumbnail
components:
  parameters:
    XPubloraClient:
      name: x-publora-client
      in: header
      required: false
      description: Optional client identifier accepted by every API-key-authenticated operation. Any non-empty value is preserved; `api` is used when absent. Setting `mcp` triggers the MCP access entitlement check.
      schema:
        type: string
  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
          description: Human-readable message. Do not match on this string — match on code where present.
          example: Invalid API key
        code:
          type: string
          description: 'Stable machine-readable error code. Present on the newer error paths

            (scheduling, platformSettings validation, idempotency); older errors

            return `error` only. Always prefer this over the `error` text.

            '
          example: SCHEDULED_TIME_IN_PAST
        field:
          type: string
          description: '`PLATFORM_SETTING_UNKNOWN` only. The exact dotted path of the rejected

            key, relative to the `platformSettings` object (no `platformSettings.`

            prefix).

            '
          example: youtube.thumbnail.typo
        serverTime:
          type: string
          format: date-time
          description: '`SCHEDULED_TIME_IN_PAST` only. Current server time (UTC) when the

            request was rejected — compare against your clock to diagnose skew.

            '
          example: '2026-03-01T14:02:11.412Z'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-publora-key
      description: 'API key from Settings > API Keys. Format: sk_timestamp.hexstring'