This document provides comprehensive documentation for cnpmcore's internal APIs that allow direct HTTP requests without using the cnpm client. These APIs enable package synchronization, administration, and other advanced operations.
- Authentication
- Package Sync API
- Binary Sync API
- Token Management API
- Package Block/Admin API
- Registry Management API
- Hook Management API
- User Management API
- Common Schemas
Most internal APIs require authentication using one of these methods:
curl -H "Authorization: Bearer ${TOKEN}" https://your-registry.com/api/endpointSome APIs require admin privileges. Admin users are configured in the registry settings.
The package sync functionality allows you to synchronize packages from external registries (like npmjs.org) to your private registry.
Trigger a package synchronization task.
PUT /-/package/:fullname/syncs
Required. Must be authenticated user.
fullname(string): Package name (can include scope, e.g.,@scope/package)
{
"skipDependencies": false,
"syncDownloadData": false,
"force": false,
"forceSyncHistory": false,
"tips": "Custom sync reason",
"registryName": "optional-source-registry",
"specificVersions": "[\"1.0.0\", \"1.0.1\"]"
}| Field | Type | Required | Description |
|---|---|---|---|
skipDependencies |
boolean | No | Skip syncing package dependencies |
syncDownloadData |
boolean | No | Sync download statistics data |
force |
boolean | No | Force immediate execution (admin only) |
forceSyncHistory |
boolean | No | Sync all historical versions (admin only) |
tips |
string | No | Custom reason/description for sync |
registryName |
string | No | Source registry name |
specificVersions |
string | No | JSON array of specific versions to sync |
curl -X PUT \
-H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-d '{
"skipDependencies": false,
"syncDownloadData": false,
"force": false,
"tips": "Manual sync from API"
}' \
https://your-registry.com/-/package/lodash/syncs{
"ok": true,
"id": "sync-task-uuid",
"type": "package",
"state": "waiting"
}Legacy endpoint for compatibility with cnpmjs.org.
PUT /:fullname/sync
fullname(string): Package namenodeps(query): Set to "true" to skip dependencies
curl -X PUT \
-H "Authorization: Bearer your-token-here" \
"https://your-registry.com/lodash/sync?nodeps=false"{
"ok": true,
"logId": "sync-task-uuid"
}Check the status of a sync task.
GET /-/package/:fullname/syncs/:taskId
fullname(string): Package nametaskId(string): Task ID returned from sync creation
curl -H "Authorization: Bearer your-token-here" \
https://your-registry.com/-/package/lodash/syncs/sync-task-uuid{
"ok": true,
"id": "sync-task-uuid",
"type": "package",
"state": "success",
"logUrl": "https://your-registry.com/-/package/lodash/syncs/sync-task-uuid/log"
}waiting: Task is queuedprocessing: Task is currently runningsuccess: Task completed successfullyerror: Task failed
Retrieve the log for a sync task.
GET /-/package/:fullname/syncs/:taskId/log
fullname(string): Package nametaskId(string): Task ID
curl -H "Authorization: Bearer your-token-here" \
https://your-registry.com/-/package/lodash/syncs/sync-task-uuid/logReturns the log content as plain text or redirects to log URL.
Legacy endpoint for checking sync status.
GET /:fullname/sync/log/:taskId
curl -H "Authorization: Bearer your-token-here" \
https://your-registry.com/lodash/sync/log/sync-task-uuid{
"ok": true,
"syncDone": true,
"log": "[2024-01-01T12:00:00Z] [done] Sync lodash data: {...}",
"logUrl": "https://your-registry.com/-/package/lodash/syncs/sync-task-uuid/log"
}Manage and sync binary packages (like Node.js, Python, etc.).
Get a list of all available binary packages.
GET /-/binary/
curl https://your-registry.com/-/binary/[
{
"name": "node/",
"category": "node/",
"description": "Node.js runtime",
"distUrl": "https://nodejs.org/dist/",
"repoUrl": "https://github.com/nodejs/node",
"type": "dir",
"url": "https://your-registry.com/-/binary/node/"
}
]Browse files in a binary package directory.
GET /-/binary/:binaryName/:subpath
binaryName(string): Binary package name (e.g., "node", "python")subpath(string): Path within the binary directorysince(query): Filter files modified since datelimit(query): Limit number of results (max 1000)
curl https://your-registry.com/-/binary/node/v18.0.0/Manage authentication tokens for users.
Create a new authentication token.
POST /-/npm/v1/tokens
Required. Must provide current password.
{
"password": "current-password",
"readonly": false,
"automation": false,
"cidr_whitelist": ["127.0.0.1", "192.168.1.0/24"]
}| Field | Type | Required | Description |
|---|---|---|---|
password |
string | Yes | Current user password (8-100 chars) |
readonly |
boolean | No | Create read-only token |
automation |
boolean | No | Mark token for automation use |
cidr_whitelist |
array | No | IP address restrictions (max 10) |
curl -X POST \
-H "Authorization: Bearer existing-token" \
-H "Content-Type: application/json" \
-d '{
"password": "my-password",
"readonly": false,
"cidr_whitelist": ["127.0.0.1"]
}' \
https://your-registry.com/-/npm/v1/tokens{
"token": "npm_xxxxxxxxxxxxxxxxxxxx",
"key": "full-token-key-hash",
"cidr_whitelist": ["127.0.0.1"],
"readonly": false,
"automation": false,
"created": "2024-01-01T12:00:00.000Z",
"updated": "2024-01-01T12:00:00.000Z"
}Get all tokens for the authenticated user.
GET /-/npm/v1/tokens
Required.
curl -H "Authorization: Bearer your-token" \
https://your-registry.com/-/npm/v1/tokens{
"objects": [
{
"token": "npm_xx...xx",
"key": "token-key-hash",
"cidr_whitelist": null,
"readonly": false,
"automation": false,
"created": "2024-01-01T12:00:00.000Z",
"updated": "2024-01-01T12:00:00.000Z",
"lastUsedAt": "2024-01-01T12:30:00.000Z"
}
],
"total": 1,
"urls": {}
}Remove an authentication token.
DELETE /-/npm/v1/tokens/token/:tokenKey
Required.
tokenKey(string): The token key to delete
curl -X DELETE \
-H "Authorization: Bearer your-token" \
https://your-registry.com/-/npm/v1/tokens/token/token-key-hash{
"ok": true
}Administrative APIs for blocking and managing packages. Requires admin access.
Block a package from being downloaded or published.
PUT /-/package/:fullname/blocks
Required. Admin access only.
fullname(string): Package name to block
{
"reason": "Detailed reason for blocking this package"
}curl -X PUT \
-H "Authorization: Bearer admin-token" \
-H "Content-Type: application/json" \
-d '{
"reason": "Package contains malicious code"
}' \
https://your-registry.com/-/package/malicious-package/blocks{
"ok": true,
"id": "block-record-id",
"package_id": "package-internal-id"
}Remove a block from a package.
DELETE /-/package/:fullname/blocks
Required. Admin access only.
fullname(string): Package name to unblock
curl -X DELETE \
-H "Authorization: Bearer admin-token" \
https://your-registry.com/-/package/malicious-package/blocks{
"ok": true
}Check if a package is blocked and why.
GET /-/package/:fullname/blocks
fullname(string): Package name to check
curl https://your-registry.com/-/package/some-package/blocks{
"blocked": true,
"reason": "Package contains malicious code (operator: admin/admin-id)",
"createdAt": "2024-01-01T12:00:00.000Z"
}Manage multiple npm registries and their configurations.
Get all configured registries.
GET /-/registry
pageSize(number): Results per page (1-100, default: 20)pageIndex(number): Page number (0-based, default: 0)
curl "https://your-registry.com/-/registry?pageSize=10&pageIndex=0"{
"data": [
{
"registryId": "npmjs",
"name": "Official NPM Registry",
"host": "https://registry.npmjs.org",
"type": "npm",
"userPrefix": "npm:",
"changeStream": "https://replicate.npmjs.com",
"response": null
}
],
"total": 1
}Get details for a specific registry.
GET /-/registry/:id
id(string): Registry ID
curl https://your-registry.com/-/registry/npmjsCreate a new registry configuration.
POST /-/registry
Required. Admin access only.
{
"name": "Custom Registry",
"host": "https://my-custom-registry.com",
"changeStream": "https://my-custom-registry.com/_changes",
"type": "cnpm"
}curl -X POST \
-H "Authorization: Bearer admin-token" \
-H "Content-Type: application/json" \
-d '{
"name": "Custom Registry",
"host": "https://my-custom-registry.com",
"type": "cnpm"
}' \
https://your-registry.com/-/registryManage webhooks that trigger on package events (publish, install, etc.).
Base Path: All hook endpoints use the base path /-/npm
Create a new webhook.
POST /-/npm/v1/hooks/hook
Required.
{
"type": "package",
"name": "hook-name",
"endpoint": "https://your-webhook-endpoint.com/hook",
"secret": "webhook-secret-key"
}| Field | Type | Required | Description |
|---|---|---|---|
type |
string | Yes | Hook type (e.g., "package") |
name |
string | Yes | Hook name (1-428 chars) |
endpoint |
string | Yes | Webhook URL (1-2048 chars) |
secret |
string | Yes | Secret key for webhook verification (1-200 chars) |
curl -X POST \
-H "Authorization: Bearer your-token" \
-H "Content-Type: application/json" \
-d '{
"type": "package",
"name": "my-webhook",
"endpoint": "https://my-server.com/webhook",
"secret": "my-secret-key"
}' \
https://your-registry.com/-/npm/v1/hooks/hook{
"id": "hook-uuid",
"name": "my-webhook",
"type": "package",
"endpoint": "https://my-server.com/webhook",
"created": "2024-01-01T12:00:00.000Z",
"updated": "2024-01-01T12:00:00.000Z",
"delivered": false,
"last_delivery": null
}Update an existing webhook.
PUT /-/npm/v1/hooks/hook/:id
Required. Must be hook owner.
id(string): Hook ID
{
"endpoint": "https://new-webhook-endpoint.com/hook",
"secret": "new-secret-key"
}curl -X PUT \
-H "Authorization: Bearer your-token" \
-H "Content-Type: application/json" \
-d '{
"endpoint": "https://updated-server.com/webhook",
"secret": "updated-secret"
}' \
https://your-registry.com/-/npm/v1/hooks/hook/hook-uuidRemove a webhook.
DELETE /-/npm/v1/hooks/hook/:id
Required. Must be hook owner.
id(string): Hook ID
curl -X DELETE \
-H "Authorization: Bearer your-token" \
https://your-registry.com/-/npm/v1/hooks/hook/hook-uuid{
"id": "hook-uuid",
"name": "my-webhook",
"type": "package",
"endpoint": "https://my-server.com/webhook",
"created": "2024-01-01T12:00:00.000Z",
"updated": "2024-01-01T12:00:00.000Z",
"deleted": "2024-01-01T13:00:00.000Z"
}Get all hooks for the authenticated user.
GET /-/npm/v1/hooks
Required.
curl -H "Authorization: Bearer your-token" \
https://your-registry.com/-/npm/v1/hooks{
"objects": [
{
"id": "hook-uuid",
"name": "my-webhook",
"type": "package",
"endpoint": "https://my-server.com/webhook",
"created": "2024-01-01T12:00:00.000Z",
"updated": "2024-01-01T12:00:00.000Z",
"delivered": true,
"last_delivery": "2024-01-01T12:30:00.000Z"
}
]
}Get details for a specific hook.
GET /-/npm/v1/hooks/hook/:id
Required. Must be hook owner.
id(string): Hook ID
curl -H "Authorization: Bearer your-token" \
https://your-registry.com/-/npm/v1/hooks/hook/hook-uuidManage user accounts and authentication.
Create a new user account or login existing user.
PUT /-/user/org.couchdb.user::username
username(string): Username to create/login
{
"_id": "org.couchdb.user:username",
"name": "username",
"password": "user-password",
"email": "[email protected]",
"type": "user",
"roles": [],
"date": "2024-01-01T12:00:00.000Z"
}| Field | Type | Required | Description |
|---|---|---|---|
_id |
string | Yes | Must be "org.couchdb.user:" + username |
name |
string | Yes | Username (1-100 chars) |
password |
string | Yes | Password (8-100 chars) |
email |
string | No | Email address (valid email format) |
type |
string | Yes | Must be "user" |
roles |
array | No | User roles (usually empty) |
date |
string | No | Registration date |
curl -X PUT \
-H "Content-Type: application/json" \
-d '{
"_id": "org.couchdb.user:johndoe",
"name": "johndoe",
"password": "securepassword123",
"email": "[email protected]",
"type": "user",
"roles": []
}' \
https://your-registry.com/-/user/org.couchdb.user:johndoe{
"ok": true,
"id": "org.couchdb.user:johndoe",
"rev": "1-hash",
"token": "user-token-uuid"
}{
"ok": true,
"id": "org.couchdb.user:johndoe",
"rev": "existing-rev-hash",
"token": "user-token-uuid"
}401 Unauthorized: Wrong password for existing user403 Forbidden: Public registration disabled409 Conflict: User exists but email differs422 Unprocessable Entity: Username mismatch in URL/body
All APIs return errors in a consistent format:
{
"error": "error_code",
"reason": "Human readable error message"
}200 OK: Request successful201 Created: Resource created successfully400 Bad Request: Invalid request parameters401 Unauthorized: Authentication required or invalid403 Forbidden: Insufficient permissions404 Not Found: Resource not found409 Conflict: Resource already exists500 Internal Server Error: Server error
Package names follow npm naming conventions:
- Unscoped:
package-name - Scoped:
@scope/package-name - Must match regex:
^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$
- Trigger sync for a package:
curl -X PUT \
-H "Authorization: Bearer your-token" \
-H "Content-Type: application/json" \
-d '{"tips": "API sync request"}' \
https://your-registry.com/-/package/lodash/syncs- Check sync status:
curl -H "Authorization: Bearer your-token" \
https://your-registry.com/-/package/lodash/syncs/task-id- View sync logs:
curl -H "Authorization: Bearer your-token" \
https://your-registry.com/-/package/lodash/syncs/task-id/logFor multiple packages, send individual requests or implement your own batch processing script using these APIs.
Always check the HTTP status code and response body for errors:
response=$(curl -s -w "%{http_code}" -H "Authorization: Bearer token" \
https://your-registry.com/-/package/nonexistent/syncs)
http_code=$(echo "$response" | tail -c 4)
body=$(echo "$response" | sed 's/...$//')
if [ "$http_code" -ne 201 ]; then
echo "Error: $body"
exit 1
fiBe mindful of rate limits when making multiple API requests. Consider implementing:
- Delays between requests
- Exponential backoff for retries
- Concurrent request limits
- Always use HTTPS in production
- Store tokens securely and rotate them regularly
- Use read-only tokens when possible
- Implement IP whitelisting for sensitive operations
- Monitor API usage for unusual patterns
For more information about cnpmcore, visit the official documentation.