Standalone Node/TypeScript CLI for bulk license creation and bulk updates against an existing LicenseGate backend.
bulk-createbulk-update(interactive per-license confirmation)single-update- JSON input files
- dry-run mode
- optional JSON report output
- no dependency on the LicenseGate frontend/backend runtime
- Node.js 18+
From this folder:
npm installnpm run build
Pass values as flags or environment variables:
--api-keyorLICENSEGATE_API_KEY--base-urlorLICENSEGATE_BASE_URL(optional, defaults tohttps://api.licensegate.io)
- Bulk create dry run:
npx ts-node src/cli.ts bulk-create --api-key YOUR_API_KEY --input ./examples/template.bulk-create.json --dry-run
- Bulk update dry run (resolves real targets and returns
targetCount):npx ts-node src/cli.ts bulk-update --api-key YOUR_API_KEY --input ./examples/template.bulk-update.json --dry-run
- Bulk update from key files dry run (returns
plannedCount):npx ts-node src/cli.ts bulk-update-key-files --api-key YOUR_API_KEY --input ./examples/template.bulk-update.json --key-files-dir ./licenseKeyFiles --dry-run
npx ts-node src/cli.ts bulk-create --api-key YOUR_API_KEY --input ./examples/template.bulk-create.json --concurrency 5 --report ./reports/create-report.json
npx ts-node src/cli.ts bulk-update --api-key YOUR_API_KEY --input ./examples/template.bulk-update.json --report ./reports/update-report.json
bulk-update is interactive:
y/yes: update this licensen/no: skip this licenseq/quit: stop processing more licensesf/fast-forward: update all remaining licenses without further prompts- after choosing update, you can optionally set a custom expiration extension (days from now) for that license
npx ts-node src/cli.ts bulk-update-key-files --api-key YOUR_API_KEY --input ./examples/template.bulk-update.json --key-files-dir ./licenseKeyFiles --report ./reports/key-files-update-report.json
Rules for bulk-update-key-files:
- loads
License Keys.csvandOrders_*.csvfrom--key-files-dir - reads scopes from the input JSON (
scopevalues) - targets assigned keys in those scopes with order assignment date in last 8 days
- sets expiration date to assignment date + 8 days
- targets available/unassigned keys in those scopes and sets expiration date to today + 8 days
Expected CSV headers:
-
License Keys.csv(required columns):keystatusorder_name
Example header:
key,tag,status,order_name,created_at
-
Orders_*.csv(required columns):order_namedate
Optional but recommended:
order_number(improves matching for values likeOrder #1697)
Example header:
order_number,order_name,customer,email,products,date
npx ts-node src/cli.ts single-update --api-key YOUR_API_KEY --input ./examples/template.single-update.json --report ./reports/single-update-report.json
You can provide either:
- JSON array of payloads (legacy format), or
- single template format with
count+data(recommended)
Single template format:
{
"count": 50,
"data": {
"name": "theNameOfYourLicense",
"notes": "",
"active": true,
"ipLimit": 1,
"validationPoints": 3,
"validationLimit": 3,
"replenishAmount": 1,
"replenishInterval": "TEN_SECONDS",
"expirationDate": {
"extendByDays": 8
},
"licenseScope": "YourScope"
}
}
This creates 50 licenses with the same settings.
Legacy array format still works:
[
{
"name": "Customer A",
"notes": "",
"active": true
}
]
Use scope to update all licenses that share a licenseScope. Set data.expirationDate to { "extendByDays": <number> } to choose how many days to add from when the script runs.
Example: renew all licenses in YOURSCOPE by 14 days:
[
{
"scope": "YOURSCOPE",
"data": {
"expirationDate": {
"extendByDays": 14
}
}
}
]
Use this to update one matching license for testing. It accepts the same scope/filter structure, but the command stops after resolving one target.
Example:
[
{
"scope": "YOURSCOPE",
"filter": {
"expiredWithinDays": 7
},
"data": {
"expirationDate": {
"extendByDays": 7
}
}
}
]
0when all items succeed1when any item fails or the command is invalid