# fetcher.sh — web data API for agents (x402 + credits)

fetcher.sh is one HTTP gateway for 111 web-data endpoints across 11 services: Twitter / X, YouTube, TikTok, Instagram, Reddit, Google Search, Google Maps, Google News, Google Play, App Store, Yelp. Every endpoint is a simple GET, paid in USDC on Base mainnet — per call via x402, or prepaid via credits with a Bearer API key. No accounts, no OAuth.

Base URL: https://fetcher.sh

## Triggers

Use this skill when the user wants to:

- Search or fetch public data from Twitter/X, YouTube, TikTok, Instagram, Reddit, Google Search, Google Maps, Google News, Google Play, the Apple App Store, or Yelp
- Scrape profiles, posts, comments, reviews, followers, trends, or search results
- Call paid web-data APIs with USDC micropayments (x402) or a prepaid credit balance

## Response envelope

Every endpoint returns JSON of the shape:

```json
{ "status": 200, "message": "ok", "data": "..." }
```

The HTTP status code mirrors the "status" field. Errors carry a descriptive "message".

## Payment mode A — prepaid credits (recommended)

One on-chain payment funds a balance; every call after that is a plain HTTP request with an API key. Fastest path: no signing, no chain round-trip per call.

Step 1 — top up (minimum $1). The top-up endpoint is itself x402-paid; pay it with any x402 client from a wallet holding USDC on Base mainnet:

```js
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount(process.env.PRIVATE_KEY);
const fetchWithPayment = wrapFetchWithPaymentFromConfig(fetch, {
  schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }],
});

const res = await fetchWithPayment(
  "https://fetcher.sh/api/credits/topup?amount=5",
  { method: "POST" },
);
const { data } = await res.json();
// data.key -> "bby_live_..." — returned EXACTLY ONCE on the first top-up. Save it.
```

Notes:

- Refill top-ups keep the existing key. Add &rotate=1 to mint a new key (the old one stops working immediately).
- Lost keys cannot be recovered (only a hash is stored) — rotate instead.
- To add credits to an EXISTING key from any wallet, send the same x402-paid POST with the header "Authorization: Bearer bby_live_..." — the credit goes to that key's account (rotate is not allowed in this mode).

Step 2 — call any endpoint with the key:

```bash
curl -H "Authorization: Bearer bby_live_..." "https://fetcher.sh/api/twitter/search?query=hello"
```

Step 3 — check the balance whenever needed (Bearer-only):

```bash
curl -H "Authorization: Bearer bby_live_..." "https://fetcher.sh/api/credits/balance"
```

If the balance cannot cover a call, the API answers 402 with message "topup_required" plus balance_micro, price_micro, and topup_url. Top up again, then retry.

## Payment mode B — x402 pay-per-call

Stateless and fully autonomous. Requirement: a wallet holding USDC on Base mainnet (eip155:8453). No ETH needed — gas is sponsored by the facilitator.

1. GET the endpoint with no payment → 402 response with a base64 payment-required header describing amount, asset, and recipient.
2. Sign an EIP-3009 USDC transferWithAuthorization for that amount.
3. Retry with the signed payload in the X-Payment header → the data comes back and the payment settles on-chain.

With @x402/fetch (configured as in mode A) the whole 402 → sign → retry loop is automatic:

```js
const res = await fetchWithPayment("https://fetcher.sh/api/twitter/search?query=hello");
console.log(await res.json());
```

## Funding notes

- A few cents of USDC covers thousands of calls at the default price.
- Humans can create or recharge a key in the browser at https://fetcher.sh/topup (connect an injected wallet, pay USDC on Base, gas sponsored).
- If no funded wallet is available, ask the user to fund a key at https://fetcher.sh/topup and hand you only the bby_live_ API key — the key alone is sufficient for all data calls.
- Never print private keys; never log the full API key.

## Endpoints (111 — all GET)

Substitute path parameters written as {param}. Prices are USD per call, settled in USDC.

### Twitter / X (15)

- GET /api/twitter/handle/{handle} — $0.005 — Handle
- GET /api/twitter/handle/{handle}/about — $0.005 — Handle about
- GET /api/twitter/list/{id}/members — $0.005 — List members
- GET /api/twitter/list/{id}/tweets — $0.005 — List tweets
- GET /api/twitter/search — $0.005 — Search
- GET /api/twitter/search/users — $0.005 — Search users
- GET /api/twitter/trends — $0.005 — Trends
- GET /api/twitter/tweet/{id} — $0.002 — Tweet
- GET /api/twitter/tweet/{id}/replies — $0.005 — Tweet replies
- GET /api/twitter/tweet/{id}/retweeters — $0.005 — Tweet retweeters
- GET /api/twitter/user/{id} — $0.005 — User
- GET /api/twitter/user/{id}/followers — $0.005 — User followers
- GET /api/twitter/user/{id}/followings — $0.005 — User followings
- GET /api/twitter/user/{id}/replies — $0.005 — User replies
- GET /api/twitter/user/{id}/tweets — $0.005 — User tweets

### YouTube (15)

- GET /api/youtube/channel/handle/{handle} — $0.005 — Channel handle
- GET /api/youtube/channel/path — $0.005 — Channel path
- GET /api/youtube/channel/{id} — $0.005 — Channel
- GET /api/youtube/channel/{id}/live-streams — $0.005 — Channel live streams
- GET /api/youtube/channel/{id}/shorts — $0.005 — Channel shorts
- GET /api/youtube/channel/{id}/videos — $0.005 — Channel videos
- GET /api/youtube/hashtag/{tag} — $0.005 — Hashtag
- GET /api/youtube/playlist/{id}/videos — $0.005 — Playlist videos
- GET /api/youtube/search/channel — $0.005 — Search channel
- GET /api/youtube/search/playlist — $0.005 — Search playlist
- GET /api/youtube/search/video — $0.005 — Search video
- GET /api/youtube/shorts/{id} — $0.005 — Shorts
- GET /api/youtube/trending — $0.005 — Trending
- GET /api/youtube/video/{id} — $0.005 — Video
- GET /api/youtube/video/{id}/comments — $0.005 — Video comments

### TikTok (13)

- GET /api/tiktok/hashtag/handle/{name} — $0.004 — Hashtag handle
- GET /api/tiktok/hashtag/{id}/posts — $0.004 — Hashtag posts
- GET /api/tiktok/location/{locationId}/posts — $0.004 — Location posts
- GET /api/tiktok/music/{id}/posts — $0.004 — Music posts
- GET /api/tiktok/post — $0.004 — Post
- GET /api/tiktok/post/search — $0.004 — Post search
- GET /api/tiktok/post/{id} — $0.004 — Post
- GET /api/tiktok/post/{id}/comments — $0.004 — Post comments
- GET /api/tiktok/post/{id}/comments/{commentId}/replies — $0.004 — Post comments replies
- GET /api/tiktok/user/handle/{username} — $0.004 — User handle
- GET /api/tiktok/user/{id}/followers — $0.004 — User followers
- GET /api/tiktok/user/{id}/followings — $0.004 — User followings
- GET /api/tiktok/user/{id}/posts — $0.004 — User posts

### Instagram (16)

- GET /api/instagram/audio/{id}/posts — $0.004 — Audio posts
- GET /api/instagram/hashtag/{name}/posts — $0.004 — Hashtag posts
- GET /api/instagram/hashtag/{name}/reels — $0.004 — Hashtag reels
- GET /api/instagram/location/{id}/posts — $0.004 — Location posts
- GET /api/instagram/post/code/{code} — $0.004 — Post code
- GET /api/instagram/post/{id}/comments — $0.004 — Post comments
- GET /api/instagram/user/handle/{handle} — $0.004 — User handle
- GET /api/instagram/user/search — $0.004 — User search
- GET /api/instagram/user/{id} — $0.004 — User
- GET /api/instagram/user/{id}/followers — $0.004 — User followers
- GET /api/instagram/user/{id}/followings — $0.004 — User followings
- GET /api/instagram/user/{id}/posts — $0.004 — User posts
- GET /api/instagram/user/{id}/posts/tagged — $0.004 — User posts tagged
- GET /api/instagram/user/{id}/reels — $0.004 — User reels
- GET /api/instagram/user/{id}/stories — $0.004 — User stories
- GET /api/instagram/userid/{handle} — $0.004 — Userid

### Reddit (15)

- GET /api/reddit/post/{id} — $0.002 — Post
- GET /api/reddit/post/{id}/comments — $0.002 — Post comments
- GET /api/reddit/post/{id}/comments/{commentId}/replies — $0.002 — Post comments replies
- GET /api/reddit/posts/best — $0.002 — Posts best
- GET /api/reddit/posts/hot — $0.002 — Posts hot
- GET /api/reddit/posts/new — $0.002 — Posts new
- GET /api/reddit/posts/top — $0.002 — Posts top
- GET /api/reddit/search/post — $0.002 — Search post
- GET /api/reddit/search/subreddit — $0.002 — Search subreddit
- GET /api/reddit/search/user — $0.002 — Search user
- GET /api/reddit/subreddit/{name} — $0.002 — Subreddit
- GET /api/reddit/subreddit/{name}/posts — $0.002 — Subreddit posts
- GET /api/reddit/user/{username} — $0.002 — User
- GET /api/reddit/user/{username}/comments — $0.002 — User comments
- GET /api/reddit/user/{username}/posts — $0.002 — User posts

### Google Search (1)

- GET /api/google/search — $0.005 — Search

### Google Maps (4)

- GET /api/google-maps/place/search — $0.005 — Place search
- GET /api/google-maps/place/{fid} — $0.005 — Place
- GET /api/google-maps/place/{fid}/reviews — $0.005 — Place reviews
- GET /api/google-maps/review/{id} — $0.005 — Review

### Google News (12)

- GET /api/google-news/business — $0.005 — Business
- GET /api/google-news/decode-article-url — $0.005 — Decode article URL
- GET /api/google-news/entertainment — $0.005 — Entertainment
- GET /api/google-news/health — $0.005 — Health
- GET /api/google-news/language-regions — $0.005 — Language regions
- GET /api/google-news/latest — $0.005 — Latest
- GET /api/google-news/science — $0.005 — Science
- GET /api/google-news/search — $0.005 — Search
- GET /api/google-news/sport — $0.005 — Sport
- GET /api/google-news/technology — $0.005 — Technology
- GET /api/google-news/topic/{topicId} — $0.005 — Topic
- GET /api/google-news/world — $0.005 — World

### Google Play (7)

- GET /api/googleplay/apps — $0.003 — Apps
- GET /api/googleplay/apps/{appId} — $0.003 — Apps
- GET /api/googleplay/apps/{appId}/datasafety — $0.003 — Apps datasafety
- GET /api/googleplay/apps/{appId}/permissions — $0.003 — Apps permissions
- GET /api/googleplay/apps/{appId}/reviews — $0.003 — Apps reviews
- GET /api/googleplay/apps/{appId}/similar — $0.003 — Apps similar
- GET /api/googleplay/developers/{developerId} — $0.003 — Developers

### App Store (9)

- GET /api/appstore/apps — $0.003 — Apps
- GET /api/appstore/apps/{appId} — $0.003 — Apps
- GET /api/appstore/apps/{appId}/reviews — $0.003 — Apps reviews
- GET /api/appstore/apps/{appId}/similar — $0.003 — Apps similar
- GET /api/appstore/bundles — $0.003 — Bundles
- GET /api/appstore/bundles/{bundleId} — $0.003 — Bundles
- GET /api/appstore/bundles/{bundleId}/reviews — $0.003 — Bundles reviews
- GET /api/appstore/bundles/{bundleId}/similar — $0.003 — Bundles similar
- GET /api/appstore/developers/{developerId} — $0.003 — Developers

### Yelp (4)

- GET /api/yelp/place/handle/{handle} — $0.003 — Place handle
- GET /api/yelp/place/{id} — $0.003 — Place
- GET /api/yelp/place/{id}/reviews — $0.003 — Place reviews
- GET /api/yelp/search — $0.003 — Search

### Credits

- POST /api/credits/topup?amount=<usd>[&rotate=1] — x402-paid; credits the paying wallet, mints or rotates the API key
- GET /api/credits/balance — Bearer-only; returns wallet, balance_micro, balance_usd, key_last4

## Error handling

- 400 — missing or invalid parameter; the message names the parameter
- 401 — unknown or rotated API key
- 402 — payment required (x402 challenge) or "topup_required" (credits exhausted)
- 404 — path is not a priced endpoint
- No rate limits: your balance is the natural backpressure.
- Settlement happens before delivery, so failed upstream calls are not refunded.

Machine-readable summary: https://fetcher.sh/llms.txt
