> ## Documentation Index
> Fetch the complete documentation index at: https://docs.postonce.to/llms.txt
> Use this file to discover all available pages before exploring further.

# Create post

> Creates one logical post that can target multiple connected accounts. Include `publish_at` to schedule it instead of sending immediately.



## OpenAPI

````yaml /openapi/public-api.yaml post /v1/posts
openapi: 3.1.0
info:
  title: PostOnce Public API
  version: 1.0.0-alpha
  description: Public API for PostOnce paid users
servers:
  - url: https://postonce.to/api/public
security:
  - bearerAuth: []
paths:
  /v1/posts:
    post:
      summary: Create post
      description: >-
        Creates one logical post that can target multiple connected accounts.
        Include `publish_at` to schedule it instead of sending immediately.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - targets
              properties:
                content:
                  type: string
                  example: Shipping the public API today.
                external_id:
                  type: string
                  nullable: true
                  example: launch-001
                external_user_id:
                  type: string
                  nullable: true
                  description: >-
                    Partner accounts only. Every target must belong to this end
                    user, otherwise the request fails with 403
                    account_not_owned_by_user.
                media:
                  type: array
                  items:
                    $ref: '#/components/schemas/MediaInput'
                publish_at:
                  type: string
                  format: date-time
                  nullable: true
                  example: '2026-04-01T14:00:00.000Z'
                targets:
                  type: array
                  items:
                    $ref: '#/components/schemas/PostTargetInput'
            examples:
              immediate:
                value:
                  content: Shipping the public API today.
                  external_id: launch-001
                  targets:
                    - account_id: account-1
                    - account_id: account-2
                      content_override: Shorter version for X
              mediaSingle:
                value:
                  content: Launching with a hero image.
                  media:
                    - url: https://cdn.example.com/launch-image.png
                      type: image
                      width: 1200
                      height: 630
                  targets:
                    - account_id: account-1
              mediaMultiple:
                value:
                  content: Carousel post with multiple images.
                  media:
                    - url: https://cdn.example.com/carousel-1.png
                      type: image
                    - url: https://cdn.example.com/carousel-2.png
                      type: image
                    - url: https://cdn.example.com/carousel-3.png
                      type: image
                  targets:
                    - account_id: account-1
              perTargetCustomization:
                value:
                  content: Shipping the public API today.
                  targets:
                    - account_id: twitter-account-id
                      content_override: Shipping today. API is live.
                    - account_id: linkedin-account-id
                      platform_options:
                        title: Public API launch
              scheduled:
                value:
                  content: Scheduled launch note
                  publish_at: '2026-04-01T14:00:00.000Z'
                  targets:
                    - account_id: account-1
              aiGeneratedDisclosure:
                value:
                  content: An AI-generated launch video
                  media:
                    - url: https://cdn.example.com/launch-video.mp4
                      type: video
                  targets:
                    - account_id: tiktok-account-id
                      platform_options:
                        ai_generated: true
                    - account_id: youtube-account-id
                      platform_options:
                        ai_generated: true
                    - account_id: instagram-account-id
                      platform_options:
                        ai_generated: true
              videoCover:
                value:
                  content: New episode is live
                  media:
                    - url: https://cdn.example.com/episode.mp4
                      type: video
                      thumbnail_url: https://cdn.example.com/episode-cover.jpg
                  targets:
                    - account_id: instagram-account-id
                    - account_id: facebook-account-id
                    - account_id: tiktok-account-id
              tiktokDraft:
                value:
                  content: Finish this caption in TikTok
                  media:
                    - url: https://cdn.example.com/video.mp4
                      type: video
                  targets:
                    - account_id: tiktok-account-id
                      platform_options:
                        publish_mode: draft
      responses:
        '201':
          description: Post created successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Post'
        '400':
          description: One or more target accounts are invalid or inactive.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Missing, invalid, revoked, or expired API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthErrorResponse'
components:
  schemas:
    MediaInput:
      type: object
      required:
        - url
      properties:
        url:
          type: string
          description: >-
            Required absolute HTTP or HTTPS media URL. Surrounding whitespace is
            trimmed. Invalid URLs reject the entire request with invalid_media;
            URL contents are not fetched during validation.
          example: https://cdn.example.com/launch-image.png
        type:
          type: string
          enum:
            - image
            - video
          example: image
        width:
          type: integer
        height:
          type: integer
        size:
          type: integer
        duration:
          type: number
          description: Video duration in seconds when known.
        thumbnail_url:
          type: string
          description: >-
            Cover image URL for video media (JPEG or PNG, 8 MB or less). It is
            applied as the video cover on Instagram Reels and Stories, Facebook
            Reels, and TikTok (inserted as the video's first frame), and is also
            used in scheduled and published post previews.
    PostTargetInput:
      type: object
      required:
        - account_id
      properties:
        account_id:
          type: string
        content_override:
          type: string
          nullable: true
        platform_options:
          type: object
          additionalProperties: true
          nullable: true
          properties:
            ai_generated:
              type: boolean
              description: >-
                Requests the target platform's native AI-generated or
                synthetic-media disclosure. Supported for TikTok direct videos,
                YouTube videos, and Instagram media. Facebook Page publishing
                does not currently expose an equivalent API field.
            channel_id:
              type: string
              description: Farcaster channel ID for the cast.
            video_cover_timestamp_ms:
              type: integer
              minimum: 0
              description: >-
                TikTok direct video posts only. Selects the frame at this
                position, in milliseconds, as the video cover. When set, it
                takes precedence over media[].thumbnail_url for that TikTok
                target. Not supported for photo posts or draft uploads.
            title:
              type: string
              description: >-
                Title for platforms that support one. For Vimeo, 1-128
                characters; defaults to the first line of the content.
            privacy_view:
              type: string
              enum:
                - anybody
                - unlisted
                - nobody
                - disable
              default: anybody
              description: Vimeo only. Who can view the uploaded video.
            reply_to:
              type: object
              nullable: true
              required:
                - hash
                - author_fid
              properties:
                hash:
                  type: string
                author_fid:
                  type: integer
              description: >-
                Farcaster parent cast. Both the full cast hash and parent author
                FID are required.
            disable_notification:
              type: boolean
              description: >-
                Telegram only. Sends the channel post silently; subscribers get
                no notification sound.
            protect_content:
              type: boolean
              description: >-
                Telegram only. Prevents forwarding and saving of the channel
                post.
            disable_link_preview:
              type: boolean
              description: Telegram only. Disables the link preview on text posts.
          description: >-
            Platform-specific settings are mapped explicitly; unknown properties
            are stored but are not forwarded automatically. For Farcaster, pass
            {"channel_id":"founders"} or
            {"reply_to":{"hash":"0x...","author_fid":123}}. To request native
            AI-content disclosure on TikTok, YouTube, or Instagram, pass
            {"ai_generated":true}. Facebook Page publishing does not currently
            expose an equivalent API field. For Reddit, pass
            {"subreddit":"SideProject","title":"Launch
            title","postType":"self"}. For Snapchat, pass
            {"placements":["spotlight","public_story"],"locale":"en_US"};
            placements default to Spotlight. For a TikTok draft upload, pass
            {"publish_mode":"draft"}; the creator must finish and publish it
            from their TikTok inbox. To choose a TikTok cover frame instead of a
            cover image, pass {"video_cover_timestamp_ms":1500}. For Vimeo, pass
            {"title":"Launch video","privacy_view":"unlisted"}; privacy_view
            defaults to anybody. Telegram accepts only the disable_notification,
            protect_content, and disable_link_preview booleans and rejects other
            keys.
    Post:
      type: object
      properties:
        id:
          type: string
        content:
          type: string
        external_id:
          type: string
          nullable: true
        media:
          type: array
          items:
            $ref: '#/components/schemas/MediaInput'
        origin:
          type: string
          enum:
            - ui
            - api
            - workflow
          nullable: true
        publish_at:
          type: string
          format: date-time
          nullable: true
        status:
          type: string
          enum:
            - queued
            - scheduled
            - processing
            - partial
            - published
            - failed
            - cancelled
          example: scheduled
        created_at:
          type: string
          format: date-time
          nullable: true
        targets:
          type: array
          items:
            $ref: '#/components/schemas/PostTarget'
    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              example: workflow_limit_reached
            message:
              type: string
              example: You have reached the maximum number of workflows for your plan.
            hint:
              type: string
              description: Suggested action to resolve the error.
    AuthErrorResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              example: invalid_api_key
            message:
              type: string
              example: Invalid API key.
            hint:
              type: string
              description: Suggested action to resolve the error.
    PostTarget:
      type: object
      properties:
        target_post_id:
          type: string
        account_id:
          type: string
          nullable: true
        platform:
          type: string
          nullable: true
        target_variant:
          type: string
          enum:
            - spotlight
            - public_story
          nullable: true
          description: >-
            Concrete placement for platforms that fan one account target into
            multiple publications.
        username:
          type: string
          nullable: true
        status:
          type: string
          enum:
            - pending
            - scheduled
            - processing
            - submitted
            - published
            - failed
            - skipped
            - cancelled
          example: pending
        error:
          type: string
          nullable: true
        platform_post_id:
          type: string
          nullable: true
        platform_post_url:
          type: string
          nullable: true
        scheduled_time:
          type: string
          format: date-time
          nullable: true
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: >-
        Scoped API key issued in PostOnce Settings. OAuth authorization grants
        are not currently supported.
      x-scopes:
        accounts:read: List and read connected accounts.
        accounts:write: Connect and disconnect social accounts.
        media:read: Read uploaded media.
        media:write: Upload media.
        posts:read: Read posts and unpublished drafts.
        posts:write: Create, update, publish, cancel, retry, and delete posts and drafts.
        workflows:read: List and read crossposting workflows.
        workflows:write: Create, update, and delete crossposting workflows.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.