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

# Generate posts

> Generate social media posts from your content.

Provide text content, a website URL, or a custom idea and we'll create
visual social posts as drafts in your queue. Returns a job ID — poll
`GET /api/businesses/{business_id}/jobs/{job_id}` until status is `completed`
or `failed`.

**Rate limits:** 100 requests/minute, 2,000/day, 10,000/week; 200 posts/month per org.

Errors:
    400 missing_field: None of content, website_url, or custom_idea was given.
    400 invalid_value: The business_id is not a valid UUID.
    401 authentication_required: API key or token is missing, invalid, or revoked.
    403 permission_denied: Your plan does not include API access, or this business is not in your org.
    404 resource_not_found: No business with that ID exists.
    429 rate_limit_exceeded: You hit the per-minute rate limit or the monthly post quota.



## OpenAPI

````yaml public-openapi.json post /api/businesses/{business_id}/posts/generate
openapi: 3.1.0
info:
  title: Marky Public API
  version: '2026-04-08'
  description: Create and schedule posts, manage businesses, library, media, and webhooks.
servers:
  - url: https://api.mymarky.ai
    description: Production
security: []
paths:
  /api/businesses/{business_id}/posts/generate:
    post:
      tags:
        - public-api
      summary: Generate posts
      description: >-
        Generate social media posts from your content.


        Provide text content, a website URL, or a custom idea and we'll create

        visual social posts as drafts in your queue. Returns a job ID — poll

        `GET /api/businesses/{business_id}/jobs/{job_id}` until status is
        `completed`

        or `failed`.


        **Rate limits:** 100 requests/minute, 2,000/day, 10,000/week; 200
        posts/month per org.


        Errors:
            400 missing_field: None of content, website_url, or custom_idea was given.
            400 invalid_value: The business_id is not a valid UUID.
            401 authentication_required: API key or token is missing, invalid, or revoked.
            403 permission_denied: Your plan does not include API access, or this business is not in your org.
            404 resource_not_found: No business with that ID exists.
            429 rate_limit_exceeded: You hit the per-minute rate limit or the monthly post quota.
      operationId: generate_draft_posts
      parameters:
        - name: business_id
          in: path
          required: true
          schema:
            type: string
            description: A UUID identifier.
            title: Business Id
          description: A UUID identifier.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GenerateRequest'
      responses:
        '202':
          description: Generation job created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobStatusResponse'
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          description: Bad Request
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          description: Forbidden
        '404':
          description: Error (Stripe-style envelope — match on error.code, not the message)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '409':
          description: Error (Stripe-style envelope — match on error.code, not the message)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          description: Too Many Requests
        '500':
          description: Error (Stripe-style envelope — match on error.code, not the message)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
      security:
        - HTTPBearer: []
components:
  schemas:
    GenerateRequest:
      properties:
        content:
          anyOf:
            - type: string
            - type: 'null'
          title: Content
          description: Plain text content to generate posts from (used as the post topic).
        website_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Website Url
          description: >-
            URL to scrape for content context. The page text is used as input
            for generation.
        custom_idea:
          anyOf:
            - type: string
            - type: 'null'
          title: Custom Idea
          description: >-
            Skip ideation and use this text directly as the post idea for all
            generated posts.
        count:
          type: integer
          maximum: 10
          minimum: 1
          title: Count
          description: Number of posts to generate (1-10).
          default: 1
        creative_formats:
          anyOf:
            - items:
                type: string
                enum:
                  - design
                  - carousel
                  - meme
                  - image
                  - gif
                  - video
                  - ai-image
                  - ai-video
              type: array
            - type: 'null'
          title: Creative Formats
          description: >-
            Which post formats to generate (round-robins across the list). One
            or more of: design, carousel, meme, image, gif, video, ai-image,
            ai-video. Omit to use the business's default mix.
        ai_image_type:
          anyOf:
            - type: string
              enum:
                - design
                - photo
                - infographic
                - meme
            - type: 'null'
          title: Ai Image Type
          description: >-
            Sub-type for AI-image generation (only used when a creative_format
            is 'ai-image'): design, photo, infographic, or meme.
        ai_image_style:
          anyOf:
            - type: string
            - type: 'null'
          title: Ai Image Style
          description: >-
            Visual style modifier for AI images (e.g. 'corporate-flat',
            'isometric', 'comic'). Only used for 'ai-image'.
        template_ids:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Template Ids
          description: >-
            Restrict design generation to these specific template IDs instead of
            auto-selecting.
        voice:
          anyOf:
            - type: string
            - type: 'null'
          title: Voice
          description: >-
            Override the brand voice/tone for this generation only (the
            business's saved Profile is used when omitted).
        include_stock:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Include Stock
          description: >-
            Whether stock photos (Unsplash/Pexels) may be used. Omit to use the
            business's saved preference.
        aspect_ratio:
          anyOf:
            - type: string
            - type: 'null'
          title: Aspect Ratio
          description: >-
            Aspect ratio for generated media, e.g. '1:1' (square), '9:16'
            (story/reel), '4:5' (portrait). Omit for the business default.
      additionalProperties: false
      type: object
      title: GenerateRequest
    JobStatusResponse:
      properties:
        job_id:
          type: string
          title: Job Id
          description: ID to poll for status
        status:
          type: string
          enum:
            - pending
            - completed
            - failed
          title: Status
          description: Current job status
        data:
          anyOf:
            - items:
                $ref: '#/components/schemas/PostResult'
              type: array
            - type: 'null'
          title: Data
          description: Generated posts (when status=completed)
        error:
          anyOf:
            - type: string
            - type: 'null'
          title: Error
          description: Error message (when status=failed)
      type: object
      required:
        - job_id
        - status
      title: JobStatusResponse
    ErrorResponse:
      properties:
        error:
          $ref: '#/components/schemas/ErrorDetail'
          description: Error details
      type: object
      required:
        - error
      title: ErrorResponse
    ErrorEnvelope:
      description: >-
        The body of every non-2xx response.


        `detail` is retained on internal routes for backward-compatibility while
        the

        frontend migrates to reading `error.code`.
      properties:
        error:
          $ref: '#/components/schemas/ErrorDetail'
      required:
        - error
      title: ErrorEnvelope
      type: object
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    PostResult:
      properties:
        post_id:
          type: string
          title: Post Id
          description: ID of the created post
        title:
          type: string
          title: Title
          description: Short post title (max 7 words) for platforms that use titles
          default: ''
        caption:
          type: string
          title: Caption
        idea:
          type: string
          title: Idea
          description: The generated post idea
        creative_format:
          type: string
          enum:
            - design
            - carousel
            - meme
            - image
            - gif
            - video
            - ai-image
            - ai-video
          title: Creative Format
          description: The creative format used for this post
          default: design
        text_content:
          additionalProperties:
            type: string
          type: object
          title: Text Content
          description: component_id → text for all filled slots
        slides:
          items:
            $ref: '#/components/schemas/SlideResult'
          type: array
          title: Slides
          description: Images used in the design (one per page with fillers)
        topic_title:
          type: string
          title: Topic Title
          description: Topic used for this post
        category_name:
          anyOf:
            - type: string
            - type: 'null'
          title: Category Name
          description: Category of the topic
        template_id:
          type: string
          title: Template Id
          description: Design template used
        theme_name:
          type: string
          title: Theme Name
          description: Theme of the template
        rendered_urls:
          items:
            type: string
          type: array
          title: Rendered Urls
          description: CloudFront URLs of rendered slide images
        score:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Score
          description: >-
            Quality scores: hook_caption, hook_visual, depth, design_text,
            design_photos, overall
      type: object
      required:
        - post_id
        - caption
        - idea
        - text_content
        - slides
        - topic_title
        - category_name
        - template_id
        - theme_name
      title: PostResult
    ErrorDetail:
      properties:
        type:
          type: string
          title: Type
          description: >-
            Broad error category derived from the HTTP status
            (invalid_request_error, authentication_error, permission_error,
            not_found_error, rate_limit_error, api_error).
        code:
          $ref: '#/components/schemas/ErrorCode'
          description: >-
            Stable, machine-readable error code. Match on THIS, never on the
            message. Codes never change even when the message is reworded.
        message:
          type: string
          title: Message
          description: Human-readable explanation. For display/logging only — do not parse.
        doc_url:
          type: string
          title: Doc Url
          description: Link to the docs entry for this error code.
        param:
          anyOf:
            - type: string
            - type: 'null'
          title: Param
          description: The offending request field, when the error is field-specific.
        request_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Request Id
          description: >-
            The id of this request (also returned as the X-Request-Id header).
            Quote it to support so they can find the exact request in our logs.
      type: object
      required:
        - type
        - code
        - message
        - doc_url
      title: ErrorDetail
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
    SlideResult:
      properties:
        image_url:
          type: string
          title: Image Url
          description: URL of the selected image
        image_keyword:
          type: string
          title: Image Keyword
          description: Search keyword used to find this image
      type: object
      required:
        - image_url
        - image_keyword
      title: SlideResult
    ErrorCode:
      type: string
      enum:
        - authentication_required
        - permission_denied
        - resource_not_found
        - rate_limit_exceeded
        - validation_error
        - internal_error
        - already_exists
        - invalid_request
        - WORKSPACE_NOT_SUPPORTED
        - INSUFFICIENT_CREDITS
        - BUSINESS_CREDIT_LIMIT_EXCEEDED
        - NO_ENABLED_TOPICS
        - GENERATION_CAP_REACHED
        - CHECKOUT_BLOCKED
        - INVALID_API_KEY
        - SOCIAL_TOKEN_EXPIRED
        - PAYMENT_REQUIRED
        - NO_CONNECTED_SOCIALS
        - NOT_ENOUGH_POSTS_FOR_TOPICS
        - WORKSPACE_LIMIT_EXCEEDED
        - PHONE_NOT_VERIFIED
        - FILE_TOO_LARGE
        - SUBSCRIPTION_ALREADY_ACTIVE
        - UPSTREAM_PROVIDER_ERROR
        - PLATFORM_MEDIA_UNSUPPORTED
        - SOCIAL_CONNECT_FAILED
        - NO_PHOTO_SOURCE
        - TEMPLATE_FORMAT_MISMATCH
        - INVALID_CSV_ROW
        - IMAGE_GENERATION_FAILED
        - POST_RENDER_FAILED
        - POST_DESIGN_SELECTION_FAILED
        - POST_CONTENT_GENERATION_FAILED
        - POST_IDEATION_FAILED
        - IDEMPOTENCY_KEY_CONFLICT
      title: ErrorCode
      description: >-
        The full set of stable `error.code` values the API can return.


        Two groups: (1) GENERIC codes the global handler derives from the HTTP
        status

        or message keyword for plain raises (see api_errors._error_code + the
        handlers),

        and (2) the typed BUSINESS codes (mirror of ErrorType) for raises the
        frontend

        must tell apart from other same-status errors.


        This enum exists so OpenAPI emits an `enum` for error.code — a canonical
        list in

        the docs and a typed union for codegen — instead of a bare string. It
        does NOT

        validate runtime responses (those are plain dicts built in
        _build_error_response),

        so a code missing here only means incomplete docs, never a 500. The

        test_error_code_enum_covers_* tests keep it in sync with ErrorType +
        _error_code

        so it can't silently drift.
  securitySchemes:
    HTTPBearer:
      type: http
      scheme: bearer

````