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

# Create a post

> Turn finished media into a post for one creator. It is created at **`pending_review`**
— the review gate's entry state. Nothing is public yet; it appears in the studio's
review queue like any other post.

`channels` defaults to that creator's CONNECTED channels, so the common case is just
`account_id`, `asset_ids` and `caption`. The format (video / carousel / photo) is derived
from the media and validated against every target platform before the post is written.



## OpenAPI

````yaml /openapi.json post /v1/clips
openapi: 3.1.0
info:
  title: Creatorline API
  version: 1.0.0
  description: >-
    Generate AI influencer photos and videos, and publish them to your creators'
    social

    accounts — from your own backend, your scripts, or a coding agent.


    Every request authenticates with an organization-scoped API key and is
    charged against

    that organization's credits, at the same prices the studio shows.
servers:
  - url: https://api.creatorline.io
    description: Production
  - url: http://localhost:3000/api
    description: Local development (the same routes, under the app's own /api prefix)
security:
  - bearerAuth: []
  - apiKeyHeader: []
tags:
  - name: Account
    description: Who the key belongs to, and what it can spend.
  - name: Catalog
    description: The live tool and model catalog. Read it, do not hardcode it.
  - name: Creators
    description: The AI creators a generation or post belongs to.
  - name: Generations
    description: Start, price and poll image and video runs.
  - name: Assets
    description: The media library, and uploading your own files.
  - name: Posts
    description: Turn media into a post and publish it to social platforms.
  - name: Credits
    description: Balance and the consumption ledger.
paths:
  /v1/clips:
    post:
      tags:
        - Posts
      summary: Create a post
      description: >-
        Turn finished media into a post for one creator. It is created at
        **`pending_review`**

        — the review gate's entry state. Nothing is public yet; it appears in
        the studio's

        review queue like any other post.


        `channels` defaults to that creator's CONNECTED channels, so the common
        case is just

        `account_id`, `asset_ids` and `caption`. The format (video / carousel /
        photo) is derived

        from the media and validated against every target platform before the
        post is written.
      operationId: createClip
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateClipRequest'
            example:
              account_id: e307923d-bc66-4959-a297-6e230b93dc22
              asset_ids:
                - 9b2f7c10-4f3a-4a2b-9f10-77c3d2e1a8b4
              caption: morning ritual ☕️
              hashtags:
                - skincare
                - grwm
      responses:
        '201':
          description: The post, awaiting review.
          headers:
            x-request-id:
              description: >-
                Correlation id for this request. Quote it in any support
                question.
              schema:
                type: string
            x-ratelimit-limit:
              description: Requests allowed per minute.
              schema:
                type: integer
            x-ratelimit-remaining:
              description: Requests left in the current window.
              schema:
                type: integer
            x-ratelimit-reset:
              description: Unix seconds when the window resets.
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Clip'
        '400':
          description: Invalid request. `param` names the offending field.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  type: invalid_request_error
                  code: invalid_parameter
                  message: >-
                    This creator has no connected channels. Connect one in the
                    studio, or pass `channels` explicitly.
                  param: channels
                request_id: req_8fQ2mRxK1pLd
        '401':
          description: Missing, malformed, revoked or expired key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  type: authentication_error
                  code: invalid_api_key
                  message: Missing or invalid API key.
                request_id: req_8fQ2mRxK1pLd
        '403':
          description: The key exists but may not do this (read-only key).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  type: permission_error
                  code: insufficient_scope
                  message: >-
                    This API key is read-only. Create a key with the `write`
                    scope to run generations.
                request_id: req_8fQ2mRxK1pLd
        '404':
          description: No such resource — including one that belongs to another workspace.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  type: not_found_error
                  code: resource_missing
                  message: No such generation.
                request_id: req_8fQ2mRxK1pLd
components:
  schemas:
    CreateClipRequest:
      type: object
      properties:
        account_id:
          type: string
          format: uuid
        asset_ids:
          type: array
          items:
            type: string
            format: uuid
          minItems: 1
          maxItems: 10
          description: Media, in post order.
        caption:
          type: string
        hashtags:
          type: array
          items:
            type: string
          description: >-
            Bare tag words, without the `#`. Appended to the caption when the
            post is sent.
        title:
          type: string
        channels:
          type: array
          items:
            type: string
            enum:
              - IG
              - TikTok
              - YouTube
              - Telegram
          description: Defaults to the creator's connected channels.
        scheduled_for:
          type: string
          description: Target time as "HH:mm".
        format:
          type: string
          enum:
            - photo
            - video
            - carousel
          description: Derived from the assets when omitted.
        timezone:
          type: string
          description: IANA zone the schedule is read in, e.g. "Europe/Istanbul".
        draft:
          type: boolean
          description: >-
            Hand the post to TikTok's Creator Inbox as a draft the creator
            finishes in the app instead of publishing it live. TikTok-only:
            rejected if any other channel is targeted.
        made_with_ai:
          type: boolean
          description: TikTok's AI-disclosure flag.
        auto_add_music:
          type: boolean
          description: 'TikTok photo carousels: let TikTok add a soundtrack. On by default.'
        photo_cover_index:
          type: integer
          minimum: 0
          description: >-
            TikTok photo carousels: which image is the cover, 0-based into
            asset_ids.
        platform_settings:
          type: object
          description: >-
            Per-platform overrides, keyed by channel. Every key must name a
            channel this post targets, and an unrecognised setting is rejected
            rather than silently dropped.
          additionalProperties:
            type: object
            properties:
              caption:
                type: string
                description: Replaces the shared caption on this platform.
              scheduled_for:
                type: string
                description: Replaces the shared time on this platform.
              title:
                type: string
                description: YouTube only.
              visibility:
                type: string
                enum:
                  - public
                  - unlisted
                  - private
                description: YouTube only.
            additionalProperties: false
      required:
        - account_id
        - asset_ids
    Clip:
      type: object
      properties:
        object:
          type: string
          enum:
            - clip
        id:
          type: string
          format: uuid
        status:
          type: string
          enum:
            - pending_review
            - approved
            - scheduled
            - published
            - draft_sent
            - failed
            - rejected
        title:
          type: string
        format:
          type: string
          enum:
            - photo
            - video
            - carousel
        ratio:
          type: string
        caption:
          type: string
        hashtags:
          type: array
          items:
            type: string
        channels:
          type: array
          items:
            type: string
        scheduled_for:
          type: string
        published_at:
          type: string
        created_at:
          type: number
        duration_sec:
          type: number
        account_id:
          type: string
          format: uuid
        error:
          type: string
        channel_posts:
          type: array
          description: Per-platform publish state, filled in as each platform confirms.
          items:
            type: object
            properties:
              platform:
                type: string
              status:
                type: string
              url:
                type: string
                format: uri
              error:
                type: string
        asset_ids:
          type: array
          items:
            type: string
            format: uuid
        timezone:
          type: string
        draft:
          type: boolean
        made_with_ai:
          type: boolean
        auto_add_music:
          type: boolean
        photo_cover_index:
          type: integer
        platform_settings:
          type: object
          description: >-
            Per-platform overrides, keyed by channel. Every key must name a
            channel this post targets, and an unrecognised setting is rejected
            rather than silently dropped.
          additionalProperties:
            type: object
            properties:
              caption:
                type: string
                description: Replaces the shared caption on this platform.
              scheduled_for:
                type: string
                description: Replaces the shared time on this platform.
              title:
                type: string
                description: YouTube only.
              visibility:
                type: string
                enum:
                  - public
                  - unlisted
                  - private
                description: YouTube only.
            additionalProperties: false
      required:
        - object
        - id
        - status
        - asset_ids
    Error:
      type: object
      description: >-
        Every failure has this shape. `param` names the offending field when
        there is one.
      properties:
        error:
          type: object
          properties:
            type:
              type: string
              enum:
                - invalid_request_error
                - authentication_error
                - permission_error
                - not_found_error
                - rate_limit_error
                - insufficient_credits_error
                - api_error
            code:
              type: string
            message:
              type: string
            param:
              type: string
          required:
            - type
            - code
            - message
        request_id:
          type: string
        required_credits:
          type: number
          description: 402 only.
        credit_balance:
          type: number
          description: 402 only.
      required:
        - error
        - request_id
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Your organization's API key, from Settings → API. `Authorization: Bearer
        crl_sk_live_…`
    apiKeyHeader:
      type: apiKey
      in: header
      name: X-API-Key
      description: Alternative to the Authorization header, for tooling that prefers it.

````

## Related topics

- [MCP server](/mcp.md)
- [Publishing](/publishing.md)
- [CLI](/cli.md)
- [Publish a post](/api-reference/posts/publish-a-post.md)
- [List posts](/api-reference/posts/list-posts.md)
