Buyers
Composer endpoints
What the marketplace serves over /packages.json, /p2/*.json, and /dist/*: the auth shape, the status codes, what is cached and how, and how to debug a misbehaving install.
What this page is for
If you just want to install a package, see Composer setup. This page is the technical reference for what the endpoints actually do - useful when you're debugging a CI run, building a wrapper script, or trying to understand why a buyer sees one set of versions and you see another.
Endpoint map
GET /packages.json- Composer V2 root metadata. Returns the
metadata-urltemplate and the list of available packages your token is entitled to. Required by Composer before any /p2/* fetch. GET /p2/{vendor}/{package}.json- Per-package version metadata. Lists every version your token can install, with composer.json-shape entries. Filtered by your active licence (and, for subscriptions, by the date your access window closes).
GET /dist/{vendor}/{package}/{version}.zip- The actual archive. Token auth, package entitlement, and the version filter are re-checked on every request, so revoking a token blocks subsequent downloads immediately. A request already mid-stream when you revoke continues to its end; the next request from that token fails.
POST /composer/downloads- Composer's notify-batch hook. Composer calls this after a successful install with the list of packages it just pulled; the platform records IP, user-agent, and token id for download analytics. Idempotent and best-effort: a 5xx here doesn't block the install.
Authentication
All four endpoints use HTTP Basic with project-scoped credentials:
- Username: the token's
public_key(a random hex string). - Password: the token's
private_key(a random hex string, revealed inline when you create the token; also available via theDownload auth.jsonlink on the token row).
Tokens are project-scoped: a token created in your "production" project sees only the licences activated against that project. Cross-project access requires either activating the licence against the other project, or creating a token in the other project - see API tokens.
A typical auth.json (the host matches your Packagento install):
{
"http-basic": {
"packagento.com": {
"username": "<public_key>",
"password": "<private_key>"
}
}
}
Status codes you'll see
200 OK- Normal response with body.
304 Not Modified- Conditional GET hit on /packages.json or /p2/*.json - Composer sent
If-None-Matchand the ETag still matches. Body is empty by HTTP spec. 401 Unauthorized- Token missing, malformed, revoked, or password mismatch. The response carries a
WWW-Authenticate: Basicheader. Either editauth.jsondirectly or runcomposer config --global http-basic.<host> <public_key> <private_key>to set the credentials. 404 Not Found- Package or version is not visible to your token. This is deliberately the same response as a non-existent package - we don't want to disclose the existence of packages a token isn't entitled to. If you expect to see a package, check the licence is activated against this project.
5xx- Genuine server error. Composer retries on its own schedule; if the retry window expires, your install fails. Get in touch through our contact form if it persists.
Caching and ETags
Composer caches metadata aggressively. The platform serves an ETag on /packages.json and /p2/*.json; on every subsequent request Composer sends If-None-Match and the platform returns 304 if the manifest hasn't changed. When you publish a new tag, the etag invalidates immediately - buyers don't need to clear their Composer cache. The /dist/* endpoint isn't etag'd (the archive's identity is the URL); browsers and proxies should treat archives as immutable.
No rate limits - but be reasonable
There is no per-token request quota at this time, and Composer is not throttled. That said, please:
- Don't poll /p2/*.json on a tight loop. Composer's ETag handling is enough - you should see 304s for repeated reads.
- Don't parallelise /dist/* downloads beyond what Composer does natively (it already runs concurrent downloads).
- Use one token per CI runner; don't share a single token across many simultaneous builds.
If the platform later introduces explicit limits (e.g. abuse mitigation), they will be communicated to API-token holders by email before they take effect.
Debugging an install
Composer's -v and -vvv flags print the HTTP requests it makes. The most useful diagnostic is:
composer require -vvv vendor/package:^1.4
Look for:
- 401 from /packages.json: the token isn't reaching the platform. Check
auth.jsonlives where Composer expects (project root or~/.composer/) and the host key matches your repository hostname exactly. - 404 from /p2/vendor/package.json: package isn't in your token's entitlement set - usually the licence is on a different project.
- 200 metadata, 401 on /dist/: shouldn't happen - both endpoints share the same auth path. If you see this, get in touch through our contact form with the request and response headers.