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

# Get Viral Library Post

> Read one viral library post by ID, including the slide texts a search result omits

Read one post from Genviral's curated corpus of organic viral posts.

This is the only place `slide_texts` is served. A search page omits it so a page
of results stays small, so reading the words on a post's slides is a deliberate
second call once the search has told you which post is worth it.

Every other field matches
[Search Viral Library](/api-reference/search-viral-library) exactly.

## Path Parameters

<ParamField path="postId" type="string" required>
  A post `id` returned by
  [Search Viral Library](/api-reference/search-viral-library).
</ParamField>

## Response

The response is one viral library post object.

<ResponseField name="id" type="string" />

<ResponseField name="platform" type="string" />

<ResponseField name="content_type" type="string" />

<ResponseField name="link" type="string | null" />

<ResponseField name="category" type="string" />

<ResponseField name="business_type" type="string | null" />

<ResponseField name="product_name" type="string | null" />

<ResponseField name="product_website" type="string | null" />

<ResponseField name="account" type="string | null" />

<ResponseField name="caption" type="string | null" />

<ResponseField name="hashtags" type="string[]" />

<ResponseField name="date_published" type="string | null">
  Calendar date, `YYYY-MM-DD`.
</ResponseField>

<ResponseField name="metrics" type="object">
  `views`, `likes`, `comments`, `shares`, and `bookmarks`, each a number or
  `null` where the platform did not report it.
</ResponseField>

<ResponseField name="slide_count" type="number | null" />

<ResponseField name="preview_image_url" type="string | null" />

<ResponseField name="image_urls" type="string[]">
  Slide images, in order.
</ResponseField>

<ResponseField name="video_url" type="string | null">
  Present only when the clip is available for playback.
</ResponseField>

<ResponseField name="hook_text" type="string | null">
  The opening line the post leads with.
</ResponseField>

<ResponseField name="hook_analysis" type="object | null">
  `content_class`, `format_template`, and `psychology_tags`.
</ResponseField>

<ResponseField name="search_summary" type="string | null" />

<ResponseField name="niche" type="string | null" />

<ResponseField name="topics" type="string[]" />

<ResponseField name="search_keywords" type="string[]" />

<ResponseField name="slide_texts" type="string[] | null">
  The text on each slide, in order. `null` for a post with no slide text.
</ResponseField>

<ResponseField name="relevance" type="null">
  Reserved. The ranking score is not exposed.
</ResponseField>

## Rate limits

Single-post reads are limited to **60 per minute and 300 per day** per
authenticated customer, with a ceiling of 900 per minute across all callers
together. A throttled request answers `429` with `error_code: "rate_limited"`
and a `retry_after_seconds` value; wait that long before retrying.

These reads spend no part of the search budget.
[Search Viral Library](/api-reference/search-viral-library) carries its own
allowance of 2,000 results a day, and each search is charged its requested
`limit`, so read a post here rather than re-running a search to see it again.

A `503 provider_unavailable` means the limiter itself could not be reached.
The daily budgets are counted centrally, so a request that cannot be counted is
refused rather than served. It is transient, and carries its own
`retry_after_seconds`.

<RequestExample>
  ```bash cURL theme={null}
  curl --request GET \
    --url 'https://www.genviral.io/api/partner/v1/viral-library/viral-post-1' \
    --header 'Authorization: Bearer <token>'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={null}
  {
    "ok": true,
    "code": 200,
    "message": "Viral library post retrieved",
    "data": {
      "id": "viral-post-1",
      "platform": "tiktok",
      "content_type": "slideshow",
      "link": "https://www.tiktok.com/@chefdesk/video/1",
      "category": "Food & Cooking",
      "business_type": "app",
      "product_name": "Chef Desk",
      "product_website": "https://chefdesk.example",
      "account": "chefdesk",
      "caption": "The 3 meals I batch on Sunday",
      "hashtags": ["mealprep", "cookingapp"],
      "date_published": "2026-07-14",
      "metrics": {
        "views": 412000,
        "likes": 38000,
        "comments": 900,
        "shares": 1200,
        "bookmarks": 5400
      },
      "slide_count": 6,
      "preview_image_url": "https://cdn.example.com/viral/preview-1.jpg",
      "image_urls": ["https://cdn.example.com/viral/slide-1.jpg"],
      "video_url": null,
      "hook_text": "I stopped cooking every night",
      "hook_analysis": {
        "content_class": "listicle",
        "format_template": "problem-solution",
        "psychology_tags": ["relief", "time-saving"]
      },
      "search_summary": "A batch-cooking app walkthrough told as a Sunday routine",
      "niche": "meal planning",
      "topics": ["batch cooking"],
      "search_keywords": ["meal prep app"],
      "slide_texts": [
        "I stopped cooking every night",
        "Sunday: 3 bases, 40 minutes",
        "Monday to Thursday: assemble only"
      ],
      "relevance": null
    }
  }
  ```
</ResponseExample>

## Error Responses

* `401` - authentication failed (missing, invalid, or revoked token)
* `402 subscription_required` - an active eligible subscription is required
* `403 tier_not_allowed` - the Scheduler tier cannot use the Partner API
* `404` - no post with this ID is in the library
* `422` - `postId` is missing or longer than 300 characters
* `429 rate_limited` - the per-customer or shared rate limit was reached; wait
  `retry_after_seconds` and retry
* `503 provider_unavailable` - the rate limiter was unreachable, so the request
  was refused rather than served uncounted; wait `retry_after_seconds` and retry
