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

# Create Post

> **Availability: pending.** This endpoint is specified ahead of implementation and is not yet live on the hosted API; it ships through recoupable/app#2241. Do not rely on it until this notice is removed.

Publish a video with its copy to **one** connected social account, now or at a set time. Send one request per target account; to post the same video to several platforms, call this once per platform.

Without `publish_at` the post starts publishing immediately and is returned as `publishing`. With `publish_at` it is returned as `scheduled` and publishes at that time. Either way this returns **202** right away: poll [Get Post](/api-reference/publishing/get) until `status` is `posted`, `failed` or `cancelled`.

The platform must already be connected for the account (see [Authorize Connector](/api-reference/connectors/authorize)). Copy uses one shape for every platform. Which fields each platform uses, and their limits:

| Platform | `title` | `description` | `cover_url` | `privacy`, `tags` |
|---|---|---|---|---|
| `youtube` | **required**, video title, max 100 characters | video description, max 5,000 characters | not used (YouTube picks the frame) | used |
| `instagram` | not used | **required**, Reel caption, max 2,200 characters | Reel cover image | not used |
| `x` | not used | **required**, post text, max 280 weighted characters (URLs count as 23) | not used | not used |
| `linkedin` | video title shown on the post | **required**, post commentary, max 3,000 characters | video thumbnail | not used |

Limits are checked here, so an over-length body fails with 400 instead of at publish time.



## OpenAPI

````yaml api-reference/openapi/social.json POST /api/posts
openapi: 3.1.0
info:
  title: Recoup API - Social
  description: >-
    API documentation for the Recoup platform - an AI agent platform for the
    music industry
  license:
    name: MIT
  version: 1.0.0
servers:
  - url: https://api.recoupable.dev
security: []
paths:
  /api/posts:
    post:
      summary: Create post
      description: >-
        **Availability: pending.** This endpoint is specified ahead of
        implementation and is not yet live on the hosted API; it ships through
        recoupable/app#2241. Do not rely on it until this notice is removed.


        Publish a video with its copy to **one** connected social account, now
        or at a set time. Send one request per target account; to post the same
        video to several platforms, call this once per platform.


        Without `publish_at` the post starts publishing immediately and is
        returned as `publishing`. With `publish_at` it is returned as
        `scheduled` and publishes at that time. Either way this returns **202**
        right away: poll [Get Post](/api-reference/publishing/get) until
        `status` is `posted`, `failed` or `cancelled`.


        The platform must already be connected for the account (see [Authorize
        Connector](/api-reference/connectors/authorize)). Copy uses one shape
        for every platform. Which fields each platform uses, and their limits:


        | Platform | `title` | `description` | `cover_url` | `privacy`, `tags` |

        |---|---|---|---|---|

        | `youtube` | **required**, video title, max 100 characters | video
        description, max 5,000 characters | not used (YouTube picks the frame) |
        used |

        | `instagram` | not used | **required**, Reel caption, max 2,200
        characters | Reel cover image | not used |

        | `x` | not used | **required**, post text, max 280 weighted characters
        (URLs count as 23) | not used | not used |

        | `linkedin` | video title shown on the post | **required**, post
        commentary, max 3,000 characters | video thumbnail | not used |


        Limits are checked here, so an over-length body fails with 400 instead
        of at publish time.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePostRequest'
      responses:
        '202':
          description: 'Post accepted: publishing now, or scheduled for `publish_at`.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreatePostResponse'
          headers:
            Location:
              schema:
                type: string
              description: URL of the created post.
        '400':
          description: >-
            Validation failed: a missing or unknown field, a field the platform
            requires (YouTube `title`; Instagram, X and LinkedIn `description`),
            a body over the platform's limit, or a `publish_at` in the past.
            `missing_fields` names the first offending field.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PostErrorResponse'
        '401':
          description: >-
            Unauthorized. Provide exactly one of `x-api-key` or `Authorization:
            Bearer`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PostErrorResponse'
        '403':
          description: Access denied to the specified `account_id`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PostErrorResponse'
        '409':
          description: >-
            The `platform` is not connected for this account. Authorize it via
            [Authorize Connector](/api-reference/connectors/authorize) before
            retrying.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PostErrorResponse'
        '500':
          description: Internal server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PostErrorResponse'
      security:
        - apiKeyAuth: []
        - bearerAuth: []
components:
  schemas:
    CreatePostRequest:
      type: object
      required:
        - platform
        - video_url
      description: >-
        One post to one connected account. Copy uses the same fields for every
        platform; see the operation description for which fields each platform
        uses and their limits.
      properties:
        account_id:
          type: string
          format: uuid
          description: >-
            Optional. The account whose connection posts (e.g. an artist). The
            authenticated account must have access. Defaults to the calling
            account.
        platform:
          $ref: '#/components/schemas/PostPlatform'
        sub_account_id:
          type: string
          description: >-
            Optional, LinkedIn only. Organization URN to post as a Page (e.g.
            `urn:li:organization:101127186`) instead of as the connected member.
            The connected member must be an admin of that Page.
        video_url:
          type: string
          format: uri
          description: >-
            Publicly reachable URL of the video file (MP4). It is fetched at
            publish time, so it must still resolve then.
        cover_url:
          type: string
          format: uri
          description: >-
            Optional. Publicly reachable image URL used as the cover or
            thumbnail where the platform supports one (see the table in the
            description).
        title:
          type: string
          description: Title. Required for `youtube`; see the table in the description.
        description:
          type: string
          description: >-
            Body text: caption, post text or description, depending on the
            platform. Required for `instagram`, `x` and `linkedin`.
        privacy:
          type: string
          enum:
            - public
            - unlisted
            - private
          default: public
          description: Optional, YouTube only. Visibility after upload.
        tags:
          type: array
          items:
            type: string
          description: Optional, YouTube only. Video tags.
        publish_at:
          type: string
          format: date-time
          description: >-
            Optional. ISO 8601 time to publish, in the future. Omit to publish
            now.
    CreatePostResponse:
      type: object
      required:
        - id
        - status
      description: The post's id and current status.
      properties:
        id:
          type: string
          format: uuid
          description: >-
            The post's id. Poll [Get Post](/api-reference/publishing/get) with
            this.
        status:
          $ref: '#/components/schemas/PostStatus'
    PostErrorResponse:
      type: object
      required:
        - status
        - error
      properties:
        status:
          type: string
          enum:
            - error
          description: Always `error`
        missing_fields:
          type: array
          description: >-
            JSON path segments to the first field that failed validation, e.g.
            `["description"]`
          items:
            oneOf:
              - type: string
              - type: integer
        error:
          type: string
          description: Human-readable error message
    PostPlatform:
      type: string
      enum:
        - instagram
        - x
        - linkedin
        - youtube
      description: Target platform. The account must have this platform connected.
    PostStatus:
      type: string
      enum:
        - scheduled
        - publishing
        - posted
        - failed
        - cancelled
      description: >-
        Lifecycle phase. `scheduled` until `publish_at`, `publishing` while the
        platform upload runs, then `posted` or `failed`. `cancelled` only from
        `scheduled`.
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: Your Recoup API key. [Learn more](/quickstart#api-keys).
    bearerAuth:
      type: http
      scheme: bearer

````

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