> ## 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.

# Get external post stats

> Fetch stats for a single post on a connected platform.

`external_post_id` is the provider's post ID (e.g. Instagram media ID,
Tweet ID, TikTok video ID) — NOT the Marky post ID. Get external IDs
from `GET /businesses/{business_id}/integrations/{integration_id}/posts`
(each entry's `publish_id`) or from
`GET /businesses/{business_id}/posts/{post_id}/stats` (each platform entry's
`external_post_id`).

Returns the normalized `PostStats` model (likes, comment_count, reach,
views, etc.).

Errors:
    400 invalid_value: The integration_id is not a valid UUID.
    400 invalid_request: A metric value or the external_post_id was rejected.
    401 authentication_required: API key or token is missing, invalid, or revoked.
    403 permission_denied: Your plan does not include API access.
    404 resource_not_found: No integration with that ID exists, or it is not in your org.
    429 rate_limit_exceeded: You sent too many requests this minute.
    502 UPSTREAM_PROVIDER_ERROR: The social platform returned an error while fetching stats.



## OpenAPI

````yaml public-openapi.json get /api/businesses/{business_id}/integrations/{integration_id}/posts/{external_post_id}/stats
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}/integrations/{integration_id}/posts/{external_post_id}/stats:
    get:
      tags:
        - public-api
      summary: Get external post stats
      description: >-
        Fetch stats for a single post on a connected platform.


        `external_post_id` is the provider's post ID (e.g. Instagram media ID,

        Tweet ID, TikTok video ID) — NOT the Marky post ID. Get external IDs

        from `GET /businesses/{business_id}/integrations/{integration_id}/posts`

        (each entry's `publish_id`) or from

        `GET /businesses/{business_id}/posts/{post_id}/stats` (each platform
        entry's

        `external_post_id`).


        Returns the normalized `PostStats` model (likes, comment_count, reach,

        views, etc.).


        Errors:
            400 invalid_value: The integration_id is not a valid UUID.
            400 invalid_request: A metric value or the external_post_id was rejected.
            401 authentication_required: API key or token is missing, invalid, or revoked.
            403 permission_denied: Your plan does not include API access.
            404 resource_not_found: No integration with that ID exists, or it is not in your org.
            429 rate_limit_exceeded: You sent too many requests this minute.
            502 UPSTREAM_PROVIDER_ERROR: The social platform returned an error while fetching stats.
      operationId: get_external_post_stats
      parameters:
        - name: business_id
          in: path
          required: true
          schema:
            type: string
            description: A UUID identifier.
            title: Business Id
          description: A UUID identifier.
        - name: integration_id
          in: path
          required: true
          schema:
            type: string
            description: A UUID identifier.
            title: Integration Id
          description: A UUID identifier.
        - name: external_post_id
          in: path
          required: true
          schema:
            type: string
            title: External Post Id
        - name: metrics
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            description: Comma-separated metric names. Omit for defaults.
            title: Metrics
          description: Comma-separated metric names. Omit for defaults.
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PostStats'
        '400':
          description: Error (Stripe-style envelope — match on error.code, not the message)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '401':
          description: Error (Stripe-style envelope — match on error.code, not the message)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '403':
          description: Error (Stripe-style envelope — match on error.code, not the message)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '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':
          description: Error (Stripe-style envelope — match on error.code, not the message)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '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:
    PostStats:
      properties:
        fetched_at:
          type: string
          format: date-time
          title: Fetched At
        likes:
          anyOf:
            - type: integer
            - type: 'null'
          title: Likes
        comment_count:
          anyOf:
            - type: integer
            - type: 'null'
          title: Comment Count
        impressions:
          anyOf:
            - type: integer
            - type: 'null'
          title: Impressions
        shares:
          anyOf:
            - type: integer
            - type: 'null'
          title: Shares
        reach:
          anyOf:
            - type: integer
            - type: 'null'
          title: Reach
        saves:
          anyOf:
            - type: integer
            - type: 'null'
          title: Saves
        clicks:
          anyOf:
            - type: integer
            - type: 'null'
          title: Clicks
        views:
          anyOf:
            - type: integer
            - type: 'null'
          title: Views
        video_duration_ms:
          anyOf:
            - type: integer
            - type: 'null'
          title: Video Duration Ms
        avg_watch_time_ms:
          anyOf:
            - type: integer
            - type: 'null'
          title: Avg Watch Time Ms
        total_watch_time_ms:
          anyOf:
            - type: integer
            - type: 'null'
          title: Total Watch Time Ms
        completion_rate:
          anyOf:
            - type: number
            - type: 'null'
          title: Completion Rate
        video_views_organic:
          anyOf:
            - type: integer
            - type: 'null'
          title: Video Views Organic
        video_views_paid:
          anyOf:
            - type: integer
            - type: 'null'
          title: Video Views Paid
      additionalProperties: false
      type: object
      title: PostStats
      description: Statistics for a single post.
    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
    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
    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

````