Skip to content
Back to skills

Paysh Catalog

ASecurity

Catalog of pay.sh services payable via agent_pay (x402). OPT-IN ONLY — activate when the user explicitly invokes pay.sh / paysh / x402 / 'pay for'. Stay dormant otherwise; defer to free tools. Full keyword list and policy in SKILL.md body.

  • 318 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added May 26, 2026
ai-agentsgonodeapi

Works with

  • api

Security analysis

A100/100

Pro scans all 15 files and shows the line behind each finding

Scanned May 27, 2026

npx -y skills add sepivip/SeekerClaw --skill paysh-catalog --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Paysh Catalog?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Paysh Catalog
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/sepivip-paysh-catalog/badge)](https://www.skillsdirectory.com/skills/sepivip-paysh-catalog)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: paysh-catalog
description: "Catalog of pay.sh services payable via agent_pay (x402). OPT-IN ONLY — activate when the user explicitly invokes pay.sh / paysh / x402 / 'pay for'. Stay dormant otherwise; defer to free tools. Full keyword list and policy in SKILL.md body."
version: "1.8.0"
metadata:
  openclaw:
    emoji: "🛒"
    requires:
      bins: []
      env: []
---

# pay.sh Service Catalog

A curated directory of HTTPS endpoints the agent can pay for using `agent_pay` and the burner wallet, **only when the user explicitly opts in** via a pay-intent keyword.

## Default: this skill is DORMANT

For the **vast majority of user messages**, this skill should not activate. The agent's default behavior for any question is:

1. Try training data (facts, definitions, well-established knowledge)
2. Try `web_search` / `web_fetch` (live web data, free)
3. If neither answers and the user did NOT explicitly invoke pay/x402, give a best-effort honest answer noting the limitation — **do NOT autonomously reach for a paid catalog service**

This skill activates ONLY when the user's message contains one of the explicit pay-intent keywords listed below. If you're unsure whether a message is opting in, **prefer the free path** — paid lookups cost USDC and the user did not authorize a charge implicitly.

### Opt-in keywords (skill activates)

- `pay.sh` / `paysh` / `pay sh` — naming the platform
- `x402` — naming the protocol
- `pay for X` / `pay to X` / `pay <amount> to <service>` / `use pay` — explicit paying verb
- `look this up paid` / `fetch this paid` / `buy data from <service>` — explicit paid-fetch verb
- `use <service> to pay` / `pay <service> for X` — service-name + paying verb
- `what can you pay for` / `show me pay.sh services` / `list paid services` — capability question

### NOT opt-in (skill stays dormant)

- Topical / factual questions: *"what's the mass of the sun"*, *"who founded Solana"*, *"what time is it in Tokyo"* → training data or `web_search`
- Live-data questions WITHOUT a paying verb: *"find me a hotel in Rome"*, *"current price of SOL"*, *"best deal on a PS5"* → `web_search`
- General Solana / Jupiter operations: *"check my balance"*, *"send 0.1 SOL to Alice"*, *"swap SOL for USDC"* → use the relevant tool directly (`solana_balance`, `solana_send`, `solana_swap`); these are NOT x402 and don't involve this skill

## What this skill does (once activated)

Once an opt-in keyword fires the skill, the agent's job is:

1. **Match intent → entry** by reading `catalog.json` (the index in this folder). v2 schema: top-level object with `entries[]` array; each entry has `id`, `service_id`, `name`, `endpoint.{method, path, cost_usdc}`, `intents[]`, `summary`, `doc_file`, `verification.*`. Pick the entry whose `intents[]` best matches user request.
2. **Build the URL** by combining `entry.upstream_ref.service_url + entry.endpoint.path`. Add URL-encoded query params for GET endpoints (see encoding rules below).
3. **Read the matching `entry.doc_file`** (e.g. `services/wolfram-alpha.md`) for body schema (POST endpoints), example calls, and any safety scoping. If the entry has a `doc_anchor`, jump to that section within the doc.
4. **Call `agent_pay`** with object-shaped args: `{ url: "<constructed-url>", max_usdc: "<decimal-string-ceiling>", method?: "GET"|"POST", body?: <JSON object or array, required for POST> }`. `max_usdc` MUST be a decimal STRING (not number) — e.g. `"0.05"`. `body` MUST be a JSON object or array (or a JSON string that parses to one); primitives like numbers/strings/booleans are rejected with `body_not_json`. GET calls run silently when under cap. **POST calls always prompt the user for confirmation** regardless of caps (POST can send SMS, post content, or trigger paid actions — the confirmation is by design). Use `entry.endpoint.method` to pick GET vs POST.
5. **Return the response** to the user

## Examples

### Activates → paid call

User: *"Use pay.sh to look up the current GDP of Japan in USD."*

Why it activates: contains `pay.sh` + naming a paid lookup.

```
1. Read catalog.json → 'wolfram-alpha' matches the math/facts intent.
2. Read services/wolfram-alpha.md → URL pattern is
   https://wolframalpha.x402.paysponge.com/v1/result?i=<URL-encoded query>
3. URL-encode the query with `encodeURIComponent`. It encodes spaces
   as `%20` and percent-encodes most special characters (`&` → `%26`,
   `=` → `%3D`, `+` → `%2B`, `#` → `%23`, `/` → `%2F`, etc.).
   **NOT encoded** by `encodeURIComponent` (per the JS spec — kept
   unchanged): A-Z a-z 0-9 `- _ . ~ ! * ' ( )`. These chars are valid
   in HTTP query strings as-is, so leaving them unencoded is fine for
   pay.sh's services. If a specific service requires stricter
   RFC3986-style encoding (rare), the service's `services/<id>.md`
   will say so.
   Example for this query:
     encodeURIComponent("current GDP of Japan in USD")
     → "current%20GDP%20of%20Japan%20in%20USD"
   Final URL:
     https://wolframalpha.x402.paysponge.com/v1/result?i=current%20GDP%20of%20Japan%20in%20USD
   Do NOT mix `+` for spaces with `encodeURIComponent` — `+` is form-
   encoded space, and applying encodeURIComponent over a string that
   already contains `+` would turn `+` into `%2B` (literal plus).
4. Invoke agent_pay with JSON args:
   agent_pay({ url: "<constructed-url-above>", max_usdc: "0.05" })
   max_usdc MUST be a decimal STRING (not number). Burner signs
   silently for this GET call since $0.01 << $0.05 ceiling.
5. Return Wolfram's answer with a brief framing.
```

### Activates → catalog browsing (no paid call yet)

User: *"What can you pay for?"*

Why it activates: matches the capability-ask phrase *"what can you pay for"*. (NOT every message containing the word "pay" — only the specific capability-ask phrases listed in the opt-in section above.) Agent reads `catalog.json`, lists the 44 supported entries (across 10 services — many services have multiple endpoints now: stablecrypto-market-data has 21, perplexity has 2, others 1-5 each) with costs, mentions the 63 known-but-not-usable ones. No `agent_pay` call. For "what can you pay for" the agent should GROUP by service in the reply (e.g. "Wolfram Alpha — 2 endpoints (math facts, structured pods); Tripadvisor — 5 endpoints (search, details, reviews, photos); StableCrypto — 21 endpoints (CoinGecko price/chart/markets, DefiLlama TVL/yields)") rather than dumping 44 individual lines.

### Does NOT activate → vanilla answer

User: *"What's the mass of the sun?"*

Why it stays dormant: no opt-in keyword. The agent answers from training data: *"The Sun's mass is about 1.989 × 10³⁰ kg."* — **no USDC charge**.

User: *"Find me a hotel in Rome."*

Why it stays dormant: "find" + "hotel" without any paying verb or service name. Use `web_search`. If the user then says *"pay Tripadvisor to find one"* the skill activates and we hit the catalog.

User: *"Check my Solana balance."*

Why it stays dormant: not an x402 query at all. Use `solana_balance` directly. The paysh-catalog skill is unrelated to Solana balance / send / swap operations.

## Reading the catalog efficiently

`catalog.json` is small-ish (currently 44 entries across 10 services, ~30KB in v2 schema — services are now genuinely multi-endpoint: stablecrypto-market-data has 21 endpoints, tripadvisor has 5, rentcast has 5, crushrewards has 4, wolframalpha/reducto/perplexity have 2, others 1). Always load it first to pick the entry by intent match. Then `read` only the matching `entry.doc_file` (potentially scrolling to `entry.doc_anchor` within it) — never load every services/*.md at once. That's the whole point of the per-entry / per-service-doc layout.

v2 schema (see `SCHEMA.md` in this folder for the full spec):
- One entry per ENDPOINT (not per service) — a service exposing N catalogued endpoints has N entries, all sharing the same `service_id`
- `entry.doc_file` may carry an optional `doc_anchor` pointing at the endpoint-specific section within the shared service doc
- `entry.verification.last_captured_at` tells you how fresh the 402 capture is; if very old, the service may have drifted upstream (run `node tests/paysh/probe-catalog.js --refresh <id>` from the dev workstation to re-verify)

## The `unsupported.json` companion registry

`unsupported.json` lists **63 additional entries** that exist on pay.sh today but the agent cannot **end-to-end use** yet — either because `agent_pay` can't pay them (protocol/auth gap), it can pay but can't deliver the response (binary content with no channel attachment path), the endpoint didn't return a 402 at probe time (broken / moved / re-routed), or the paid-response shape is contested and unverified.

v2 schema: top-level object with `entries[]` (same shape as catalog entries + `reason` field) AND a top-level `reasons` object — a registry of `{ <bucket>: { label, explanation, actionable } }` you compose your "why can't you use X?" answers from. Several entries also carry `audit_pending[]` — sibling endpoints found by the BAT-706 audit that aren't catalogued yet (with `deferred_to: BAT-XXX` pointer).

Read `unsupported.json` when:

- The user asks "do you know about service X?" or "is X on pay.sh?"
- The user asks for a capability (translation, image OCR, video analysis, screenshots, Google Vision, image generation, etc.) that the supported 10 don't cover
- You want to give an honest "I know it exists but can't deliver it because of Y" answer instead of a generic "I don't have a service for that"

Six reason buckets:

| Reason | What it means | Will we ever use it? |
|---|---|---|
| `mpp_protocol` | Service uses Multi-Party Protocol (newer pay.sh settlement flow we don't implement) | Future BAT — not yet filed |
| `siwx_auth_required` | Service needs Sign-In-With-Solana auth before returning 402 | Adjacent to BAT-697 (Trigger V2 also needs SIWX) — likely unblocked when that lands |
| `invalid_demand` | Service returns 402 with amount=0; agent_pay refuses zero-demand AND our web_fetch throws on 402, so neither tool reaches them | Possible follow-up: a 402-tolerant fetch flag |
| `requires_binary_response` | Service returns binary content (image/audio/video) we can't pipe to Telegram/Discord as attachment | Future BAT — needs `agent_pay` → workspace-file path |
| `endpoint_not_402_at_probe` | Service is listed upstream but our probe got a non-402 HTTP status (4xx/5xx/200/301) — likely broken, moved, or auth-gated differently. Each entry's `note` records the probe-time status code | Re-probe via `tests/paysh/probe-catalog.js` if pay.sh announces the endpoint is back |
| `unverified_paid_response_shape` | Paid endpoint exists and parses OK, but available evidence about the response shape is contested or absent (e.g. openapi declares one content-type while product-family inference suggests another). Distinct from `requires_binary_response` — we only assert binary when evidence clearly points there. Conservative refuse pending paid-response capture | BAT-708 — paid-response capture + classification before catalog inclusion |

Some `endpoint_not_402_at_probe` and `invalid_demand` entries also carry BAT-706 audit notes about **sibling endpoints on the same host** that ARE payable but aren't catalogued yet (e.g. paysponge/nyne person-search endpoints — deferred to BAT-772 Tier 2c). Each pending endpoint's `deferred_to` field is either a BAT-XXX follow-up ticket id, or `null` when the endpoint is unscheduled (no ticket yet — known to exist, but no decision on when/how to catalog). Read each entry's `note` field — it tells you whether the audit found more and what their status is. (Note: paysponge/perplexity also had audit-discovered siblings; BAT-769 promoted /search and /v1/agent to the catalog, leaving only /v1/async/sonar in audit_pending as unscheduled.)

**NEVER call `agent_pay` on a service in `unsupported.json`.** Reasons and what to tell the user:

- **`mpp_protocol`** / **`siwx_auth_required`** — `agent_pay` fails at the protocol layer (free, no USDC spent). Tell the user the service is known but uses a protocol we don't support yet.
- **`invalid_demand`** — service returns 402 with amount=0. `agent_pay` refuses zero-demand AND our `web_fetch` throws on any non-2xx, so neither tool reaches it today. Tell the user the service is known but not currently usable via our tools.
- **`requires_binary_response`** — `agent_pay` would actually **succeed and spend USDC** — but the binary response (PNG/audio/video) can't be delivered to Telegram/Discord today. Don't burn their money. Tell them the service is recognized but the binary output isn't deliverable yet.
- **`endpoint_not_402_at_probe`** — service is in pay.sh's upstream catalog but our probe got a non-402 HTTP status (the entry's `note` field records the exact code). `agent_pay` needs a 402 to settle, so it can't pay these. Tell the user the service is listed upstream but our probe found it broken / moved / auth-gated at probe time; suggest re-probing later via `tests/paysh/probe-catalog.js` if pay.sh announces a fix.
- **`unverified_paid_response_shape`** — `agent_pay` WOULD settle (parseable 402 exists), but we have NOT captured an actual paid response and the evidence is contested. Tell the user the service is known and the catalog-listed URL pays, but we conservatively refuse it until we capture a paid response to confirm we can deliver the output. Mention that BAT-708 will resolve this.

## When NOT to use this catalog

- **Direct URL provided** — user gives `https://...` already, just call `agent_pay` directly.
- **Free info works** — math facts in your training data, definitions, public Wikipedia content. `web_search` is free; don't burn USDC for things web_search returns.
- **No matching service** — if no entry fits the user's intent in EITHER catalog.json OR unsupported.json, fall back to `web_search` / `web_fetch` and tell the user we don't have a pay.sh service for this yet.

## What's NOT in this catalog (yet)

- Auto-refresh from upstream pay.sh — V1 ships static (this file). V2 will add a refresh tool. Until then the catalog is whatever the APK shipped.
- Services that demand non-USDC assets or non-Solana chains only — filtered out at probe time (see `tests/paysh/catalog-summary.md`).

## Boundaries

- All charges go through the **burner wallet**, never the main wallet. `agent_pay` is **burner-only** — there is no main-wallet fallback. If the user doesn't have a burner configured, `agent_pay` refuses with `burner_not_configured` — tell them to set one up in Settings → Solana Wallet → Burner Wallet.
- `max_usdc` is a **ceiling**, not a target. The actual charge is whatever the service demands, capped at `max_usdc`. Default to `max_usdc = 2× the listed cost` for safety.
- Burner caps (per-tx / daily USDC) apply on top of `max_usdc`. If a single call exceeds the per-tx cap or the daily cap is exhausted, `agent_pay` returns `burner_cap_exceeded` and **does not fall back to the main wallet**. Tell the user to either raise the cap with `wallet_set_caps`, lower their request, or wait for the 00:00 UTC daily reset.

## Failure modes

| Error | What it means | What to do |
|-------|---------------|------------|
| `burner_not_configured` | No burner wallet set up | Tell user to set up in Settings |
| `demand_exceeds_max_usdc` | Service costs more than you offered | Retry with higher max_usdc, within burner cap |
| `burner_cap_exceeded` | Burner per-tx or daily USDC cap insufficient for this charge | Tell user to raise cap with `wallet_set_caps`, lower the request, or wait for 00:00 UTC daily reset. **No main-wallet fallback.** |
| `insufficient_burner_balance` | Burner USDC balance < demanded amount | Reason text states exact shortfall — tell user how much more USDC to send to the burner pubkey, offer to retry once funded |
| `non_usdc_asset` | Service demanded non-USDC payment | Service incompatible — not actionable |
| `no_solana_offer` | Service is EVM-only on this call | Service incompatible — not actionable |
| `unsupported_version` | Service speaks newer x402 than we support | Service incompatible — file a BAT to upgrade |
| HTTP 4xx after payment | Service-side issue (bad params, auth, etc.) | Reply with the error; refund is on the service, not us |

Files in this skill

  • SCHEMA.md21.2 KB
  • SKILL.md16 KB
  • catalog.json51.6 KB
  • services/2captcha.md2.5 KB
  • services/crushrewards.md4.4 KB
  • services/perplexity.md8.9 KB
  • services/purch.md1.3 KB
  • services/reducto.md2.3 KB
  • services/rentcast.md8.7 KB
  • services/stablecrypto-market-data.md13.5 KB
  • services/stableenrich.md1.3 KB
  • services/textbelt-sms.md4.8 KB
  • services/tripadvisor.md3.2 KB
  • services/wolfram-alpha.md3.5 KB
  • unsupported.json94.2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.