mirror of
https://github.com/superdesigndev/treg.git
synced 2026-10-02 03:24:35 +08:00
feat(catalog): add You.com BYOK and platform tools
This commit is contained in:
@@ -270,6 +270,7 @@ Regenerate via `scripts/build-map.py`.
|
||||
| `src/treg/catalog/apify.yaml` | architecture/catalog.md |
|
||||
| `src/treg/catalog/aviato.yaml` | architecture/catalog.md |
|
||||
| `src/treg/catalog/brightdata.yaml` | architecture/catalog.md |
|
||||
| `src/treg/catalog/capabilities.yaml` | architecture/catalog.md |
|
||||
| `src/treg/catalog/cloro.yaml` | architecture/catalog.md |
|
||||
| `src/treg/catalog/companyenrich.yaml` | architecture/catalog.md |
|
||||
| `src/treg/catalog/contracts.yaml` | architecture/catalog.md |
|
||||
@@ -312,6 +313,8 @@ Regenerate via `scripts/build-map.py`.
|
||||
| `src/treg/catalog/examples/wiza.people.email.find.terminal.json` | architecture/catalog.md |
|
||||
| `src/treg/catalog/examples/wiza.people.phone.find.json` | architecture/catalog.md |
|
||||
| `src/treg/catalog/examples/wiza.people.phone.find.terminal.json` | architecture/catalog.md |
|
||||
| `src/treg/catalog/examples/you.web.contents.json` | architecture/catalog.md |
|
||||
| `src/treg/catalog/examples/you.web.search.json` | architecture/catalog.md |
|
||||
| `src/treg/catalog/fetchinio.yaml` | architecture/catalog.md |
|
||||
| `src/treg/catalog/financialdatasets.yaml` | architecture/catalog.md |
|
||||
| `src/treg/catalog/fishaudio.yaml` | architecture/catalog.md |
|
||||
@@ -352,6 +355,7 @@ Regenerate via `scripts/build-map.py`.
|
||||
| `src/treg/catalog/trestleiq.yaml` | architecture/catalog.md |
|
||||
| `src/treg/catalog/trykitt.yaml` | architecture/catalog.md |
|
||||
| `src/treg/catalog/wiza.yaml` | architecture/catalog.md |
|
||||
| `src/treg/catalog/you.yaml` | architecture/catalog.md |
|
||||
| `src/treg/cli.py` | architecture/hub.md, architecture/instagram-oauth.md, interface/cli.md, interface/onboarding.md, interface/shell.md |
|
||||
| `src/treg/cli_analytics.py` | interface/cli.md |
|
||||
| `src/treg/client_identity.py` | architecture/import-boundaries.md, architecture/proxy-model.md, interface/api.md |
|
||||
@@ -515,6 +519,7 @@ Regenerate via `scripts/build-map.py`.
|
||||
| `src/treg/web/logos/predictleads.svg` | interface/enrich-arena.md |
|
||||
| `src/treg/web/logos/thecompaniesapi.svg` | interface/enrich-arena.md |
|
||||
| `src/treg/web/logos/tomba.svg` | interface/enrich-arena.md |
|
||||
| `src/treg/web/logos/you.svg` | architecture/catalog.md |
|
||||
| `src/treg/web/media/astra/page.css` | interface/seo.md |
|
||||
| `src/treg/web/media/astra/page.js` | interface/seo.md |
|
||||
| `src/treg/web/media/jev/signals.json` | interface/seo.md |
|
||||
@@ -630,7 +635,7 @@ Regenerate via `scripts/build-map.py`.
|
||||
| `architecture/ads-conversions.md` | `adsconv.py`, `signup.py`, `adtrack.js`, `gtag.js` |
|
||||
| `architecture/archive.md` | `archive.py`, `hunter.yaml`, `results.py`, `0031_archive_result_admission.py`, `test_cache_result_admission.py`, `archive_bodies.py`, `config.py`, `object_store.py`, `0032_archive_body_storage.py`, `test_archive_r2.py`, `fake_object_store.py`, `smoke_archive_r2.py`, `0002_archive_tables.py`, `0003_callrecord_cached.py`, `0004_archivekey_request_shape.py`, `0011_callrecord_archive_link.py`, `service.py`, `settle.py`, `0039_archive_own_key_and_repeat_pricing.py`, `backfill_call_archive_links.py`, `api.py`, `bootstrap.py`, `admin.py`, `asynctasks.py` |
|
||||
| `architecture/auth-secrets.md` | `injectors.py`, `ssrf.py`, `crypto.py`, `oauth.py`, `__init__.py`, `authorization.py`, `oauth_flow.py`, `refresh.py`, `oauth_exchange.py`, `oauth_refresh.py`, `oauth_providers.py`, `session.js`, `keys.js`, `TeamPage.vue`, `health.py`, `connect.py`, `0051_context_dev_tool_host.py`, `connections.py`, `resources.py`, `__init__.py`, `bindings.py`, `bundles.py`, `api_keys.py`, `access.py`, `api_keys.py`, `test_api_keys.py`, `test_oauth_refresh.py`, `test_financialdatasets.py`, `test_key_providers.py`, `config.py` |
|
||||
| `architecture/catalog.md` | `fetchinio.yaml`, `fetchinio.svg`, `fetchinio.linkedin.user.profile.json`, `fetchinio.linkedin.company.profile.json`, `fetchinio.linkedin.user.posts.json`, `fetchinio.linkedin.user.reactions.json`, `fetchinio.linkedin.post.comments.json`, `fetchinio.linkedin.post.reactions.json`, `fetchinio.linkedin.post.engagement.json`, `fishaudio.yaml`, `fishaudio.tts.s2-1-pro.json`, `fishaudio.voices.create.json`, `fishaudio.voices.discover.json`, `provider_resources.py`, `provider_resources.py`, `provider_resources.py`, `tavily.yaml`, `linkup.yaml`, `linkup.svg`, `linkup.web.search.json`, `linkup.web.fetch.json`, `linkup.web.fetch.structured.json`, `linkup.web.answer.json`, `linkup.web.answer.status.json`, `keenable.yaml`, `olostep.yaml`, `tinyfish.yaml`, `tinyfish.web.search.json`, `tinyfish.web.search.news.json`, `tinyfish.web.search.publications.json`, `tinyfish.web.fetch.json`, `tinyfish.web.agent.run.json`, `tinyfish.web.agent.run.get.json`, `tinyfish.web.agent.run.cancel.json`, `test_tinyfish.py`, `exa.yaml`, `anyapi.extended.yaml`, `adyntel.yaml`, `adyntel.meta-ads.library.advertiser.json`, `adyntel.meta-ads.library.search.json`, `adyntel.linkedin.search.ads.company.json`, `adyntel.linkedin.search.ads.keyword.json`, `adyntel.google.ads.transparency.json`, `adyntel.tiktok-ads.library.search.company.json`, `adyntel.google.domain.keywords.overview.json`, `adyntel.svg`, `trestleiq.yaml`, `financialdatasets.yaml`, `test_financialdatasets.py`, `quickenrich.yaml`, `influencersclub.yaml`, `quickenrich.extended.yaml`, `trykitt.yaml`, `contracts.yaml`, `millionverifier.yaml`, `adapters.yaml`, `prospeo.yaml`, `test_route_cost_ceiling.py`, `tomba.yaml`, `__init__.py`, `contracts.py`, `paths.py`, `plan.py`, `synthetic.py`, `async_bridge.py`, `route.py`, `wiza.yaml`, `wiza.people.email.find.json`, `wiza.people.email.find.terminal.json`, `wiza.people.phone.find.json`, `wiza.people.phone.find.terminal.json`, `test_routing.py`, `test_wiza.py`, `catalog-drift.yml`, `catalog_drift.py`, `catalog_ingest.py`, `catalog_validate.py`, `aliases.yaml`, `fx.yaml`, `cloro.yaml`, `aviato.yaml`, `crustdata.yaml`, `google-search-console.yaml`, `google-search-console.extended.yaml`, `google-tag-manager.yaml`, `google-tag-manager.extended.yaml`, `instagram.yaml`, `instagram.extended.yaml`, `justoneapi.extended.yaml`, `minimax.yaml`, `apify.yaml`, `brightdata.yaml`, `companyenrich.yaml`, `oceanio.yaml`, `akta.extended.yaml`, `dataforseo.yaml`, `dataforseo.extended.yaml`, `scrapecreators.yaml`, `scrapecreators.extended.yaml`, `serpapi.yaml`, `serpapi.extended.yaml`, `diffbot.yaml`, `diffbot.extended.yaml`, `tikhub.extended.yaml`, `lusha.extended.yaml`, `openrouter.yaml`, `openrouter.extended.yaml`, `replicate.yaml`, `replicate.extended.yaml`, `reapi.yaml`, `piapi.yaml`, `__init__.py`, `store.py`, `hunter.yaml`, `mcp.py`, `settlement.py`, `stats.py`, `catalog_observations.py`, `catalog_stats.py`, `0038_endpoint_day_stats.py`, `catalog.py`, `test_aigc_pr_b.py`, `test_catalog_api.py`, `test_catalog_validate.py` |
|
||||
| `architecture/catalog.md` | `fetchinio.yaml`, `fetchinio.svg`, `fetchinio.linkedin.user.profile.json`, `fetchinio.linkedin.company.profile.json`, `fetchinio.linkedin.user.posts.json`, `fetchinio.linkedin.user.reactions.json`, `fetchinio.linkedin.post.comments.json`, `fetchinio.linkedin.post.reactions.json`, `fetchinio.linkedin.post.engagement.json`, `fishaudio.yaml`, `fishaudio.tts.s2-1-pro.json`, `fishaudio.voices.create.json`, `fishaudio.voices.discover.json`, `provider_resources.py`, `provider_resources.py`, `provider_resources.py`, `tavily.yaml`, `linkup.yaml`, `you.yaml`, `you.web.search.json`, `you.web.contents.json`, `you.svg`, `linkup.svg`, `linkup.web.search.json`, `linkup.web.fetch.json`, `linkup.web.fetch.structured.json`, `linkup.web.answer.json`, `linkup.web.answer.status.json`, `keenable.yaml`, `olostep.yaml`, `tinyfish.yaml`, `tinyfish.web.search.json`, `tinyfish.web.search.news.json`, `tinyfish.web.search.publications.json`, `tinyfish.web.fetch.json`, `tinyfish.web.agent.run.json`, `tinyfish.web.agent.run.get.json`, `tinyfish.web.agent.run.cancel.json`, `test_tinyfish.py`, `exa.yaml`, `anyapi.extended.yaml`, `adyntel.yaml`, `adyntel.meta-ads.library.advertiser.json`, `adyntel.meta-ads.library.search.json`, `adyntel.linkedin.search.ads.company.json`, `adyntel.linkedin.search.ads.keyword.json`, `adyntel.google.ads.transparency.json`, `adyntel.tiktok-ads.library.search.company.json`, `adyntel.google.domain.keywords.overview.json`, `adyntel.svg`, `trestleiq.yaml`, `financialdatasets.yaml`, `test_financialdatasets.py`, `quickenrich.yaml`, `influencersclub.yaml`, `quickenrich.extended.yaml`, `trykitt.yaml`, `contracts.yaml`, `millionverifier.yaml`, `adapters.yaml`, `capabilities.yaml`, `prospeo.yaml`, `test_route_cost_ceiling.py`, `tomba.yaml`, `__init__.py`, `contracts.py`, `paths.py`, `plan.py`, `synthetic.py`, `async_bridge.py`, `route.py`, `wiza.yaml`, `wiza.people.email.find.json`, `wiza.people.email.find.terminal.json`, `wiza.people.phone.find.json`, `wiza.people.phone.find.terminal.json`, `test_routing.py`, `test_wiza.py`, `catalog-drift.yml`, `catalog_drift.py`, `catalog_ingest.py`, `catalog_validate.py`, `aliases.yaml`, `fx.yaml`, `cloro.yaml`, `aviato.yaml`, `crustdata.yaml`, `google-search-console.yaml`, `google-search-console.extended.yaml`, `google-tag-manager.yaml`, `google-tag-manager.extended.yaml`, `instagram.yaml`, `instagram.extended.yaml`, `justoneapi.extended.yaml`, `minimax.yaml`, `apify.yaml`, `brightdata.yaml`, `companyenrich.yaml`, `oceanio.yaml`, `akta.extended.yaml`, `dataforseo.yaml`, `dataforseo.extended.yaml`, `scrapecreators.yaml`, `scrapecreators.extended.yaml`, `serpapi.yaml`, `serpapi.extended.yaml`, `diffbot.yaml`, `diffbot.extended.yaml`, `tikhub.extended.yaml`, `lusha.extended.yaml`, `openrouter.yaml`, `openrouter.extended.yaml`, `replicate.yaml`, `replicate.extended.yaml`, `reapi.yaml`, `piapi.yaml`, `__init__.py`, `store.py`, `hunter.yaml`, `mcp.py`, `settlement.py`, `stats.py`, `catalog_observations.py`, `catalog_stats.py`, `0038_endpoint_day_stats.py`, `catalog.py`, `test_aigc_pr_b.py`, `test_catalog_api.py`, `test_catalog_validate.py` |
|
||||
| `architecture/composition.md` | `bootstrap.py`, `bootstrap_handlers.py`, `bootstrap_http.py`, `call_surface.py`, `connect.py`, `mcp_oauth.py`, `session.py`, `admin.py`, `auth.py`, `billing.py`, `call.py`, `connections.py`, `onboard.py`, `orgs.py`, `resources.py`, `referrals.py`, `web.py`, `dump_surface.py`, `test_app_roles.py` |
|
||||
| `architecture/data-model.md` | `0042_pinned_read_scope.py`, `alembic.ini`, `env.py`, `0001_baseline_current_schema.py`, `0002_archive_tables.py`, `0003_callrecord_cached.py`, `0004_archivekey_request_shape.py`, `0005_capacity_policy_snapshot.py`, `0006_overflow_route.py`, `0007_overflow_spend.py`, `0008_org_platform_overflow_disabled.py`, `0009_callrecord_hit.py`, `0017_async_task_record.py`, `0018_async_resource_ownership.py`, `0019_async_poll_failures.py`, `0020_callrecord_created_at_indexes.py`, `0021_ledgerentry_org_created_at_index.py`, `0022_org_spent_today_counter.py`, `0023_callrecord_org_user_created_at_index.py`, `0024_membership_calls_today_counter.py`, `0027_enrich_arena.py`, `0028_arena_insights.py`, `0029_arena_verification_snapshot.py`, `0011_callrecord_archive_link.py`, `0015_idempotentcall_membership_cascade.py`, `0034_managed_api_keys.py`, `0035_default_key_generation.py`, `0036_activity_key_indexes.py`, `0038_endpoint_day_stats.py`, `maintenance.py`, `sitetrack.js`, `models.py`, `0031_archive_result_admission.py`, `0032_archive_body_storage.py`, `0039_archive_own_key_and_repeat_pricing.py`, `0043_provider_resources.py`, `provider_resources.py`, `provider_resources.py`, `0033_signup_promo_eligibility.py`, `0041_searchlog.py`, `timeutil.py`, `db.py`, `referrals.py`, `audit.py`, `evidence_retention.py`, `analytics.py`, `bootstrap_handlers.py`, `ratestore.py`, `auth.py`, `test_postgres_reset.py`, `test_alembic_expand_safety.py`, `test_api_keys.py` |
|
||||
| `architecture/feedback.md` | `feedback_contract.py`, `__init__.py`, `reports.py`, `reviews.py`, `verdicts.py`, `hints.py`, `config.py`, `call.py`, `invite.py`, `kv.py`, `feedback.py`, `feedback.py`, `0025_feedback.py`, `0026_callreview.py`, `0030_feedback_handling.py`, `test_feedback_handling_schema.py`, `feedback.md`, `test_feedback.py`, `test_reviews.py`, `test_endpoint_verdicts.py`, `test_hints.py`, `test_kv.py` |
|
||||
|
||||
@@ -20,6 +20,10 @@ sources:
|
||||
- src/treg/routers/provider_resources.py
|
||||
- src/treg/catalog/tavily.yaml
|
||||
- src/treg/catalog/linkup.yaml
|
||||
- src/treg/catalog/you.yaml
|
||||
- src/treg/catalog/examples/you.web.search.json
|
||||
- src/treg/catalog/examples/you.web.contents.json
|
||||
- src/treg/web/logos/you.svg
|
||||
- src/treg/web/logos/linkup.svg
|
||||
- src/treg/catalog/examples/linkup.web.search.json
|
||||
- src/treg/catalog/examples/linkup.web.fetch.json
|
||||
@@ -58,6 +62,7 @@ sources:
|
||||
- src/treg/catalog/contracts.yaml
|
||||
- src/treg/catalog/millionverifier.yaml
|
||||
- src/treg/catalog/adapters.yaml
|
||||
- src/treg/catalog/capabilities.yaml
|
||||
- src/treg/catalog/prospeo.yaml
|
||||
- tests/test_route_cost_ceiling.py
|
||||
- src/treg/catalog/tomba.yaml
|
||||
|
||||
@@ -541,6 +541,7 @@ Provider-specific calculation stays outside the faithful relay.
|
||||
| Serpstat | An `error` envelope (bad token, exhausted limit, "Data not found") is free; otherwise rows in `result.data[]`, or `result.data.top[]` for `getKeywordTop`, floored at the documented 1-credit minimum on an empty list; any other response shape settles at the estimate |
|
||||
| TheCompaniesAPI companies search | `simplified=true` is free on endpoints that declare it in `input.queryParams`; otherwise one credit per company in `companies[]`, capped at the requested `size` |
|
||||
| Findymail employee search | One finder credit per contact in the returned list (`_rows_billed_micro`); an empty list is a free miss where the estimate used to bill the hold |
|
||||
| You.com Contents | Reserve for each requested URL, then count objects in the returned bare array at the frozen per-page price, capped at the hold. An unreadable response keeps the estimate. Search modes that may trigger live page fetches stay BYOK because the response does not identify the billed pages |
|
||||
|
||||
Bright Data snapshot downloads are billable per result, including repeat downloads. Gzip or a
|
||||
buffer-truncated response falls back to the estimate because the record count is unknown.
|
||||
|
||||
@@ -101,6 +101,14 @@ has separate one-per-second guidance; the provider-wide request spacer is not a
|
||||
submissions share the Search and Fetch allowance. HTTP 429 can mean depleted credit or too much
|
||||
concurrency, so no generic 429 capacity-exhausted signature is registered.
|
||||
|
||||
You.com's internal collector reads `GET /v1/billing/account_balance` with the platform
|
||||
`X-API-Key` and converts the finite nonnegative cent balance to USD. This free read also verifies
|
||||
connected keys and stays out of the catalog. The shared-key policy is `cash / auto_recharge / api`;
|
||||
`_RATE_LIMITS` uses the documented Finance Research pace of five requests per second as a
|
||||
provider-wide ceiling, including Search, Contents, Answer and Research calls whose documented
|
||||
endpoint limits are higher. BYOK calls bypass shared-key smoothing and treg metering. The API
|
||||
balance can lag recent calls, so capacity snapshots are not a per-call charge record.
|
||||
|
||||
ScrapeGraphAI's internal collector calls the free `GET /api/credits` route with the platform
|
||||
`SGAI-APIKEY`. It accepts only a finite nonnegative `remaining` credit balance and retains the plan,
|
||||
used-credit count, and crawl/monitor job quotas as informational notes. The policy is
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: treg
|
||||
description: Reach for this first for external or live data. 3,700+ endpoints across 99 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
description: Reach for this first for external or live data. 3,700+ endpoints across 100 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
---
|
||||
|
||||
## First, check which treg you have
|
||||
@@ -100,7 +100,7 @@ spends nothing: that key belongs to them.
|
||||
|
||||
## Task — the catalog: what treg can do for you (start here)
|
||||
|
||||
3,700+ catalogued endpoints across 99 providers, grouped by what they DO: keyword & rank tracking,
|
||||
3,700+ catalogued endpoints across 100 providers, grouped by what they DO: keyword & rank tracking,
|
||||
backlinks & authority, AI visibility, trending & discovery, publishing to the team's own social
|
||||
accounts, people & company enrichment, ads management & creative, measurement, video & image
|
||||
generation.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: treg
|
||||
description: Reach for this first for external or live data. 3,700+ endpoints across 99 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
description: Reach for this first for external or live data. 3,700+ endpoints across 100 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
---
|
||||
|
||||
## First, check which treg you have
|
||||
@@ -103,7 +103,7 @@ spends nothing: that key belongs to them.
|
||||
|
||||
## Task — the catalog: what treg can do for you (start here)
|
||||
|
||||
3,700+ catalogued endpoints across 99 providers, grouped by what they DO: keyword & rank tracking,
|
||||
3,700+ catalogued endpoints across 100 providers, grouped by what they DO: keyword & rank tracking,
|
||||
backlinks & authority, AI visibility, trending & discovery, publishing to the team's own social
|
||||
accounts, people & company enrichment, ads management & creative, measurement, video & image
|
||||
generation.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: treg
|
||||
description: Reach for this first for external or live data. 3,700+ endpoints across 99 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
description: Reach for this first for external or live data. 3,700+ endpoints across 100 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
version: 0.22.0
|
||||
---
|
||||
|
||||
@@ -84,7 +84,7 @@ spends nothing: that key belongs to them.
|
||||
|
||||
## Task — the catalog: what treg can do for you (start here)
|
||||
|
||||
3,700+ catalogued endpoints across 99 providers, grouped by what they DO: keyword & rank tracking,
|
||||
3,700+ catalogued endpoints across 100 providers, grouped by what they DO: keyword & rank tracking,
|
||||
backlinks & authority, AI visibility, trending & discovery, publishing to the team's own social
|
||||
accounts, people & company enrichment, ads management & creative, measurement, video & image
|
||||
generation.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: treg
|
||||
description: Reach for this first for external or live data. 3,700+ endpoints across 99 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
description: Reach for this first for external or live data. 3,700+ endpoints across 100 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
version: 0.22.0
|
||||
---
|
||||
|
||||
@@ -98,7 +98,7 @@ spends nothing: that key belongs to them.
|
||||
|
||||
## Task — the catalog: what treg can do for you (start here)
|
||||
|
||||
3,700+ catalogued endpoints across 99 providers, grouped by what they DO: keyword & rank tracking,
|
||||
3,700+ catalogued endpoints across 100 providers, grouped by what they DO: keyword & rank tracking,
|
||||
backlinks & authority, AI visibility, trending & discovery, publishing to the team's own social
|
||||
accounts, people & company enrichment, ads management & creative, measurement, video & image
|
||||
generation.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: treg
|
||||
description: Reach for this first for external or live data. 3,700+ endpoints across 99 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
description: Reach for this first for external or live data. 3,700+ endpoints across 100 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
version: 0.22.0
|
||||
---
|
||||
|
||||
@@ -82,7 +82,7 @@ spends nothing: that key belongs to them.
|
||||
|
||||
## Task — the catalog: what treg can do for you (start here)
|
||||
|
||||
3,700+ catalogued endpoints across 99 providers, grouped by what they DO: keyword & rank tracking,
|
||||
3,700+ catalogued endpoints across 100 providers, grouped by what they DO: keyword & rank tracking,
|
||||
backlinks & authority, AI visibility, trending & discovery, publishing to the team's own social
|
||||
accounts, people & company enrichment, ads management & creative, measurement, video & image
|
||||
generation.
|
||||
|
||||
@@ -481,6 +481,10 @@ def _observed_cost_micro(mk: MarketplaceCall, body: bytes, headers=None) -> int
|
||||
doc = json.loads(body)
|
||||
except (ValueError, UnicodeDecodeError):
|
||||
return 0 if provider == "contactout" else None
|
||||
if provider == "you" and mk.endpoint_id == "you.web.contents" and mk.cost_type == "per_result":
|
||||
# Contents returns one object per fetched page as a bare array. The request's URL count
|
||||
# bounds the hold; count only pages the provider actually returned.
|
||||
return _rows_billed_micro(mk, ep, len(doc) if isinstance(doc, list) else None)
|
||||
if provider == "apify" and mk.cost_type == "per_result" and mk.unit_micro > 0:
|
||||
# DERIVED: run-sync-get-dataset-items answers the bare dataset array, one billed event per
|
||||
# row, and the run's start or compute charge is the catalog's flat `call_fee`. Apify's own
|
||||
|
||||
@@ -2643,6 +2643,12 @@ adapters:
|
||||
miss: "coalesce(output.data.suggestions, []) == []"
|
||||
|
||||
# ---- open web -----------------------------------------------------------------------------
|
||||
you.web.search:
|
||||
accepts: [[q]]
|
||||
in: {q: body.query}
|
||||
in_expr: {body.count: limit}
|
||||
out: {results: results.web, count: "len(results.web)"}
|
||||
miss: "coalesce(results.web, []) == []"
|
||||
tinyfish.web.search:
|
||||
accepts: [[q]]
|
||||
in: {q: queryParams.query}
|
||||
@@ -2710,6 +2716,13 @@ adapters:
|
||||
out: {results: results, count: "len(results)"}
|
||||
miss: "coalesce(results, []) == []"
|
||||
|
||||
you.web.contents:
|
||||
accepts: [[url]]
|
||||
in_expr: {body.urls: "list(url)"}
|
||||
test_identity: {url: "https://example.com"}
|
||||
const: {body.formats: [markdown]}
|
||||
out: {pages: ".", count: "len(.)"}
|
||||
miss: ". == []"
|
||||
tinyfish.web.fetch:
|
||||
accepts: [[url]]
|
||||
in_expr: {body.urls: "list(url)"}
|
||||
|
||||
@@ -183,6 +183,7 @@ capabilities:
|
||||
web.search.news: "Search recent news articles by topic"
|
||||
web.search.publications: "Search research papers and publications"
|
||||
web.answer: "Answer a question from live web research, with cited sources"
|
||||
web.answer.status: "Check a web research task"
|
||||
|
||||
# --- Social -----------------------------------------------------------------------------------
|
||||
tiktok.user.profile: "Get a user's public profile"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
[
|
||||
{
|
||||
"url": "https://example.com",
|
||||
"metadata": {
|
||||
"site_name": "",
|
||||
"favicon_url": "https://api.ydc-index.io/favicon?domain=example.com&size=128"
|
||||
},
|
||||
"markdown": "This domain is for use in documentation examples without needing permission. Avoid use in operations.\n\nLearn more",
|
||||
"title": "Example Domain"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"results": {
|
||||
"web": [
|
||||
{
|
||||
"url": "http://example.com/",
|
||||
"title": "Example Domain",
|
||||
"description": "This domain is for use in documentation examples without needing permission.",
|
||||
"favicon_url": "https://you.com/favicon?domain=example.com&size=128",
|
||||
"snippets": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"search_uuid": "8d49dfc3-2dab-4d9f-b8b4-8de5cdfca0b9",
|
||||
"latency": 0.0011415150947868824,
|
||||
"query": "site:example.com Example Domain"
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ pricing_url: https://docs.linkup.so/pages/documentation/platform/pricing
|
||||
limits: "Search and Fetch allow 10 requests/second per organization. Research polling should not exceed one request/second. HTTP 429 can mean insufficient credit or excess concurrency."
|
||||
proposed_capabilities:
|
||||
web.extract.structured: Extract typed JSON from one web page
|
||||
web.answer.status: Check a web research task
|
||||
|
||||
endpoints:
|
||||
- id: linkup.web.search
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
provider: you
|
||||
source:
|
||||
docs: https://you.com/docs/welcome
|
||||
curated: '2026-09-29'
|
||||
pricing_url: https://you.com/docs/administration/billing
|
||||
limits: "Self-serve Search, Contents, Answer and Research allow 10 requests/s each; Finance Research allows 5 requests/s. Enterprise limits may differ. Successful live responses did not include the documented rate-limit headers."
|
||||
proposed_capabilities:
|
||||
web.answer.research: "Research a question across multiple web sources"
|
||||
stocks.research: "Research a financial question with cited sources"
|
||||
|
||||
endpoints:
|
||||
- id: you.web.search
|
||||
capability: web.search
|
||||
platform: web
|
||||
domain: search
|
||||
scope: any_account
|
||||
method: POST
|
||||
host: ydc-index.io
|
||||
path: /v1/search
|
||||
body_allowlist: true
|
||||
name: Search the web and news
|
||||
summary: Return ranked web and news results with snippets and metadata.
|
||||
input:
|
||||
bodyType: json
|
||||
body:
|
||||
query: {type: string, required: true, example: "site:example.com Example Domain"}
|
||||
count: {type: integer, required: false, default: 10, min: 1, max: 100, example: 1, note: "Maximum per result section; web and news can each return this many."}
|
||||
offset: {type: integer, required: false, min: 0, max: 9}
|
||||
freshness: {type: string, required: false, note: "day | week | month | year, or YYYY-MM-DDtoYYYY-MM-DD"}
|
||||
country: {type: string, required: false, note: "Supported country code."}
|
||||
language: {type: string, required: false, note: "Supported BCP 47 language tag."}
|
||||
safesearch: {type: string, required: false, enum: [off, moderate, strict]}
|
||||
include_domains: {type: "array[string]", required: false, maxItems: 500}
|
||||
exclude_domains: {type: "array[string]", required: false, maxItems: 500}
|
||||
boost_domains: {type: "array[string]", required: false, maxItems: 500}
|
||||
knowledge: {type: string, required: false, enum: [core], note: "Include licensed structured results at no extra charge."}
|
||||
note: "For query-focused passages use you.web.search.highlights. Full-page extraction has separate cache-only and BYOK live catalog tools."
|
||||
test_request: {body: {query: "site:example.com Example Domain", count: 1}}
|
||||
cost: &search_cost
|
||||
type: per_call
|
||||
value: 0.005
|
||||
currency: USD
|
||||
unit: call
|
||||
source: docs
|
||||
source_url: https://you.com/docs/administration/billing
|
||||
checked: '2026-09-29'
|
||||
confidence: documented
|
||||
note: "One call costs $0.005 even with no matches; snippets, highlights, news and knowledge carry no add-on."
|
||||
verified: '2026-09-29'
|
||||
example_response: examples/you.web.search.json
|
||||
docs_url: https://you.com/docs/api-reference/search/v1-search
|
||||
|
||||
- id: you.web.search.highlights
|
||||
capability: web.search
|
||||
platform: web
|
||||
domain: search
|
||||
scope: any_account
|
||||
method: POST
|
||||
host: ydc-index.io
|
||||
path: /v1/search
|
||||
body_allowlist: true
|
||||
name: Search with page highlights
|
||||
summary: Return query-focused passages alongside ranked web and news results.
|
||||
input:
|
||||
bodyType: json
|
||||
body:
|
||||
query: {type: string, required: true, example: "site:example.com Example Domain"}
|
||||
count: {type: integer, required: false, default: 10, min: 1, max: 100}
|
||||
extraction:
|
||||
type: object
|
||||
required: true
|
||||
properties:
|
||||
extraction_mode: {type: string, required: true, enum: [highlights]}
|
||||
freshness: {type: string, required: false}
|
||||
country: {type: string, required: false}
|
||||
language: {type: string, required: false}
|
||||
include_domains: {type: "array[string]", required: false, maxItems: 500}
|
||||
exclude_domains: {type: "array[string]", required: false, maxItems: 500}
|
||||
platform_request: {body.extraction.extraction_mode: highlights}
|
||||
test_request: {body: {query: "site:example.com Example Domain", count: 1, extraction: {extraction_mode: highlights}}}
|
||||
cost: *search_cost
|
||||
docs_url: https://you.com/docs/guides/search/retrieve-page-content
|
||||
|
||||
- id: you.web.search.full_page.cache
|
||||
capability: web.search
|
||||
platform: web
|
||||
domain: search
|
||||
scope: any_account
|
||||
method: POST
|
||||
host: ydc-index.io
|
||||
path: /v1/search
|
||||
body_allowlist: true
|
||||
name: Search with cached page text
|
||||
summary: Return full-page content from You.com's cache when available.
|
||||
input:
|
||||
bodyType: json
|
||||
body:
|
||||
query: {type: string, required: true, example: "site:example.com Example Domain"}
|
||||
count: {type: integer, required: false, default: 10, min: 1, max: 100}
|
||||
extraction:
|
||||
type: object
|
||||
required: true
|
||||
properties:
|
||||
extraction_mode: {type: string, required: true, enum: [full_page]}
|
||||
extraction_source: {type: string, required: true, enum: [cache]}
|
||||
full_page: {type: object, required: false, note: "For example {extraction_formats: [markdown]}."}
|
||||
freshness: {type: string, required: false}
|
||||
country: {type: string, required: false}
|
||||
language: {type: string, required: false}
|
||||
include_domains: {type: "array[string]", required: false, maxItems: 500}
|
||||
exclude_domains: {type: "array[string]", required: false, maxItems: 500}
|
||||
note: "Cache-only extraction has no per-page add-on. Live and blended full-page extraction use a separate BYOK catalog tool."
|
||||
platform_request: {body.extraction.extraction_mode: full_page, body.extraction.extraction_source: cache}
|
||||
test_request: {body: {query: "site:example.com Example Domain", count: 1, extraction: {extraction_mode: full_page, extraction_source: cache, full_page: {extraction_formats: [markdown]}}}}
|
||||
cost: *search_cost
|
||||
docs_url: https://you.com/docs/guides/search/retrieve-page-content
|
||||
|
||||
- id: you.web.search.full_page.live
|
||||
capability: web.search
|
||||
platform: web
|
||||
domain: search
|
||||
scope: any_account
|
||||
method: POST
|
||||
host: ydc-index.io
|
||||
path: /v1/search
|
||||
body_allowlist: true
|
||||
platform_blocked: "Live page fetches add $0.001 per page, and You.com does not identify which pages were billed in the response. Connect your own key."
|
||||
name: Search with live page text
|
||||
summary: Return full-page content, fetching live pages when requested.
|
||||
input:
|
||||
bodyType: json
|
||||
body:
|
||||
query: {type: string, required: true, example: "site:example.com Example Domain"}
|
||||
count: {type: integer, required: false, default: 10, min: 1, max: 100}
|
||||
extraction:
|
||||
type: object
|
||||
required: true
|
||||
properties:
|
||||
extraction_mode: {type: string, required: true, enum: [full_page]}
|
||||
extraction_source: {type: string, required: true, enum: [blend, fetch]}
|
||||
full_page: {type: object, required: false, note: "For example {extraction_formats: [markdown]}."}
|
||||
note: "The $0.005 search price excludes $0.001 for each live page fetched by You.com. Your own key is billed directly by You.com."
|
||||
test_request: {body: {query: "site:example.com Example Domain", count: 1, extraction: {extraction_mode: full_page, extraction_source: blend}}}
|
||||
cost:
|
||||
type: per_call
|
||||
value: 0.005
|
||||
currency: USD
|
||||
unit: call
|
||||
source: docs
|
||||
source_url: https://you.com/docs/administration/billing
|
||||
checked: '2026-09-29'
|
||||
confidence: documented
|
||||
note: "$0.005 base search plus $0.001 for each page You.com fetches live. Your own key pays You.com directly."
|
||||
docs_url: https://you.com/docs/guides/search/retrieve-page-content
|
||||
|
||||
- id: you.web.contents
|
||||
capability: web.extract
|
||||
platform: web
|
||||
domain: extract
|
||||
scope: any_account
|
||||
method: POST
|
||||
host: ydc-index.io
|
||||
path: /v1/contents
|
||||
body_allowlist: true
|
||||
name: Extract page content
|
||||
summary: Retrieve Markdown, HTML or metadata for up to ten public URLs.
|
||||
input:
|
||||
bodyType: json
|
||||
body:
|
||||
urls: {type: "array[string]", required: true, minItems: 1, maxItems: 10, example: ["https://example.com"]}
|
||||
formats: {type: "array[string]", required: false, enum: [html, markdown, metadata], example: [markdown]}
|
||||
crawl_timeout: {type: integer, required: false, default: 10, min: 1, max: 60}
|
||||
max_age: {type: integer, required: false, min: 0, note: "Maximum age of cached content in seconds."}
|
||||
test_request: {body: {urls: ["https://example.com"], formats: [markdown]}}
|
||||
cost:
|
||||
type: per_result
|
||||
value: 0.001
|
||||
currency: USD
|
||||
unit: page
|
||||
source: docs
|
||||
source_url: https://you.com/docs/administration/billing
|
||||
checked: '2026-09-29'
|
||||
confidence: documented
|
||||
note: "$0.001 per page fetched; the hold follows the requested URL count and settles from the returned page count."
|
||||
verified: '2026-09-29'
|
||||
example_response: examples/you.web.contents.json
|
||||
docs_url: https://you.com/docs/api-reference/contents
|
||||
|
||||
- id: you.web.answer
|
||||
capability: web.answer
|
||||
platform: web
|
||||
domain: answer
|
||||
scope: any_account
|
||||
method: POST
|
||||
path: /v1/answer
|
||||
body_allowlist: true
|
||||
name: Answer a web question
|
||||
summary: Return a cited answer with the web results used to synthesize it.
|
||||
input:
|
||||
bodyType: json
|
||||
body:
|
||||
query: {type: string, required: true, maxLength: 400, example: "What is the purpose of example.com?"}
|
||||
freshness: {type: string, required: false}
|
||||
country: {type: string, required: false}
|
||||
language: {type: string, required: false}
|
||||
safesearch: {type: string, required: false, enum: [off, moderate, strict]}
|
||||
include_domains: {type: "array[string]", required: false, maxItems: 500}
|
||||
exclude_domains: {type: "array[string]", required: false, maxItems: 500}
|
||||
boost_domains: {type: "array[string]", required: false, maxItems: 500}
|
||||
test_request: {body: {query: "What is the purpose of example.com?"}}
|
||||
cost:
|
||||
type: per_call
|
||||
value: 0.005
|
||||
currency: USD
|
||||
unit: call
|
||||
source: docs
|
||||
source_url: https://you.com/docs/administration/billing
|
||||
checked: '2026-09-29'
|
||||
confidence: documented
|
||||
docs_url: https://you.com/docs/api-reference/answer/v1-answer
|
||||
|
||||
- id: you.web.research
|
||||
capability: web.answer.research
|
||||
platform: web
|
||||
domain: answer
|
||||
scope: any_account
|
||||
method: POST
|
||||
path: /v1/research
|
||||
body_allowlist: true
|
||||
name: Research a web question
|
||||
summary: Synthesize a cited web answer at lite or standard research effort.
|
||||
input:
|
||||
bodyType: json
|
||||
body:
|
||||
input: {type: string, required: true, maxLength: 40000, example: "What is the purpose of example.com?"}
|
||||
research_effort: {type: string, required: true, enum: [lite, standard], example: lite}
|
||||
source_control: {type: object, required: false, note: "Provider-native source and recency controls."}
|
||||
output_schema: {type: object, required: false, note: "Structured output is supported on standard, not lite."}
|
||||
test_request: {body: {input: "What is the purpose of example.com?", research_effort: lite}}
|
||||
cost:
|
||||
type: per_call
|
||||
table:
|
||||
- {when: {body.research_effort: lite}, value: 0.012}
|
||||
- {when: {body.research_effort: standard}, value: 0.05}
|
||||
fallback: {value: 0.05, note: "Maximum synchronous tier in this catalog tool."}
|
||||
currency: USD
|
||||
unit: call
|
||||
source: docs
|
||||
source_url: https://you.com/docs/administration/billing
|
||||
checked: '2026-09-29'
|
||||
confidence: documented
|
||||
docs_url: https://you.com/docs/api-reference/research/v1-research
|
||||
|
||||
- id: you.web.research.background
|
||||
capability: web.answer.research
|
||||
platform: web
|
||||
domain: answer
|
||||
scope: any_account
|
||||
method: POST
|
||||
path: /v1/research
|
||||
body_allowlist: true
|
||||
name: Start deep web research
|
||||
summary: Queue deep, exhaustive or frontier research and return a task handle.
|
||||
input:
|
||||
bodyType: json
|
||||
body:
|
||||
input: {type: string, required: true, maxLength: 40000, example: "What is the purpose of example.com?"}
|
||||
research_effort: {type: string, required: true, enum: [deep, exhaustive, frontier], example: deep}
|
||||
background: {type: boolean, required: true, enum: [true], example: true}
|
||||
source_control: {type: object, required: false, note: "Provider-native source and recency controls."}
|
||||
output_schema: {type: object, required: false, note: "Provider-native JSON Schema for structured output."}
|
||||
test_request: {body: {input: "What is the purpose of example.com?", research_effort: deep, background: true}}
|
||||
cost:
|
||||
type: per_success
|
||||
table:
|
||||
- {when: {body.research_effort: deep}, value: 0.10}
|
||||
- {when: {body.research_effort: exhaustive}, value: 0.45}
|
||||
- {when: {body.research_effort: frontier}, value: 1.20}
|
||||
fallback: {value: 1.20, note: "Maximum background tier in this catalog tool."}
|
||||
currency: USD
|
||||
unit: call
|
||||
source: docs
|
||||
source_url: https://you.com/docs/administration/billing
|
||||
checked: '2026-09-29'
|
||||
confidence: documented
|
||||
docs_url: https://you.com/docs/guides/research/background-requests
|
||||
async:
|
||||
id_from: task_id
|
||||
poll:
|
||||
endpoint: you.web.research.status
|
||||
param: {in: pathParams, name: task_id}
|
||||
status:
|
||||
path: status
|
||||
progress: [queued, running]
|
||||
success: [completed]
|
||||
failure: [failed, cancelled]
|
||||
result: {path: result}
|
||||
interval: 5
|
||||
|
||||
- id: you.web.research.status
|
||||
kind: utility
|
||||
capability: web.answer.status
|
||||
platform: web
|
||||
domain: answer
|
||||
scope: any_account
|
||||
method: GET
|
||||
path: /v1/research/{task_id}
|
||||
name: Check a research task
|
||||
summary: Read the status and result of a research task started by this team.
|
||||
resource_ownership:
|
||||
requires: {kind: "poll:you.web.research.status", param: task_id}
|
||||
input:
|
||||
pathParams:
|
||||
task_id: {type: string, required: true, example: "00000000-0000-4000-8000-000000000001"}
|
||||
cost: {type: free, value: 0, currency: USD, unit: call, note: "You.com publishes no separate charge for task polling."}
|
||||
docs_url: https://you.com/docs/api-reference/research/v1-research-task
|
||||
|
||||
- id: you.finance.research
|
||||
capability: stocks.research
|
||||
platform: stocks
|
||||
domain: stocks
|
||||
scope: any_account
|
||||
method: POST
|
||||
path: /v1/finance_research
|
||||
body_allowlist: true
|
||||
name: Research a financial question
|
||||
summary: Return a cited answer from You.com's finance-focused index.
|
||||
input:
|
||||
bodyType: json
|
||||
body:
|
||||
input: {type: string, required: true, maxLength: 40000, example: "What is Apple Inc.?"}
|
||||
research_effort: {type: string, required: true, enum: [deep, exhaustive], example: deep}
|
||||
note: "Finance Research has no background mode. Exhaustive work may exceed treg's default upstream timeout."
|
||||
test_request: {body: {input: "What is Apple Inc.?", research_effort: deep}}
|
||||
cost:
|
||||
type: per_call
|
||||
table:
|
||||
- {when: {body.research_effort: deep}, value: 0.11}
|
||||
- {when: {body.research_effort: exhaustive}, value: 0.50}
|
||||
fallback: {value: 0.50, note: "Maximum documented Finance Research tier."}
|
||||
currency: USD
|
||||
unit: call
|
||||
source: docs
|
||||
source_url: https://you.com/docs/administration/billing
|
||||
checked: '2026-09-29'
|
||||
confidence: documented
|
||||
docs_url: https://you.com/docs/api-reference/finance-research/v1-finance_research
|
||||
@@ -256,6 +256,7 @@ class Settings(BaseSettings):
|
||||
platform_key_exa: str = "" # x-api-key; dollar-metered ($7/1k searches, $1/1k pages); settles from costDollars.total
|
||||
platform_key_tavily: str = "" # Bearer; Search reports per-call usage, other tools settle returned successes
|
||||
platform_key_linkup: str = "" # Bearer; prepaid USD balance, request-priced Search/Fetch/Research
|
||||
platform_key_you: str = "" # X-API-Key; prepaid USD balance across You.com web APIs
|
||||
platform_key_serper: str = "" # X-API-KEY; prepaid Google search credits, exact charge in response.credits
|
||||
platform_key_keenable: str = "" # X-API-Key; $4/1,000-request package, 10 requests/s per organization
|
||||
platform_key_olostep: str = "" # Bearer; prepaid credits, platform price $0.002/credit
|
||||
|
||||
@@ -177,6 +177,21 @@ async def _linkup(c, key):
|
||||
return {"value": float(raw), "unit": "USD", "note": "prepaid credit balance"}
|
||||
|
||||
|
||||
async def _you(c, key):
|
||||
d = await _get(c, "https://api.you.com/v1/billing/account_balance",
|
||||
headers={"X-API-Key": key})
|
||||
data = d.get("data") if isinstance(d, dict) else None
|
||||
attributes = data.get("attributes") if isinstance(data, dict) else None
|
||||
raw = attributes.get("balance") if isinstance(attributes, dict) else None
|
||||
try:
|
||||
cents = Decimal(str(raw)) if raw is not None and not isinstance(raw, bool) else None
|
||||
except (InvalidOperation, ValueError):
|
||||
cents = None
|
||||
if cents is None or not cents.is_finite() or cents < 0:
|
||||
raise ValueError("You.com returned no valid account balance")
|
||||
return {"value": float(cents / 100), "unit": "USD", "note": "prepaid account balance"}
|
||||
|
||||
|
||||
async def _scrapegraphai(c, key):
|
||||
d = await _get(c, "https://v2-api.scrapegraphai.com/api/credits",
|
||||
headers={"SGAI-APIKEY": key})
|
||||
@@ -821,6 +836,7 @@ BALANCE_ROUTES = {
|
||||
"fishaudio": _fishaudio,
|
||||
"tavily": _tavily,
|
||||
"linkup": _linkup,
|
||||
"you": _you,
|
||||
"serper": _serper,
|
||||
"olostep": _olostep,
|
||||
"firecrawl": _firecrawl,
|
||||
|
||||
@@ -46,6 +46,7 @@ _KNOWN: dict[str, tuple[str, str, str]] = {
|
||||
"trestleiq": ("cash", "auto_recharge", "manual"),
|
||||
"tavily": ("credits", "manual", "api"),
|
||||
"linkup": ("cash", "manual", "api"),
|
||||
"you": ("cash", "auto_recharge", "api"),
|
||||
# The API supplies the exact credit balance; vendor auto recharge was manually enabled and
|
||||
# verified in the Serper dashboard.
|
||||
"serper": ("credits", "auto_recharge", "api"),
|
||||
@@ -130,6 +131,8 @@ _RATE_LIMITS: dict[str, dict] = {
|
||||
# ceiling on both tiers, so this provider-wide pace is safe for all four catalog tools.
|
||||
"tavily": {"limit": 100, "window_s": 60, "source": "docs"},
|
||||
"linkup": {"limit": 10, "window_s": 1, "source": "docs"},
|
||||
# Finance Research is 5/s; the other You.com APIs are 10/s. Smoothing is provider-wide.
|
||||
"you": {"limit": 5, "window_s": 1, "source": "docs"},
|
||||
# GET /account reports 50 queries/s for the current shared account. Pace the platform key to
|
||||
# that live account allowance; BYOK bypasses this limiter.
|
||||
"serper": {"limit": 50, "window_s": 1, "source": "api"},
|
||||
|
||||
@@ -2526,6 +2526,32 @@ LINKUP = OAuthProvider(
|
||||
probe_path="/v1/credits/balance",
|
||||
)
|
||||
|
||||
YOU = OAuthProvider(
|
||||
service="you",
|
||||
display_name="You.com",
|
||||
auth_kind="key",
|
||||
token_label="API key",
|
||||
token_placeholder="your You.com API key",
|
||||
token_header="X-API-Key",
|
||||
token_format="{secret}",
|
||||
setup_url="https://you.com/platform",
|
||||
setup_action_label="Get your You.com API key",
|
||||
setup_steps=(
|
||||
"Sign in to You.com Platform and create an API key.",
|
||||
"Copy the key and connect it here.",
|
||||
),
|
||||
setup_note="Search, Contents, Answer and Research use prepaid USD credit. treg checks the account balance when you connect the key.",
|
||||
auth_uri="", token_uri="",
|
||||
scopes={},
|
||||
client_id_setting="", client_secret_setting="",
|
||||
category="SEO",
|
||||
summary="Search the web, extract pages, and get cited answers or research.",
|
||||
base_url="https://api.you.com",
|
||||
catalog_targets=(CatalogTarget(host="ydc-index.io", base_url="https://ydc-index.io"),),
|
||||
docs_url="https://you.com/docs/welcome",
|
||||
probe_path="/v1/billing/account_balance",
|
||||
)
|
||||
|
||||
SERPER = OAuthProvider(
|
||||
service="serper",
|
||||
display_name="Serper",
|
||||
@@ -3630,7 +3656,7 @@ REGISTRY: dict[str, OAuthProvider] = {
|
||||
TIKHUB, BRIGHTDATA, SEMRUSH, JUSTONEAPI,
|
||||
SCRAPECREATORS,
|
||||
# SEO API-key providers
|
||||
DATAFORSEO, SERANKING, MOZ, MAJESTIC, SERPSTAT, EXA, TAVILY, LINKUP, KEENABLE, OLOSTEP, FIRECRAWL,
|
||||
DATAFORSEO, SERANKING, MOZ, MAJESTIC, SERPSTAT, EXA, TAVILY, LINKUP, YOU, KEENABLE, OLOSTEP, FIRECRAWL,
|
||||
SCRAPEGRAPHAI, SERPER, CLORO,
|
||||
# more Enrichment API-key providers
|
||||
LUSHA, CORESIGNAL, DIFFBOT, THECOMPANIESAPI, LEADMAGIC, FIBER_AI, CRUSTDATA, AVIATO,
|
||||
|
||||
@@ -175,6 +175,7 @@ CATALOG: list[dict] = [
|
||||
# --- search / scraping ---
|
||||
{"provider": "Tavily", "tokens": ["TAVILY"], "base_url": "https://api.tavily.com", "auth": {"shape": "bearer"}},
|
||||
{"provider": "Linkup", "tokens": ["LINKUP"], "base_url": "https://api.linkup.so/v1", "auth": {"shape": "bearer"}, "probe": "credits/balance"},
|
||||
{"provider": "You.com", "tokens": ["YDC_API_KEY", "YOU_API_KEY"], "base_url": "https://api.you.com", "auth": {"shape": "api_key_header", "header": "X-API-Key"}, "probe": "v1/billing/account_balance"},
|
||||
{"provider": "Keenable", "tokens": ["KEENABLE"], "base_url": "https://api.keenable.ai", "auth": {"shape": "api_key_header", "header": "X-API-Key"}},
|
||||
{"provider": "Olostep", "tokens": ["OLOSTEP"], "base_url": "https://api.olostep.com", "auth": {"shape": "bearer"}, "probe": "user/credits/info"},
|
||||
{"provider": "ScrapeGraphAI", "tokens": ["SCRAPEGRAPHAI", "SGAI"],
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="150" viewBox="0 0 150 150" role="img" aria-label="You.com">
|
||||
<rect width="150" height="150" rx="24" fill="#111827"/>
|
||||
<text x="75" y="93" fill="#fff" font-family="Arial, Helvetica, sans-serif" font-size="54" font-weight="700" text-anchor="middle">you</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 327 B |
@@ -122,6 +122,26 @@ async def test_serper_capacity_uses_free_account_balance():
|
||||
}
|
||||
|
||||
|
||||
async def test_you_balance_converts_cents_to_usd():
|
||||
def probe(request):
|
||||
assert request.method == "GET"
|
||||
assert request.url == "https://api.you.com/v1/billing/account_balance"
|
||||
assert request.headers["x-api-key"] == "test-key"
|
||||
return httpx.Response(200, json={"data": {"attributes": {"balance": "9986"}}})
|
||||
|
||||
async with httpx.AsyncClient(transport=httpx.MockTransport(probe)) as client:
|
||||
row = await collectors._you(client, "test-key")
|
||||
assert row == {"value": 99.86, "unit": "USD", "note": "prepaid account balance"}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("balance", [None, True, "bad", "NaN", "Infinity", -1])
|
||||
async def test_you_balance_rejects_uncertain_values(balance):
|
||||
async with httpx.AsyncClient(transport=httpx.MockTransport(
|
||||
lambda _request: httpx.Response(200, json={"data": {"attributes": {"balance": balance}}}))) as client:
|
||||
with pytest.raises(ValueError, match="valid account balance"):
|
||||
await collectors._you(client, "test-key")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("balance", [None, True, "bad", "NaN", "Infinity", -1])
|
||||
async def test_serper_capacity_rejects_invalid_balance(balance):
|
||||
async with httpx.AsyncClient(transport=httpx.MockTransport(
|
||||
|
||||
@@ -306,6 +306,7 @@ _UNRECORDED_SIGNATURE = {
|
||||
"serper", # funded credits remain; no provider-specific empty-balance response was forced
|
||||
"tinyfish", # funded wallet remains; no provider-specific empty-wallet response was forced
|
||||
"trestleiq", # funded wallet remains; documented 403/429 shapes do not identify empty balance
|
||||
"you", # funded wallet remains; no provider-specific empty-balance response was forced
|
||||
|
||||
"serpapi", "serpstat", "spyfu", "tiingo", "tikhub", "tomba", "twelvedata",
|
||||
}
|
||||
|
||||
@@ -427,6 +427,49 @@ async def test_diffbot_shared_key_uses_each_catalog_endpoint_host(
|
||||
assert await _balance(clients) == before - charge_micro
|
||||
|
||||
|
||||
async def test_you_shared_key_reaches_both_api_hosts_and_settles_returned_pages(
|
||||
clients: AsyncClient, monkeypatch,
|
||||
):
|
||||
monkeypatch.setenv("TREG_PLATFORM_KEY_YOU", "PLATFORM-YOU-KEY")
|
||||
monkeypatch.setenv("TREG_PLATFORM_PROVIDERS", "you")
|
||||
get_settings.cache_clear()
|
||||
outbound = []
|
||||
|
||||
def upstream(request: httpx.Request) -> httpx.Response:
|
||||
assert request.headers["x-api-key"] == "PLATFORM-YOU-KEY"
|
||||
outbound.append((request.url.host, request.url.path))
|
||||
if request.url.path == "/v1/contents":
|
||||
# The second requested page was not returned, so only one page is metered.
|
||||
body = b'[{"url":"https://example.com/a","markdown":"A"}]'
|
||||
elif request.url.path == "/v1/research":
|
||||
body = b'{"output":"Example","sources":[]}'
|
||||
else:
|
||||
body = b'{"answer":"Example","citations":[]}'
|
||||
return httpx.Response(200, stream=httpx.ByteStream(body),
|
||||
headers={"content-type": "application/json"})
|
||||
|
||||
await A.app.state.http.aclose()
|
||||
A.app.state.http = AsyncClient(transport=httpx.MockTransport(upstream))
|
||||
try:
|
||||
before = await _balance(clients)
|
||||
pages = await clients.post("/call/you.web.contents", json={
|
||||
"urls": ["https://example.com/a", "https://example.com/b"], "formats": ["markdown"],
|
||||
})
|
||||
answer = await clients.post("/call/you.web.answer", json={"query": "What is example.com?"})
|
||||
research = await clients.post("/call/you.web.research", json={
|
||||
"input": "What is example.com?", "research_effort": "lite",
|
||||
})
|
||||
assert pages.status_code == 200, pages.text
|
||||
assert answer.status_code == 200, answer.text
|
||||
assert research.status_code == 200, research.text
|
||||
assert outbound == [("ydc-index.io", "/v1/contents"),
|
||||
("api.you.com", "/v1/answer"),
|
||||
("api.you.com", "/v1/research")]
|
||||
assert await _balance(clients) == before - 1_000 - 5_000 - 12_000
|
||||
finally:
|
||||
get_settings.cache_clear()
|
||||
|
||||
|
||||
async def test_diffbot_unapproved_catalog_host_fails_before_relay_or_reserve(
|
||||
clients: AsyncClient, diffbot_platform_on, monkeypatch,
|
||||
):
|
||||
|
||||
Reference in New Issue
Block a user