A GitHub Action is a cron host with a checkout and a secret store. The workflow YAML schedules POST https://api.trendsapi.ai/api on get_growth and get_top_trends. body in the response is a JSON string and must be parsed a second time before the job writes a CSV or fails. A 2-keyword, 3-source watchlist is 6 growth calls. Add one live board and the run is 7 requests. Daily that is 210 per 30 days, above the free 100. Weekly is 28. On the 2026-08-31 pull used as the sample watchlist, gta 6 google search sat at 80.0 (+110.53% 7D) and ps5 pro google shopping sat at 57.0 (+78.12% 7D). Full rows for that pair sit in the GTA 6 vs PS5 Pro search vs shopping post. Field names: the API reference. A host crontab without Actions is cron Trends API.

How does the workflow YAML call POST /api?

Official GitHub Actions workflow syntax already has on.schedule. No marketplace action is required. The job needs requests or curl, the Bearer secret, and a second parse of body.

name: trends-watchlist
on:
  schedule:
    - cron: "0 10 * * 1"
  workflow_dispatch:
jobs:
  pull:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: pip install requests
      - run: python scripts/pull_watchlist.py
        env:
          TRENDSAPI_API_KEY: ${{ secrets.TRENDSAPI_API_KEY }}

The Python file is the same shape as the Python Trends API client. One function, one Bearer header, json.loads on body.

import json
import os
import requests

API_URL = "https://api.trendsapi.ai/api"
API_KEY = os.environ["TRENDSAPI_API_KEY"]

def trends_api(payload):
    res = requests.post(
        API_URL,
        headers={
            "Authorization": f"Bearer {API_KEY}",
            "Content-Type": "application/json",
        },
        json=payload,
        timeout=60,
    )
    res.raise_for_status()
    envelope = res.json()
    # body is a JSON string; parse it a second time
    return json.loads(envelope["body"])

Monday 10:00 UTC matches a weekly cadence. workflow_dispatch keeps a manual rerun for debugging. Caps: free 100, Starter 5,000, Pro 25,000, Business 100,000. Only HTTP 200 counts.

Where does the Bearer token live?

Create a repository secret named TRENDSAPI_API_KEY. Official GitHub Actions secrets inject it at runtime. The env block on the run step is enough. Do not put Bearer on a curl line in the YAML. Do not print os.environ["TRENDSAPI_API_KEY"]. Fork pull requests from untrusted branches should not inherit the secret. That is a GitHub default for secrets, not a Trends API rule.

Forks and pull_request triggers are a leak path. Keep this workflow on schedule and workflow_dispatch only.

What payload does a watchlist send?

One live board, then one get_growth per keyword and source. Single-source growth calls avoid gateway timeouts. The 2026-08-31 sample used gta 6 and ps5 pro.

WATCH = [
    ("gta 6", "google search"),
    ("gta 6", "youtube"),
    ("gta 6", "google shopping"),
    ("ps5 pro", "google search"),
    ("ps5 pro", "youtube"),
    ("ps5 pro", "google shopping"),
]

board = trends_api({
    "mode": "get_top_trends",
    "type": "Google Trends",
    "limit": 25,
})

rows = []
for keyword, source in WATCH:
    growth = trends_api({
        "mode": "get_growth",
        "source": source,
        "keyword": keyword,
        "percent_growth": ["7D", "14D", "30D", "3M", "12M"],
    })
    rows.append(growth)

get_top_trends takes a type and no keyword. Google Trends as of 2026-08-31T08:01:33Z ranked when does gta 6 come out at 12 and ps5 pro at 23. The board token and the growth keyword are not always the same string. Score both. Source notes for search sit on Google Trends.

What did the sample watchlist return?

Pulled 2026-08-31. Weekly tip date 2026-08-29 unless noted. Scores are 0-100.

Keyword Source Score 7D baseline 7D % 14D % 12M %
gta 6 google search 80.0 38.0 110.53 471.43 1500.0
gta 6 youtube 43.0 15.0 186.67 975.0 2050.0
gta 6 google shopping 35.0 14.0 150.0 250.0 1066.67
ps5 pro google search 43.0 23.0 86.96 79.17 138.89
ps5 pro youtube 16.0 13.0 23.08 33.33 45.45
ps5 pro google shopping 57.0 32.0 78.12 72.73 111.11

gta 6 google news was 67.0 (+34.0% 7D from 50.0, +3250.0% 12M from 2.0). ps5 pro google news was 40.0 (+21.21% 7D from 33.0, -11.11% 14D from 45.0). YouTube Trending rank 5 at 2026-08-31T10:01:30Z was a sold-out PS5 Pro clip after a GTA 6 trailer. The hardware shopping score (57.0) outran hardware YouTube (16.0). The game YouTube score (43.0) outran game shopping (35.0). Store those six cells, not a single blended rank.

gta 6 google search peaked at 100.0 on 2026-06-27, then 43.0 on 2026-07-04, 12.0 on 2026-08-01, 14.0 on 2026-08-15, 38.0 on 2026-08-22, and 80.0 on 2026-08-29. The Action should persist the tip week, not only the percent. A 110.53% 7D print without 80.0 vs 38.0 is not auditable.

How should the job fail?

Fail on HTTP errors first. res.raise_for_status() catches 4xx and 5xx. A 200 with an inner error key is a data finding, not a runner crash. tiktok and steam both returned no_data for gta 6 in this session. Write that string. Do not retry those sources in a loop. Each extra 200 still counts if the call later succeeds.

A useful fail rule for this watchlist:

  1. Google Trends rank for the related token is 25 or better.
  2. Matching get_growth 7D on google search or google shopping is +50% or more.
  3. Both conditions in the same run.

On 2026-08-31 that rule fires: rank 12 and 23, search +110.53% and shopping +78.12%. ps5 pro YouTube at +23.08% would not fire alone. Do not page on YouTube alone when shopping is the SKU.

Write as_of_ts, recent_date, score, baseline, and percent into the job summary or an artifact. Do not fail the workflow on collapsed_range. Amazon 7D and 14D collapsed for both keywords. The monthly Amazon tip was 2026-07-31, a month behind the weekly search tip of 2026-08-29.

What quota math belongs in the README?

Cadence Calls per run Per 30 days Free 100 Starter 5,000
Weekly, 6 growth + 1 board 7 28 fits fits
Daily, same payload 7 210 over fits
Daily, 2 keywords, 1 source, no board 2 60 fits fits
Hourly, 1 keyword, 1 source 1 720 over fits

n8n and Zapier canvases also POST the same envelope. Those pages are n8n Trends API and Zapier Trends API. Graduate to Airflow when the watchlist needs retries, pools, and a warehouse load. The Action is the right default while the list is two titles and a board.