AI Power Ups
Contents

Dev · Serper discovery + PyPI

pypi.search

PyPI has no supported keyword-search API. Uses Serper to search site:pypi.org/project/, returning only PyPI project links, deduplicated within each page. Results are unverified discovery candidates; details verifies the package through official PyPI JSON metadata. Requires the existing SERPER_API_KEY. Supports more and update; does not download the entire package index.
Operation
POST /v1/capabilities/pypi.search/execute
operationId
executePypiSearch
Typical credits
1
Search deadline
15 s server-side
Paging
page
Availability
Not checked
Cost basis: $0.001 per Serper credit; official metadata details are free. Availability is reported per deployment by GET /v1/catalog (available). The timestamped snapshot describes configuration, not provider uptime or your account's enabled choices. Check the catalog with your own key before a call. Credits are explained under credits and limits.

Request

Body of POST /v1/capabilities/pypi.search/execute, JSON, validated against the PypiSearchRequest component of the public OpenAPI document. Defaults are applied server-side, so an omitted optional field behaves exactly as its default.

Request fields of pypi.search
FieldTypeRequiredDefaultConstraints and description
querystringyesmin length 1, max length 300
Discovery query such as Python PDF extraction. Searched through Serper with site:pypi.org/project/.
numintegerno10min 1, max 20
  • Unknown keys are rejected with 400 invalid_request.

Examples

PDF extraction libraries

curl
curl -s -X POST https://ai-powerups.smalltree.cloud/v1/capabilities/pypi.search/execute \
  -H "Authorization: Bearer $AIPA_API_KEY" -H "Content-Type: application/json" \
  -d '{"query":"Python PDF extraction","num":5}'
No recorded response is published for this capability yet. The envelope is the ExecuteResponse component (see sessions and records); the record keys below are what the adapter emits. A first call with the example above returns search_id, the records and the charge.

Result record

Every item in results[] carries record_id and title (contract, always present) and usually url and snippet. The keys below are the documented tier: produced deterministically by this capability, omitted when the source has no value, checked against recorded source fixtures in our test suite, and published as the PypiSearchRecord component (all optional, extra keys allowed) so generated clients type them. The wire schema itself still validates only the base keys. See stability tiers.

Record keys of pypi.search
KeyTypePresenceNote
packagestringalways
sourcestringalways
verifiedbooleanalways

Caveats

  • Discovery requires SERPER_API_KEY; it is not a native PyPI search API. Records are unverified until details succeeds. Non-project URLs are dropped, so a page can be empty while has_more is true. Projects can recur on later pages.

Follow-ups

  • Paging: Provider page number; more fetches the next page from the source. Send { "search_id": "…", "action": "more" } while has_more is true; tolerate an empty page and stop after a bounded number of pages.
  • Update: Re-run with changed parameters (merged into the stored query); page state resets, search_id stays. Params accept any subset of the request fields (PypiSearchUpdateParams).
  • Record actions:
    • details: Verify the candidate and retrieve official latest-version PyPI metadata for free.
  • Detail behaviour: First details call fetches from the provider (billed as stated); repeats are cached and free. Official PyPI metadata lookup is free; repeated details are cached by the session store.
record action
curl -s -X POST https://ai-powerups.smalltree.cloud/v1/follow-up \
  -H "Authorization: Bearer $AIPA_API_KEY" -H "Content-Type: application/json" \
  -d '{"record_id":"rec_…","action":"details"}'

Record detail objects of this capability are provider-shaped: documented by observation, not by schema. Full follow-up semantics: follow-up.

Typed client

With types generated from the public document (see types, client and samples) the call is path-keyed and the body is checked at compile time:

TypeScript (openapi-fetch)
const { data, error } = await client.POST("/v1/capabilities/pypi.search/execute", {
  body: {
    "query": "Python PDF extraction",
    "num": 5
  },
});
if (error) throw new Error(`${error.error.code}: ${error.error.message}`);
for (const record of data.results) console.log(record.record_id, record.title);