Let both SDKs search the catalog by scope with no query - #30
Merged
Conversation
GET /catalog/search takes any non-empty combination of q, category and platform. Both readers typed query as required and always set q, so "every reddit API" or "everything in the social category" was expressible against the gateway and against MCP and impossible through the SDKs. query is now optional in TypeScript SearchOptions and in the Python sync and async clients. Every existing call site keeps compiling and sends the same request: q is set exactly when there is a query to send. An absent or empty query omits q entirely rather than sending it empty, because an empty q is a different request. A call naming none of the three never reaches the gateway to earn a 400. Both readers raise AnyAPIError with status 0, the status this repository already uses for a caller error detected before any HTTP. The credentialless live discovery canaries now make a scope-only call against production in both languages, so CI proves the capability on the source tree rather than only in a mock. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
kev1n
added a commit
that referenced
this pull request
Sep 6, 2026
The first catalog refresh since v0.35.3 on 2026-09-01. Every regen run since then classified blocked, so both packages have been carrying a five-day-old catalog. v0.36.0 bumped versions alongside #30 but did not refresh the catalog, so this is the first release that closes the gap. anyapi#940 merged three minutes after the last green regen and started it; six more shipped changes stacked up behind it. The classifier is right to stop: two published fields disappear. Both are deliberate, both are already live, and each item is reviewed here against the gateway PR that made it. Blocked, with the slugs the machine summary omits: - twitter.search: input.lang removed (anyapi#940). Deliberate retirement. `lang` was declared absent on all three cheap lanes, so sending it collapsed the SKU to one apify lane at 9x the price; X honours `lang:` inside the query, so the gateway now folds it into `query` before validation. A caller who still sends it keeps working against the API and reaches every lane. The generated field is gone, so a TypeScript caller passing it no longer compiles. - youtube.search_hashtag: input.type enum member "shorts" removed (anyapi#961). Deliberate: no source we buy returns a Shorts row with the channel and publish time this endpoint requires, so the member could never be served. - youtube.channel_shorts: output.shorts[].title is no longer required (anyapi#1023). A loosening to match what the lanes actually return. - company_enrichment.crustdata_v3: output `name` is no longer required (anyapi#1044). Same shape of fix: one junk row with a null field was aborting the whole transform and losing the page it arrived on. - tiktok.video_transcript_full: output confidence numeric bounds removed (anyapi#1023). The recognizer reports a negative log-scale score on audio it could not align, so 0 to 1 was never true. Bounds are doc-only in the emitters. - yelp.search: input.limit default 20 recorded (anyapi#1003). The description already documented it. Its price also drops from $0.0605 to $0.0035 per request, from the litescrape lane. - tiktok.video: input required fields changed (anyapi#1030). `id` joins `url` under anyOf, so both emit optional, matching youtube.video. Minor rather than patch by the repo's own ladder: a new SKU (youtube.search_shorts) and new optional fields (threads.search startDate/endDate, tiktok.video id) each earn a minor on their own, and the two removals are why it needed a human. Gate: pnpm check exit 0; pyright and mypy clean; 499 pytest tests pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was broken
GET /catalog/searchaccepts any non-empty combination ofq,categoryandplatform. Measured against production today:Both SDKs were stricter:
querywas typed as required andqwas set unconditionally. So "every reddit API" or "everything in the social category" was expressible against the gateway and against MCP, and impossible through either SDK. Gateway PR getanyapi-com/anyapi#1013 relaxed the MCP side; the SDKs were never updated.What changed
queryis optional in TypeScriptSearchOptionsand in the Python sync and asyncsearch(). Every existing call site keeps compiling and sends the identical request.qis set exactly when there is a query. An absent or empty query omitsqfrom the query string rather than sending it empty, because an emptyqis a different request.AnyAPIErrorwith status0, the status this repository already uses for a caller error detected before any HTTP (see the missing-API-key path)._account.search_requestbuilder, so the sync and async clients have one owner for the rule.SPEC.mdrecords the rule beside thesearch(options)contract.No generated code,
openapi.json,catalog.jsonor IR was touched. The tolerant-reader rules are unchanged: the readers still rejectcreditkeys and any non-AnyAPIprovider, and derive nothing. A scope-only response is the same envelope withranking: "keyword", which both readers already accepted.Proof
pnpm check(dash guard, release tests, regen drift, generator, TypeScript, consumer-typecheck): EXIT=0, generator 158 tests, TypeScript 471 tests.cd packages/python && pyright && mypy && pytest: pyright 0 errors, mypy clean on 86 source files, 498 tests passed.New regression coverage fails without the fix (verified by reverting the builder): 3 TypeScript cases in
tests/account.test.tsand 3 Python cases intests/test_account.pycovering the scope-only request, the empty-query omission, and the no-scope rejection with zero HTTP calls.Live against
api.getanyapi.com, through the built SDKs:TypeScript
Python
Both live canaries pass end to end:
PASS TypeScript live discovery: 363 APIsandPASS Python live discovery: 363 APIs.Not in this PR
No tag and no publish. A release is a separate decision.
The three framework adapters (
langchain-anyapi,llama-index-tools-anyapi,anyapi-haystack) each declarequery: stras required in their own tool signatures and pass it straight through, so they all still block a scope-only search until they are relaxed too. That is a follow-up for after an SDK release, not a change here.🤖 Generated with Claude Code