PosteAhora Posts API

The Posts API from PosteAhora — 3 operation(s) for posts.

Operations 6

GET /posts List posts #
POST /posts Create a draft, schedule, or publish now (controlled by status) #
GET /posts/{id} Read one post (includes connected_account_id and platform_results) #
PATCH /posts/{id} Edit a draft or scheduled post (only sent fields are touched) #
DELETE /posts/{id} Soft-delete a post #
POST /posts/{id}/publish Publish an existing draft/scheduled post immediately #

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/posteahora-posts-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

posteahora-posts-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: PosteAhora Public Posts API
  version: 1.0.0
  description: 'Key-authenticated REST gateway over the same publishing pipeline as the PosteAhora web app. It powers the MCP server, the CLI, the n8n node, and any third-party integration. This is the frozen **v1** contract: additive changes only.


    Human-readable docs: https://posteahora.com/docs/api'
  contact:
    name: PosteAhora
    url: https://posteahora.com/docs/api
servers:
- url: https://api.posteahora.com/functions/v1/api
  description: Production. The /functions/v1/ segment is part of the stable URL — do not strip it.
security:
- ApiKey: []
tags:
- name: Posts
paths:
  /posts:
    get:
      tags:
      - Posts
      summary: List posts
      parameters:
      - name: status
        in: query
        schema:
          type: string
          enum:
          - draft
          - scheduled
          - queued
          - published
          - partial_published
          - failed
      - name: limit
        in: query
        schema:
          type: integer
          default: 50
          maximum: 200
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  posts:
                    type: array
                    items:
                      $ref: '#/components/schemas/Post'
      operationId: getPosts
      x-operation-id-source: derived
    post:
      tags:
      - Posts
      summary: Create a draft, schedule, or publish now (controlled by status)
      description: Multi-platform posts fan out into one row per platform at publish time. Publishing is asynchronous — a "published" create returns status "queued"; poll GET /posts/{id} and read platform_results.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePostRequest'
            examples:
              multiPlatformVideo:
                summary: One video → YouTube Shorts + TikTok + Instagram Reels, per-platform metadata
                value:
                  caption: Fallback text if a platform override is missing
                  mediaUrls:
                  - https://cdn.posteahora.com/…/clip.mp4
                  mediaType: video
                  postType: reel
                  status: published
                  accountMappings:
                  - platform: youtube
                    accountId: <yt-account-id>
                  - platform: tiktok
                    accountId: <tt-account-id>
                  - platform: instagram
                    accountId: <ig-account-id>
                  platformCaptions:
                    youtube: Full YouTube description — links, timestamps, etc.
                    tiktok: 'TikTok caption #fyp'
                    instagram: Reel caption for IG ✨
                  platformOptions:
                    youtube:
                      title: My video title
                      categoryId: '22'
                      madeForKids: false
                      privacyStatus: public
                      tags:
                      - demo
                      - api
                    tiktok:
                      privacyLevel: PUBLIC_TO_EVERYONE
                      disableComment: false
                      brandContentToggle: false
                      brandOrganicToggle: false
                      isAigc: false
                    instagram:
                      shareToFeed: true
                      coverUrl: https://cdn.posteahora.com/…/cover.jpg
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreatePostResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '402':
          description: Monthly post quota reached
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          $ref: '#/components/responses/Forbidden'
      operationId: postPosts
      x-operation-id-source: derived
  /posts/{id}:
    parameters:
    - $ref: '#/components/parameters/Id'
    get:
      tags:
      - Posts
      summary: Read one post (includes connected_account_id and platform_results)
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  post:
                    $ref: '#/components/schemas/Post'
        '404':
          $ref: '#/components/responses/NotFound'
      operationId: getPostsById
      x-operation-id-source: derived
    patch:
      tags:
      - Posts
      summary: Edit a draft or scheduled post (only sent fields are touched)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdatePostRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  post:
                    $ref: '#/components/schemas/Post'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
      operationId: patchPostsById
      x-operation-id-source: derived
    delete:
      tags:
      - Posts
      summary: Soft-delete a post
      responses:
        '200':
          $ref: '#/components/responses/Deleted'
        '404':
          $ref: '#/components/responses/NotFound'
      operationId: deletePostsById
      x-operation-id-source: derived
  /posts/{id}/publish:
    parameters:
    - $ref: '#/components/parameters/Id'
    post:
      tags:
      - Posts
      summary: Publish an existing draft/scheduled post immediately
      description: Enters the async pipeline. Poll GET /posts/{id} for platform_results.
      responses:
        '200':
          description: Queued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreatePostResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
      operationId: postPostsByIdPublish
      x-operation-id-source: derived
components:
  parameters:
    Id:
      name: id
      in: path
      required: true
      schema:
        type: string
        format: uuid
  schemas:
    AccountMapping:
      type: object
      properties:
        platform:
          type: string
          example: youtube
        accountId:
          type: string
          description: connected_accounts.id. Required for every network except a few that don't need account selection.
      required:
      - platform
    DiscordOptions:
      type: object
      properties:
        channelId:
          type: string
    UpdatePostRequest:
      type: object
      description: Edit a draft or scheduled post. Only sent fields are touched.
      properties:
        title:
          type: string
        caption:
          type: string
        hashtags:
          type: array
          items:
            type: string
        mediaUrls:
          type: array
          items:
            type: string
            format: uri
        mediaType:
          type: string
          enum:
          - image
          - video
        postType:
          type: string
          enum:
          - post
          - reel
          - story
        platforms:
          type: array
          items:
            type: string
        connectedAccountId:
          type: string
        platformOptions:
          $ref: '#/components/schemas/PlatformOptions'
        status:
          type: string
          enum:
          - draft
          - scheduled
        scheduledAt:
          type: string
          format: date-time
    Post:
      type: object
      properties:
        id:
          type: string
          format: uuid
        title:
          type:
          - string
          - 'null'
        caption:
          type:
          - string
          - 'null'
        platforms:
          type: array
          items:
            type: string
        status:
          type: string
          enum:
          - draft
          - scheduled
          - queued
          - published
          - partial_published
          - failed
        scheduled_at:
          type:
          - string
          - 'null'
          format: date-time
        published_at:
          type:
          - string
          - 'null'
          format: date-time
        media_urls:
          type: array
          items:
            type: string
            format: uri
        media_type:
          type:
          - string
          - 'null'
          enum:
          - image
          - video
          - null
        connected_account_id:
          type:
          - string
          - 'null'
          format: uuid
        platform_results:
          type: array
          items:
            $ref: '#/components/schemas/PlatformResult'
        created_at:
          type: string
          format: date-time
    PlatformOptions:
      type: object
      description: Per-network settings, keyed by platform id.
      properties:
        youtube:
          $ref: '#/components/schemas/YouTubeOptions'
        tiktok:
          $ref: '#/components/schemas/TikTokOptions'
        instagram:
          $ref: '#/components/schemas/InstagramOptions'
        threads:
          $ref: '#/components/schemas/ThreadsOptions'
        bluesky:
          $ref: '#/components/schemas/BlueskyOptions'
        mastodon:
          $ref: '#/components/schemas/MastodonOptions'
        telegram:
          $ref: '#/components/schemas/TelegramOptions'
        discord:
          $ref: '#/components/schemas/DiscordOptions'
        pinterest:
          $ref: '#/components/schemas/PinterestOptions'
      additionalProperties: true
    PlatformResult:
      type: object
      properties:
        platform:
          type: string
        success:
          type: boolean
        error:
          type: string
        remote_post_id:
          type: string
        remote_publish_id:
          type: string
        remote_permalink:
          type: string
          format: uri
      required:
      - platform
      - success
    Error:
      type: object
      properties:
        error:
          type: string
      required:
      - error
    PinterestOptions:
      type: object
      description: boardId is REQUIRED and validated on create (400 without it). A Pin needs at least one image; 2–5 images make a carousel.
      required:
      - boardId
      properties:
        boardId:
          type: string
          description: Board id from GET /accounts/{id}/boards
        boardName:
          type: string
          description: Display only
        title:
          type: string
          maxLength: 100
        link:
          type: string
          format: uri
        altText:
          type: string
          maxLength: 500
        coverUrl:
          type: string
          format: uri
          description: 'Video Pins: 2:3 cover image URL'
        thumbOffsetMs:
          type: integer
          minimum: 0
          description: 'Video Pins: keyframe used as cover when coverUrl is absent (ms)'
    ThreadsOptions:
      type: object
      properties:
        replyControl:
          type: string
          enum:
          - everyone
          - accounts_you_follow
          - mentioned_only
          - parent_post_author_only
          - followers_only
        topic:
          type: string
        altText:
          type: string
        linkAttachment:
          type: string
          format: uri
        quotePostId:
          type: string
        locationId:
          type: string
        allowlistedCountryCodes:
          type: array
          items:
            type: string
        chainItems:
          type: array
          items:
            type: object
            properties:
              text:
                type: string
              mediaUrl:
                type: string
                format: uri
              mediaType:
                type: string
                enum:
                - image
                - video
              altText:
                type: string
            required:
            - text
    CreatePostResult:
      type: object
      properties:
        postIds:
          type: array
          items:
            type: string
            format: uuid
        status:
          type: string
          enum:
          - draft
          - scheduled
          - queued
        dispatchDeferred:
          type: boolean
          description: When true, rows are stored but the worker wasn't reached synchronously; the cron sweep will publish them.
    YouTubeOptions:
      type: object
      description: 'The video description is the post caption (platformCaptions.youtube, ≤5000 chars). The video title is the required `title` field. There is no "Shorts" flag — a vertical clip ≤3 min is auto-classified as a Short.

        '
      properties:
        title:
          type: string
          maxLength: 100
        categoryId:
          type: string
          example: '22'
        madeForKids:
          type: boolean
        privacyStatus:
          type: string
          enum:
          - public
          - unlisted
          - private
          default: private
        tags:
          type: array
          items:
            type: string
        defaultLanguage:
          type: string
        containsSyntheticMedia:
          type: boolean
        embeddable:
          type: boolean
        publicStatsViewable:
          type: boolean
        license:
          type: string
          enum:
          - youtube
          - creativeCommon
        thumbnailUrl:
          type: string
          format: uri
      required:
      - title
      - categoryId
      - madeForKids
    CreatePostRequest:
      type: object
      properties:
        title:
          type: string
        caption:
          type: string
          description: Shared caption. Per-network override via platformCaptions.
        accountMappings:
          type: array
          items:
            $ref: '#/components/schemas/AccountMapping'
          description: Canonical channel selection. Prefer this over platforms+accountId.
        platforms:
          type: array
          items:
            type: string
          description: Convenience form for a single-channel post (combine with accountId).
        accountId:
          type: string
          description: Used only with the platforms convenience form.
        mediaUrls:
          type: array
          items:
            type: string
            format: uri
        mediaType:
          type: string
          enum:
          - image
          - video
        postType:
          type: string
          enum:
          - post
          - reel
          - story
          default: post
        hashtags:
          type: array
          items:
            type: string
        platformCaptions:
          type: object
          additionalProperties:
            type: string
          description: Per-platform caption/description override, keyed by platform id.
        platformOptions:
          $ref: '#/components/schemas/PlatformOptions'
        status:
          type: string
          enum:
          - draft
          - scheduled
          - published
          default: draft
        scheduledAt:
          type: string
          format: date-time
          description: Required (and must be in the future) when status = scheduled.
      required:
      - accountMappings
    InstagramOptions:
      type: object
      description: Set postType "reel" (top level) for a Reel, "story" for a Story.
      properties:
        shareToFeed:
          type: boolean
        coverUrl:
          type: string
          format: uri
        thumbOffsetMs:
          type: number
        audioName:
          type: string
        collaborators:
          type: array
          items:
            type: string
        locationId:
          type: string
        userTags:
          type: array
          items:
            type: object
            properties:
              username:
                type: string
              x:
                type: number
              y:
                type: number
            required:
            - username
        altText:
          type: string
        isAiGenerated:
          type: boolean
        isTrialReel:
          type: boolean
          description: reel only
        trialGraduationStrategy:
          type: string
          enum:
          - MANUAL
          - SS_PERFORMANCE
          description: reel only
    TikTokOptions:
      type: object
      properties:
        privacyLevel:
          type: string
          enum:
          - PUBLIC_TO_EVERYONE
          - MUTUAL_FOLLOW_FRIENDS
          - FOLLOWER_OF_CREATOR
          - SELF_ONLY
        disableComment:
          type: boolean
        brandContentToggle:
          type: boolean
        brandOrganicToggle:
          type: boolean
        isAigc:
          type: boolean
        postMode:
          type: string
          enum:
          - DIRECT_POST
          - MEDIA_UPLOAD
          default: DIRECT_POST
        disableDuet:
          type: boolean
          description: video only
        disableStitch:
          type: boolean
          description: video only
        videoCoverTimestampMs:
          type: number
          description: video only
        autoAddMusic:
          type: boolean
          description: photo only
        photoCoverIndex:
          type: number
          description: photo only
        photoTitle:
          type: string
          maxLength: 90
          description: photo only
      required:
      - privacyLevel
      - disableComment
      - brandContentToggle
      - brandOrganicToggle
      - isAigc
    TelegramOptions:
      type: object
      properties:
        disableNotification:
          type: boolean
        protectContent:
          type: boolean
    MastodonOptions:
      type: object
      properties:
        visibility:
          type: string
          enum:
          - public
          - unlisted
          - private
          - direct
        spoilerText:
          type: string
        sensitive:
          type: boolean
        language:
          type: string
    BlueskyOptions:
      type: object
      properties:
        langs:
          type: array
          items:
            type: string
  responses:
    Deleted:
      description: Deleted
      content:
        application/json:
          schema:
            type: object
            properties:
              id:
                type: string
              deleted:
                type: boolean
    Forbidden:
      description: Key lacks the required scope (or viewer-role key attempting a write)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    BadRequest:
      description: Invalid request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: Resource not found (or not in the key's workspace)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    ApiKey:
      type: http
      scheme: bearer
      description: 'A PosteAhora API key: `Authorization: Bearer pah_live_…` (or `pah_test_…`). Keys are created in the app under /api and carry scopes (ideas:read/write, posts:read/write, analytics:read, accounts:read, media:write). A missing scope returns 403.

        '