{"openapi":"3.1.0","info":{"title":"HALOWERK paketwerk","version":"1.0.0","description":"HALOWERK paketwerk — bezahlte Endpunkte nach x402. Preise in USDC auf Base Mainnet.","contact":{"url":"https://paket.halowerk.com/"}},"servers":[{"url":"https://paket.halowerk.com"}],"paths":{"/v1/package-versions":{"post":{"operationId":"package_versions","summary":"Get every published version of a package across npm, PyPI, Maven, Go, Cargo, NuGet and RubyGems in one schema — correctly ordered, with publication dates, the default version, deprecations and withdrawal reasons.","description":"Returns the full version history of a package from a single normalised schema that covers seven ecosystems. Versions are ordered by semantic version, not alphabetically and not in registry order, so 1.10.0 sorts after 1.9.0 — the mistake that quietly breaks naive comparisons. For each version you get the publication timestamp, whether it is the registry default, whether it is deprecated and the deprecation reason as the registry states it. On top of the list the response names the newest version, the newest stable version ignoring pre-releases, the oldest, the total count, how many are deprecated and the span in days between first and last publication. Versions whose string does not parse as semantic version are kept and flagged rather than dropped, because Maven and Go both carry shapes that strict parsers reject; the confidence value falls when that happens. Licence information from the registries is machine-derived and does not replace a legal review.","tags":["paketwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["system","name"],"additionalProperties":false,"properties":{"system":{"type":"string","enum":["npm","pypi","maven","go","cargo","nuget","rubygems"],"description":"The package ecosystem."},"name":{"type":"string","minLength":1,"maxLength":300,"description":"Package name. Maven uses groupId:artifactId, Go uses the module path."},"include_prereleases":{"type":"boolean","default":true,"description":"Whether pre-release versions appear in the list. They are counted either way."},"limit":{"type":"integer","minimum":1,"maximum":500,"default":200,"description":"How many versions to return, newest first."}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/v1/package-freshness":{"post":{"operationId":"package_freshness","summary":"Score how actively a package is maintained from its own release history — age of the current version, the usual gap between releases, whether that rhythm has broken down, and deprecation — with every threshold stated.","description":"Turns the release history of a package into a maintenance signal an agent can act on. Four measurements go in: the age in days of the newest stable release, the median gap between the last ten releases, the ratio of the current silence to that median, and whether the newest version is deprecated. Each maps to a component score and the components combine into a grade from A to E. Every threshold used is returned alongside the verdict, so the judgement can be recomputed or overridden rather than taken on faith — a score whose cut-offs are hidden is an opinion presenting itself as a measurement. The median is used rather than the mean because one burst of five patch releases in a day otherwise makes a dormant project look busy. Packages with fewer than three releases get a grade of null and a stated reason instead of a number derived from nothing. This measures publication rhythm only: a small, finished library that needs no changes will score as dormant, and that is a limit of the method, not a fault of the package.","tags":["paketwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["system","name"],"additionalProperties":false,"properties":{"system":{"type":"string","enum":["npm","pypi","maven","go","cargo","nuget","rubygems"]},"name":{"type":"string","minLength":1,"maxLength":300},"include_prereleases":{"type":"boolean","default":false,"description":"Whether pre-releases count as releases for the rhythm. Off by default: a nightly build stream would mask a dormant stable line."}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/v1/lifecycle-check":{"post":{"operationId":"lifecycle_check","summary":"Find out how long a runtime, database or operating system version is still supported — days remaining, the end-of-life and end-of-active-support dates, and the newest release line that is still maintained.","description":"Answers the question an agent actually has about a product cycle: for the version in use, is support over, how many days remain, and where should it move. Given a product identifier from endoflife.date and optionally a version, it locates the matching release line and returns the release date, the end of active support, the end of life, the end of extended security support where one exists, whether the line is an LTS line, the latest patch release within that line and the number of days to each boundary — negative when the date has passed. Without a version it returns every cycle with the same fields, marks which are still maintained and names the newest supported line. Version matching walks from the most specific line downwards, so 20.11.1 finds the cycle 20 rather than failing, and the matched cycle is always named so a wrong match is visible. Dates that the source leaves open come back as null with the cycle marked accordingly, never as a guess. The authoritative statement is always the vendor announcement; this is a normalised reading of a community-maintained dataset.","tags":["paketwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["product"],"additionalProperties":false,"properties":{"product":{"type":"string","minLength":1,"maxLength":80,"description":"Product identifier as used by endoflife.date, e.g. nodejs, python, postgresql, ubuntu, debian, redis."},"version":{"type":"string","maxLength":40,"description":"The version in use, e.g. 20.11.1. Without it every cycle is returned."}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/v1/dependency-graph":{"post":{"operationId":"dependency_graph","summary":"Resolve the full transitive dependency tree of a package version with each node placed at its true depth, direct and indirect counts, duplicate versions of the same package, and the edges with their version requirements.","description":"Returns the resolved dependency graph of one package version across seven ecosystems: every node with its ecosystem, name, resolved version, whether it is bundled, and its depth from the root. Depth is computed as the shortest path from the root by breadth-first search — a depth-first walk loops forever on a cyclic graph and recursion overflows the stack on large trees, so neither is used. Alongside the nodes you get the edges with the version requirement that produced each resolution, the count of direct versus indirect dependencies, the maximum depth, and any package that appears at more than one version, which is the usual cause of a bloated install and of two copies of the same library disagreeing at runtime. Resolution errors that the upstream reports for individual nodes are passed through per node rather than dropped, because a partially resolved graph that hides its gaps is worse than one that names them. Large graphs can be capped with max_nodes; the response says when it happened and how many nodes were left out rather than pretending the tree ended there.","tags":["paketwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["system","name"],"additionalProperties":false,"properties":{"system":{"type":"string","enum":["npm","pypi","maven","go","cargo","nuget","rubygems"]},"name":{"type":"string","minLength":1,"maxLength":300},"version":{"type":"string","maxLength":60,"description":"The version to resolve. Without it the registry default version is used."},"max_nodes":{"type":"integer","minimum":10,"maximum":3000,"default":800},"include_edges":{"type":"boolean","default":true}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/v1/upgrade-path":{"post":{"operationId":"upgrade_path","summary":"Plan the upgrade from an installed version to a target as a sequence of testable steps that never skips a major version, with the release date, the number of versions crossed and the deprecation state of each stop.","description":"Turns \"we are on 2.4.1 and want to be current\" into an ordered list of stops. The rule it enforces is that no major version is skipped: going from 2 to 5 means stopping at the last release of 3 and the last release of 4, because that is where the migration notes live and where the warnings about the next major are published. Each stop names the version, its release date, how many published versions are crossed to reach it, whether it is deprecated and why, and whether it is a major, minor or patch step. Pre-releases are excluded from the path by default but reported as a count, since routing a production upgrade through a beta is rarely intended. The target defaults to the newest stable version. When the installed version is not in the registry the call fails rather than guessing a starting point, because a path from an unknown origin is not a path. Ecosystems whose versions do not parse as semantic versions are handled by falling back to string ordering, which is stated in the response and lowers the confidence value rather than being silently assumed correct.","tags":["paketwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["system","name","from_version"],"additionalProperties":false,"properties":{"system":{"type":"string","enum":["npm","pypi","maven","go","cargo","nuget","rubygems"]},"name":{"type":"string","minLength":1,"maxLength":300},"from_version":{"type":"string","minLength":1,"maxLength":60,"description":"The version currently installed."},"to_version":{"type":"string","maxLength":60,"description":"Target version. Defaults to the newest stable release."},"include_prereleases":{"type":"boolean","default":false}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/v1/dependency-bloat":{"post":{"operationId":"dependency_bloat","summary":"Measure the weight a package adds to a project — total transitive nodes, depth, duplicated versions and fan-out — and name the single direct dependency that drags in the most of it.","description":"Scores how much a package costs to depend on, using the resolved graph rather than a guess. Four measurements: the number of transitive nodes, the maximum depth, how many packages appear at more than one version, and the fan-out of the root. From those comes a grade from A to E with every threshold returned, so the judgement can be recomputed with different weights. The part worth reading is the ranking of direct dependencies by exclusive cost: for each direct dependency, how many nodes would disappear from the graph if it were removed and nothing else pulled them in. That is the number that tells you which one is worth replacing, and it is computed by reachability from the remaining roots rather than by counting a subtree, because in a shared graph a subtree count double-counts everything. Weight here is node count, not bytes; deps.dev does not carry install sizes, and inventing them from version names would be a fabrication. A package with many small dependencies and one with few large ones can therefore score the same, which the response says outright.","tags":["paketwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["system","name"],"additionalProperties":false,"properties":{"system":{"type":"string","enum":["npm","pypi","maven","go","cargo","nuget","rubygems"]},"name":{"type":"string","minLength":1,"maxLength":300},"version":{"type":"string","maxLength":60}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/v1/artifact-hash":{"post":{"operationId":"artifact_hash","summary":"Identify which published package version a file hash belongs to, across npm, PyPI, Maven, Go, Cargo, NuGet and RubyGems — for artefacts that turned up without provenance.","description":"Takes a file digest and answers which released package version it is. Useful for an artefact found in a container layer, a build directory or an attachment with no metadata attached. Hex and base64 input are both accepted and normalised, the digest length is checked against the declared algorithm before anything is fetched, and the response names every matching package version, since one artefact can be published under more than one coordinate. A hit establishes identity and nothing else: a package can be known and still vulnerable, so this is not a safety verdict and says so. A miss means the digest does not match any archive the index carries — which can mean the artefact was never published, was rebuilt, was modified, or simply belongs to an ecosystem the index does not cover. Those readings are listed rather than collapsed into the word unknown, because an agent deciding what to do next needs the distinction.","tags":["paketwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["hash"],"additionalProperties":false,"properties":{"hash":{"type":"string","minLength":16,"maxLength":200,"description":"The digest, hex or base64."},"algorithm":{"type":"string","enum":["SHA1","SHA256","SHA512","MD5"],"default":"SHA1","description":"Digest algorithm. SHA1 is what most registries publish for archives."}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/v1/package-match":{"post":{"operationId":"package_match","summary":"Find out whether packages in different ecosystems come from the same source project, and list every package an npm, PyPI, Maven, Go, Cargo, NuGet or RubyGems name declares a link to.","description":"Resolves a package to the source projects it declares, with the provenance of each link stated. This is the honest way to answer whether two packages belong together: names repeat across ecosystems and mean different things there, and that gap is exactly what dependency confusion attacks aim at. For the queried package the response gives every related project with the relation type — source repository, issue tracker, homepage — and how the link was established, because deps.dev marks links it verified differently from links it merely read out of package metadata. An unverified link is one an attacker can put in their own package, so it is labelled and never presented as proof. When a second package is supplied the two are compared and the response says whether they share a verified source project, share only an unverified one, or share nothing. Sharing an issue tracker is not sharing a codebase, and the response distinguishes those rather than reporting a match.","tags":["paketwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["system","name"],"additionalProperties":false,"properties":{"system":{"type":"string","enum":["npm","pypi","maven","go","cargo","nuget","rubygems"]},"name":{"type":"string","minLength":1,"maxLength":300},"version":{"type":"string","maxLength":60,"description":"Defaults to the registry default version."},"compare_system":{"type":"string","enum":["npm","pypi","maven","go","cargo","nuget","rubygems"],"description":"Second package to compare against."},"compare_name":{"type":"string","maxLength":300}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/v1/deprecation-monitor":{"post":{"operationId":"deprecation_monitor","summary":"Watch a list of packages and get told what changed since your last check — newly deprecated packages and versions, withdrawals that were taken back, and new releases on a deprecated line.","description":"A monitor with memory. The first call stores a snapshot of the packages you name and returns the baseline, explicitly marked as such rather than reporting everything as new — a monitor that cries wolf on day one is not read on day two. Every later call with the returned snapshot token compares the current registry state against what was stored and reports the differences: packages whose newest version became deprecated, individual versions that gained a deprecation notice, and, equally, deprecations that were withdrawn again, because a monitor that only looks for new warnings leaves stale ones in your inventory forever. Each finding carries the reason text as the registry states it, the version it applies to and when the change was first observed here. The snapshot is updated on every call, so the comparison is always against your previous check and not against a fixed starting point. Up to fifty packages per call across the seven supported ecosystems. Deprecation is what the registry says; a package can be abandoned without ever being marked, which this cannot see and does not claim to.","tags":["paketwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["packages"],"additionalProperties":false,"properties":{"packages":{"type":"array","minItems":1,"maxItems":50,"description":"The packages to watch.","items":{"type":"object","required":["system","name"],"additionalProperties":false,"properties":{"system":{"type":"string","enum":["npm","pypi","maven","go","cargo","nuget","rubygems"]},"name":{"type":"string","minLength":1,"maxLength":300}}}},"snapshot_token":{"type":"string","maxLength":80,"description":"Token from an earlier call. Without it a new baseline is created."}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/v1/release-cadence":{"post":{"operationId":"release_cadence","summary":"Detect changes in a package release rhythm — unusually long silences, sudden bursts and a shift in the underlying cadence — measured against the package own history rather than a cross-project average.","description":"Looks at when a package published, not how often, and reports where the pattern breaks. Three kinds of finding, which mean different things and are kept apart. A long gap: a silence several times the package own median interval, which suggests dormancy. A burst: several releases inside a short window, which is either emergency fixes or an automated publish loop that ran away, and the response gives the dates so the reader can tell. A cadence shift: the median interval of the older half of the history differs from the newer half by more than a stated factor, which often marks a change of maintainer or of release policy. Everything is measured against the package own history, so a project that has published twice a year for a decade is not flagged for publishing twice a year again. The sensitivity is a parameter and its effect is stated; the thresholds actually used come back in the response. Packages with fewer than six dated releases return no findings and say why, rather than producing anomalies out of three data points.","tags":["paketwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["system","name"],"additionalProperties":false,"properties":{"system":{"type":"string","enum":["npm","pypi","maven","go","cargo","nuget","rubygems"]},"name":{"type":"string","minLength":1,"maxLength":300},"include_prereleases":{"type":"boolean","default":false},"sensitivity":{"type":"string","enum":["low","normal","high"],"default":"normal","description":"How far from the median counts as an anomaly. low = 5x median gap, normal = 3x, high = 2x."}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/v1/dependency-confusion":{"post":{"operationId":"dependency_confusion","summary":"Check whether your internal package names also exist publicly, whether the public one is newer than yours, and how recently it appeared — the three things that decide a dependency confusion attack.","description":"Takes the names your organisation publishes internally and checks each against the public registry of the same ecosystem. Three findings, kept apart because they call for different actions. Name is free: nobody has taken it, the door is open but unattended, and the answer is to reserve the name yourself. Name is taken and old: probably an unrelated project that happens to share the name, worth confirming but rarely urgent. Name is taken and appeared recently, especially after your internal package existed: the pattern of an actual attack, and the response gives the first publication date so that judgement can be made. On top of that, when you supply your internal version, the public version is compared against it, because a resolver that prefers the highest version will pick the public package the moment it climbs above yours — that comparison, not mere existence, is what decides the outcome in most build systems. Scope prefixes are honoured as they are given: an npm name under an organisation scope is a different name from the unscoped one, and treating them alike would produce false alarms on every package you own.","tags":["paketwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["system","packages"],"additionalProperties":false,"properties":{"system":{"type":"string","enum":["npm","pypi","maven","go","cargo","nuget","rubygems"]},"packages":{"type":"array","minItems":1,"maxItems":60,"description":"Your internal package names, optionally with the internal version.","items":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":300},"internal_version":{"type":"string","maxLength":60}}}}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/v1/typosquat-radar":{"post":{"operationId":"typosquat_radar","summary":"Find packages whose names are one typo away from yours and that actually exist — generated systematically rather than searched, with age, release count and shared source project so a real squat can be told from a coincidence.","description":"Generates the typical misspellings of a package name and looks up every one of them in the registry. Generation rather than search is deliberate: most of the seven ecosystems have no search API, and the ones that do rank by popularity instead of similarity, so a fresh squat with no downloads never appears. The variants cover a dropped character, a doubled character, two swapped characters, hyphen against underscore, the digit-letter pairs 1 and l, 0 and o, the rn and m confusion, and the common suffixes that get appended to a name. Each variant that exists comes back with its first and last publication date, how many versions it has, and whether it declares the same source project as the original — the three things that separate a squat from a coincidence. A hit is not an accusation and the response says so: two projects can arrive at similar names independently, and it is the age and the provenance that decide, which is why they are reported instead of a verdict. Variants are capped per call and the number checked and skipped is stated, so a truncated sweep is never mistaken for a clean one.","tags":["paketwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["system","name"],"additionalProperties":false,"properties":{"system":{"type":"string","enum":["npm","pypi","maven","go","cargo","nuget","rubygems"]},"name":{"type":"string","minLength":3,"maxLength":120,"description":"The package name to protect."},"max_variants":{"type":"integer","minimum":5,"maximum":80,"default":45,"description":"How many generated variants to look up."},"recent_days":{"type":"integer","minimum":1,"maximum":3650,"default":365,"description":"A variant first published within this many days counts as recent, which is the strongest signal."}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/v1/runtime-compat":{"post":{"operationId":"runtime_compat","summary":"Read the operating system, CPU architecture and runtime requirements a package version declares, as one machine-readable matrix — and see clearly which of them the package simply does not state.","description":"Normalises what a package version declares about where it can run. For npm that is the engines, os and cpu fields plus the declared package type and whether native build scripts are present; for PyPI it is requires_python together with the operating system, implementation and Python version classifiers. Both end up in the same shape: a runtime requirement with its raw range, the allowed and explicitly excluded operating systems, the allowed architectures, and a per-field note of where the value came from. The distinction that matters runs through the whole response: a missing declaration is not a promise. A package without an engines field is not saying it runs everywhere, it is saying nothing, and every field therefore carries a state of declared, excluded or not_declared rather than being filled with a permissive default. When you supply your own runtime, operating system or architecture, each is checked against the declaration and the answer is compatible, incompatible or unknown, never a guess. Only npm and PyPI publish these fields in a machine-readable way; for the other ecosystems the call is refused with that reason instead of returning an empty matrix that looks like an answer.","tags":["paketwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["system","name"],"additionalProperties":false,"properties":{"system":{"type":"string","enum":["npm","pypi"],"description":"Only npm and PyPI declare these fields machine-readably."},"name":{"type":"string","minLength":1,"maxLength":300},"version":{"type":"string","maxLength":60,"description":"Defaults to the latest version."},"target_runtime":{"type":"string","maxLength":40,"description":"Your runtime version, e.g. 20.11.1 for Node or 3.11 for Python."},"target_os":{"type":"string","maxLength":30,"description":"linux, darwin, win32 …"},"target_arch":{"type":"string","maxLength":20,"description":"x64, arm64 …"}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/v1/maintainer-pulse":{"post":{"operationId":"maintainer_pulse","summary":"Condense the state of the project behind a package — last push, release rhythm, open issues, stars, forks and OpenSSF scorecard — into one maintenance signal that still works when the GitHub rate limit is exhausted.","description":"Answers whether the project behind a package is still alive, from two sources with different roles. deps.dev supplies stars, forks, open issue count, the declared licence and the OpenSSF scorecard without any rate limit or account. GitHub supplies the last push and recent commit activity, but only sixty requests per hour per IP without authentication, so it is treated as optional: when it is unavailable the response still comes back, the affected fields are named as unavailable, and the confidence value falls rather than the call failing. A service that dies at somebody else scale limit is not a service. The signal combines release recency from the registry, push recency where known, the ratio of open issues to project size, and the scorecard where present, into a grade from A to E with all thresholds and component scores returned so it can be recomputed. Stars are reported but deliberately carry no weight in the grade: they measure past attention, not present maintenance, and a popular abandoned project is exactly the case this is meant to catch.","tags":["paketwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["system","name"],"additionalProperties":false,"properties":{"system":{"type":"string","enum":["npm","pypi","maven","go","cargo","nuget","rubygems"]},"name":{"type":"string","minLength":1,"maxLength":300},"use_github":{"type":"boolean","default":true,"description":"Whether to try GitHub for push activity. Off makes the call faster and never rate-limited."}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}}},"components":{"schemas":{"PaymentRequired":{"type":"object","properties":{"x402Version":{"type":"integer"},"error":{"type":"string"},"description":{"type":"string"},"inputSchema":{"type":"object"},"accepts":{"type":"array","items":{"type":"object"}}}}},"securitySchemes":{"x402":{"type":"apiKey","in":"header","name":"PAYMENT-SIGNATURE","description":"x402 Zahlungsnachweis"}}}}