git clone --depth 1 https://github.com/superdesigndev/treg /tmp/vendor-listing && cp -r /tmp/vendor-listing/.claude/skills/vendor-listing ~/.claude/skills/vendor-listingSKILL.md
# Vendor listing — add a provider to the catalog
A listing has **three parts**, and all three ship in the same PR:
1. **Registry entry** (`src/treg/oauth_providers.py`) — how a team connects a credential for the
provider, and how treg verifies that credential is real.
2. **Core catalog file** (`src/treg/catalog/<service>.yaml`) — what an agent can *do*: 8–15
curated endpoints with capability mapping, inputs, cost + provenance, and verified examples.
3. **Platform-key slot** (`config.py` + `render.yaml` + `fx.yaml`) — so treg can serve the
endpoints on its own key (tier 4). **Always aim for this.** A listing that is BYOK-only is the
exception and needs a stated reason (no self-serve pricing, `own_account` data, sales-gated).
And every listing PR carries a **verification evidence ledger** (Step 7b). No ledger, no merge.
Deep references (read before non-trivial work; do not duplicate them here):
- `docs/context/guides/expanding-a-category.md` — the add-a-provider playbook, verify toolbox, traps
- `docs/context/architecture/catalog.md` — catalog schema, cost provenance, verify pipeline, PII rules
- `docs/VENDORS.md` — what we told the vendor to prepare (their checklist)
- `src/treg/web/vendor-listing.md` — the HOSTED instructions (served at `/vendor-listing`) that a
vendor's own coding agent follows to raise a listing PR; the dashboard's "List as vendor" modal
(connections view, `vendorAsk` in `index.html`) hands vendors a prompt pointing at it. Keep the
three vendor-facing surfaces (doc, hosted page, modal prompt) telling one story.
## Step 0 — intake: collect the vendor facts
Before touching code, you need ALL of these. If the vendor's submission is missing any, ask —
do not guess ("unconfirmed" beats a wrong path shipped):
- **A contact email for the vendor's team** — required in the PR/issue description. It is how a
test credential gets arranged for live verification; without it the listing stalls at step 7.
- `service` id (lowercase slug), display name, one-line summary (what an agent can DO)
- `base_url` (exact API root)
- Auth: where the key rides (header name + format, or query param name). Key **in the URL path is
not supported** — decline or defer.
- A **free or near-free probe endpoint** where a valid key returns 2xx and an invalid key does NOT
— plus the exact bad-key behavior (status code, or the JSON field that signals invalid)
- Pricing page URL, per-endpoint prices, and the billing model (`per_call` / `per_success` /
`per_result` / credits / quota). Machine-readable rate-card endpoint if they have one.
- Docs URL; OpenAPI spec URL if published
- The 8–15 endpoints they consider their core surface, with example parameter *values*
- A test credential (or credits grant) for verification — read it from env only, never write it
into any file
## Step 1 — eligibility gate
Reject decisively, with a recorded reason, when:
- The key **cannot be validated** (API returns success for garbage keys) — e.g. ScrapeCreators
- Key rides in the **URL path** (`/v3/{key}/…`) — injectors do header/query only
- **Sales-gated** signup (no self-serve key breaks the fast path)
- Legal/shutdown risk, or deprecated/absorbed products
## Step 2 — registry entry
Add an `OAuthProvider(auth_kind="key", …)` in `oauth_providers.py` and append it to `REGISTRY`.
Model it on `HUNTER` (a clean key provider). Pick the verify fields from the toolbox table in
`expanding-a-category.md` (`token_header`/`token_format`, `token_location="query"`+`token_param`,
`probe_url`, `probe_method`+`probe_json`, `token_verify_field`, `token_ok_field`+`token_ok_value`,
`token_reject_field`, `probe_reject_statuses`, …). Prefer a header over a query key so the secret
never lands in a logged URL. Set `category` (add to `CATEGORY_ORDER` only if genuinely new),
`summary`, `base_url`, `docs_url`, `probe_path`, and `setup_url`/`setup_steps` so a user can find
their key.
**Provider-required constant headers** (Crustdata's `x-api-version: 2025-11-01`): declare them in
`required_headers=(("name", "value"),)` on the `OAuthProvider` and in the `providers.py` CATALOG
row — never in the proxy. They become constant-format bindings. Trap (PR #191): a binding whose
`format` has no `{secret}` must NOT be fed to `_secret_renderings` — otherwise the literal
value (a date!) joins the redaction set and gets masked out of error evidence. Check the
constant does not appear in `_secret_renderings`' output, and add a test.
## Step 2b — platform-key slot (do this for every listing)
The tier-4 wiring is part of the listing, not a follow-up:
- `src/treg/config.py`: `platform_key_<service>: str = ""` with a one-line comment (auth shape,
what a top-up buys). Pairs (key+secret) use `platform_extra_setting`; see Tomba.
- `render.yaml`: `- key: TREG_PLATFORM_KEY_<SERVICE>` + `sync: false` + a comment. **No value.**
- `src/treg/catalog/fx.yaml` `credit_rates_usd`: the USD-per-credit treg actually pays, with
`basis` naming the real top-up/receipt (not the pricing page's headline tier), `source`, `checked`.
- A test asserting `cat.platform_eligible(ep)` for every endpoint in the file (see
`test_crustdata_and_aviato_catalogs_are_platform_priced`); every cost must therefore be
`confidence: documented|verified` with a computable USD figure.
- If the platform key also needs a constant header, `_platform_bindings` must carry it — assert
the tier-4 binding list equals BYOK's (see `test_crustdata_platform_key_keeps_the_required_version_header`).
- Hand the **env value** to Jason out-of-band (a file, never the PR, never chat if avoidable) with
the `TREG_PLATFORM_PROVIDERS` allow-list entry. Setting it in Render is his ops decision; the PR
just makes it possible.
Modal pricing (preview/rescrape/email riders, bulk-per-record) that one scalar can't express: keep
the numbers in the YAML cost block (`note` today; a `modifiers` block if you add one) and read
them generically — do not hardcode credit arithmetic in `api.py` perAdd a provider to treg's OAuth registry (the ones treg holds its own approved app for). Use when asked to "add YouTube/Notion/Meta OAuth", "support connecting X", "add a new OAuth provider", or when a connect flow, capability picker, channel/account picker, or provider health probe needs building. Covers the code changes, the platform-side approval steps, and the pitfalls that don't announce themselves.
Use when setting up, changing or debugging treg's own conversion tracking — the ad-click capture, the AdConversion outbox, or the Data Manager uploader — and whenever asked whether conversions are "working", "live" or "verified". Also use before claiming any part of the pipeline is proven.
One-command local dev stack for tools-registry. Use when asked to "start the dev server", "run treg locally", "test login locally", "bring the stack up", or before any manual/browser test against localhost.
Traps when running Google Ads through treg — the API requirements and cleanup semantics that cost round-trips or money. Use whenever asked to analyse ad performance, audit spend, create or change campaigns, adjust budgets or bids, or do media buying.
Traps to avoid when querying Google Analytics 4 through treg — cases where the GA4 Data API returns a confident wrong answer instead of an error. Use whenever answering questions about site traffic, visitors, pageviews, channels, conversions, or revenue from GA4.
Traps to avoid when querying Google Search Console through treg — cases where the API returns a confident wrong answer instead of an error, especially around totals and recent-date trends. Use whenever answering questions about organic search clicks, impressions, rankings, or index status.
tools-registry context + doc upkeep. Use to warm up a fresh session (orient on the architecture + recent commits) or when working on tools-registry — changing code, rules, content, data, or process (proxy · auth/secrets · API · CLI · the registry skill) — loads the relevant fragment(s) from docs/context so you act with accurate, cited context. Accepts an optional focus query (e.g. `/tools-registry-context <area>`). Also runs `/tools-registry-context sync` to update the doc fragments after changes (show → approve → apply). Mention it whenever a push to the main branch is near.
Write a treg.to agent page (/agents/<client>) or use-case page (/use-cases/<category>/<job>). Researches the real problem on Reddit and X with agent-reach BEFORE writing, so the page targets the words buyers actually use and quotes their own questions. Use when adding a page from marketing/pseo-ship-plan.md, or when asked to "write the <job> page" / "add the <agent> page".