Skip to content

Commands

Every operation the management API exposes is reachable from a command, and a test in the CLI’s repository fails the build if a new endpoint ever ships without one.

Run keylight <group> --help for the flags on any group, and keylight <group> <command> --help for a single command. Nothing here prompts: every input is a flag.

Terminal window
keylight products list
keylight products get my-app
keylight products create --display-name "My App" --key-prefix MYAP --support-email help@myapp.com
keylight products update my-app --purchase-url https://myapp.com/buy
keylight products free-tier set my-app --enabled
keylight products test-mode disable my-app

update accepts the support email and the purchase URL. Those are the only two fields the API changes on an existing app.

Key types live under the app that owns them:

Terminal window
keylight products key-types list --product my-app
keylight products key-types create --product my-app --key-type-id pro --display-name "Pro"
keylight products key-types update --product my-app --key-type-id pro --activation-limit 5
keylight products key-types verify-prices --product my-app
keylight products key-types delete --product my-app --key-type-id pro

verify-prices checks that every mapped payment-provider price still resolves — worth running after you edit prices at the provider, since a stale mapping only shows up at checkout.

Enabling Stripe test mode needs two secrets, read from environment variables you name rather than passed as arguments:

Terminal window
export KEYLIGHT_STRIPE_TEST_SECRET_KEY=sk_test_...
export KEYLIGHT_STRIPE_TEST_WEBHOOK_SECRET=whsec_...
keylight products test-mode enable my-app
Terminal window
keylight licenses list --limit 10
keylight licenses get <license-id>
keylight licenses create --product my-app --key-type pro --customer-email buyer@example.com
keylight licenses remint <license-id>
keylight licenses deactivate-device <license-id> --instance-id <instance-id>
keylight licenses import --product my-app --file ./rows.json
keylight licenses revoke <license-id>
keylight licenses export

Keys are masked in list output, so a screenshot or a shared terminal does not leak one. The raw key is returned once, when it is minted or reminted.

create accepts an --idempotency-key. Reuse it across retries and a repeated call cannot issue a second license; omit it and one is generated per invocation.

Use --send-email on create if you want Keylight to email the key to the customer. Without it, nothing is sent.

import is the one command whose input you have to author, so it is the one place a wrong guess costs you a round trip. The file is a JSON array of rows. email and key_type are required; license_key, name and expires_at are optional. The field names are snake_case here, unlike every other payload:

[
{ "email": "buyer@example.com", "key_type": "pro", "license_key": "OLD-KEY-0001", "name": "Ada" },
{ "email": "second@example.com", "key_type": "pro" }
]

Give license_key to carry an existing key across from a previous vendor; omit it and Keylight mints a fresh one. --migration-source tags the whole batch with where the keys came from, which is what later tells an imported license apart from one you issued.

Terminal window
keylight customers list --limit 10
keylight customers get <customer-id>
keylight customers create --email buyer@example.com --name "Buyer"
keylight customers link-license <customer-id> --license <license-id>
keylight customers entitlements set <customer-id> --license <license-id> --entitlements '["sync","export"]'

entitlements set replaces the entitlements on that license rather than adding to them, so pass every one the customer should end up holding.

Terminal window
keylight integrations list
keylight integrations status
keylight integrations connect <provider>
keylight integrations disconnect <provider>
keylight integrations rotate-secret <provider>

list shows every provider and whether it is connected; status shows the Stripe connection in detail, including which account and whether it is live or sandbox.

Terminal window
keylight usage
keylight usage --days 30

Activations, validations, active devices, and monthly actives — the same figures the dashboard reports.

Terminal window
keylight sdk-key get
keylight sdk-key rotate
keylight webhook get
keylight webhook set --url https://example.com/keylight
Terminal window
keylight test-purchase create --product my-app --key-type pro
keylight test-purchase get <run-id>

Runs a purchase end to end and lets you inspect what it issued, without a real card.

Seven operations are dangerous enough that a token cannot run them on its own, however broad its scopes. A human approves the specific call in a browser first — the same shape as npm’s web-based two-factor login.

CommandWhy it is gated
licenses revokeA customer loses access, and it cannot be undone
licenses exportBulk customer data leaves the account
products key-types deleteCannot be undone
integrations rotate-secretThe current ping URL stops working immediately
sdk-key getA live secret leaves the dashboard
sdk-key rotateEvery shipped build embedding the old key fails until you release an update
webhook setRedirects where your events are delivered

When a command hits one, the CLI prints an approval URL (and opens it, unless --no-browser is set or stdout is not a terminal), polls until you approve or deny, and then retries the original call automatically. You never have to know which commands are gated — it walks the flow whenever the server asks for it.

These block and wait rather than failing fast. They are human-gated by design, and an unattended caller failing instantly would misrepresent what they are; an agent surfaces the URL to its user and waits. Approving grants that one request, not standing permission — the confirmation is consumed on use, and the server checks that the retried request matches the one you approved.

Every command takes --json:

Terminal window
keylight licenses list --json | jq -r '.items[] | select(.status == "active") | .displayKey'

List commands are cursor-paginated. Human output tells you when there is more and prints the command to continue; --json responses carry nextCursor, which is null on the last page.

Terminal window
keylight licenses list --limit 100 --cursor <cursor>