All docs
API reference

Hooks

List your hook library and trigger an on-demand refresh.

1 min readLast updated Edit this page

Hooks are short openers tagged by niche, language, and category. The system refreshes them daily on Starter+; this API also exposes a manual on-demand refresh trigger (Starter+, rate limited to 1/hour per organization).

GET/v0/api/v1/hooksAPI key or session

List hooks for your organization. Default sort: performance_score desc.

Parameters

NameInTypeDescription
pagequeryinteger1-indexed page (default 1).
limitqueryintegerItems per page, max 200 (default 50).
nichequerystringFilter by niche.
languagequerystringISO language code.
categoryquerystringproblem | curiosity | social_proof | listicle | contrarian | story.
statusquerystringAPPROVED | PENDING | REJECTED.
qquerystringCase-insensitive substring search on hook text.
sortquerystringPass "recent" to sort by createdAt desc instead of performance.

Response

json
{
  "success": true,
  "data": [
    {
      "_id": "hk_01HQ...",
      "organization_id": "org_01HQ...",
      "text": "POV: you found the meditation app that actually clicks.",
      "category": "curiosity",
      "language": "en",
      "niche": "meditation",
      "source": "TIKTOK_TREND",
      "status": "APPROVED",
      "performance_score": 0.82,
      "createdAt": "2026-05-12T03:00:00.000Z"
    }
  ],
  "page": 1,
  "limit": 50,
  "total": 137
}

cURL

Terminalbash
curl "https://api.viralslides.app/v0/api/v1/hooks?niche=meditation&language=en&limit=20" \
  -H "Authorization: Bearer vs_live_..."
POST/v0/api/v1/hooks/refresh-nowAPI key or session

Trigger an immediate hook library refresh for one app (or all active apps if app_id is omitted). Asynchronous — returns 202 with the jobs that were started.

Parameters

NameInTypeDescription
app_idbodystringOptional — refresh hooks for this app only. If omitted, refreshes all ACTIVE apps.

Request

Request bodyjson
{ "app_id": "app_01HQ..." }

Response

202 Acceptedjson
{
  "success": true,
  "data": {
    "jobs_started": 1,
    "apps": [
      { "id": "app_01HQ...", "name": "Meditate Daily", "niche": "meditation", "language": "en" }
    ]
  }
}

cURL

Terminalbash
curl -X POST https://api.viralslides.app/v0/api/v1/hooks/refresh-now \
  -H "Authorization: Bearer vs_live_..." \
  -H "Content-Type: application/json" \
  -d '{}'

TypeScript / JS

Node.jstypescript
const res = await fetch("https://api.viralslides.app/v0/api/v1/hooks/refresh-now", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.VIRALSLIDES_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({}),
})
if (res.status === 429) {
  const wait = res.headers.get("Retry-After")
  console.log(`rate-limited; retry in ${wait}s`)
}

Errors

StatusCodeDescription
403PLAN_UPGRADE_REQUIREDFree plan — upgrade to Starter+ to refresh hooks manually.
404NO_ACTIVE_APPSNo ACTIVE apps to refresh (or specified app_id not found).
429RATE_LIMITEDAlready refreshed within the last hour. Check Retry-After header.
Refresh-now is asynchronous

It returns 202 immediately and runs the Gemini/OpenAI calls in the background. Poll GET /hooks to see new entries appear (typically within 10–30 seconds).