Skip to content

CLI reference

The CLI is the npm package @kasskeep/cli. It calls the admin API with a personal access token. It needs Node.js 22 or later and has no other dependencies. Every command prints JSON, except ads export --format csv.

Terminal window
npx @kasskeep/cli login
npx @kasskeep/cli whoami

npx downloads the latest version on first use. To install it once and type kasskeep instead of npx @kasskeep/cli, run npm install -g @kasskeep/cli.

Terminal window
npx @kasskeep/cli login # paste the token when asked; input is hidden
npx @kasskeep/cli login --token-file - < token.txt # non-interactive
npx @kasskeep/cli logout

login checks the personal access token (kkp_..., see Keys and access) against the API and saves it to ~/.config/kasskeep/credentials (or $XDG_CONFIG_HOME/kasskeep/credentials) with permissions 600. logout deletes that file; the token stays valid until it expires or you revoke it with DELETE /v1/admin/me/tokens/<token_id>.

Option or variable Meaning
--api <url>, KASSKEEP_API_URL API address. Default https://api.kasskeep.com
KASSKEEP_TOKEN Use this token instead of the saved one, for CI
--tenant ten_xxx Selects the tenant. You can leave it out if you belong to exactly one
--help Help for a command, e.g. npx @kasskeep/cli ads --help

A saved token is only sent to the address it was saved for; --api with another address asks you to log in again.

  • apps create and apps rotate-keys print public_key, secret_key and webhook_secret once, with a reminder to save them.
  • Every other command shows the public key masked (pk_…a1b2); add --show-keys to see it in full. Secret keys, webhook secrets and tokens are never printed.
  • File options read the file on your machine and send its content. - reads standard input, for one option per command: --apple-private-key-file - < AuthKey.p8.

On an error the CLI prints the HTTP status, the error code and message, then a hint, and exits with status 1:

401 invalid_admin_token
the token is missing, expired or revoked; run: kasskeep login
Command Does
login, logout Save or forget the token
whoami Current user and memberships
tenants Tenants you can see
apps list Apps in the tenant
apps create --name <name> [app options] Create an app
apps update --id <app_id> [app options] Change an app. An empty string clears a field, e.g. --webhook-url ""
apps rotate-keys --id <app_id> [--webhook-secret] New public and secret keys; optionally a new webhook secret
apps delete --id <app_id> Delete the app and its data
products list|set|remove --id <app_id> Web channel product mapping
test-store <subcommand> --id <app_id> Test store
ads <subcommand> --id <app_id> Rewarded ads, ad unit mapping, stats and export
notify <subcommand> Alert subscriptions
Option Field
--name name
--ios-bundle-id ios_bundle_id
--android-package android_package
--apple-app-apple-id apple_app_apple_id
--apple-environment production|sandbox apple_environment
--apple-refund-preference DECLINE|GRANT_FULL|GRANT_PRORATED apple_refund_preference
--apple-issuer-id, --apple-key-id, --apple-private-key-file Apple credentials, all three together; an empty file path removes them
--google-service-account-file Google credentials; empty removes them
--google-pubsub-audience, --google-pubsub-email RTDN token checks
--google-consumable-products "coins_*,gems_100" Replaces the consumable list
--webhook-url webhook_url
--checkout-return-hosts "a.example.com,*.example.com" checkout_return_hosts
--cors-origins "https://a.example.com,*.example.com" cors_origins
--stripe-secret-key-file, --stripe-webhook-secret-file Stripe credentials (apps update only)
--ads-unmapped-policy reject|emit ads_unmapped_policy
--ads-allow-shared-test-units true|false ads_allow_shared_test_units
Terminal window
npx @kasskeep/cli products set --id app_xxx --product-id pro_monthly --external-id price_1Q... --type subscription
npx @kasskeep/cli products list --id app_xxx [--channel stripe]
npx @kasskeep/cli products remove --id app_xxx --product-id pro_monthly

--channel defaults to stripe. --type is subscription or one_time.

Subcommand Options
show, enable, disable
config --period-seconds N, --renewal-success-rate 0..1, --grace-period-seconds N, --billing-retry-seconds N, --products "demo.*,x", --prices-file prices.json
purchases --user <app_user_id>, --limit N
simulate --scenario <name> and --purchase-id <test_...> or --user <app_user_id> [--product-id <id>]; --to-product-id for upgrades and downgrades
advance --user <app_user_id>, --purchase-id, --outcome success|failure

Scenarios are listed on the test store page.

Subcommand Options
networks Callback paths and credential checks
units List mappings
unit-set --name <name> and any of --admob, --applovin, --levelplay. Repeat a flag or separate ids with commas; prefix ios: or android: to label the platform. An empty value removes that network
unit-remove --name <name>
unmatched --limit 50
credentials --applovin-event-key-file, --admob-app-id, --levelplay-private-key-file, --levelplay-app-key, --levelplay-timestamp-window <seconds>, --levelplay-ip-allowlist levelplay|<ip,cidr,...>, --levelplay-reporting-secret-key-file, --levelplay-reporting-refresh-token-file, --levelplay-reconcile-threshold 20, --applovin-report-key-file, --applovin-reconcile-threshold 20. An empty value removes the key
test-show, test-enable, test-disable Test mode switch
simulate --user, --ad-unit, --reward-type, --reward-amount, --custom-data, --outcome completed|skipped|failed, --transaction-id, --network test|admob|applovin|levelplay
simulate-impressions --user, --ad-unit, --count 1..50, --network, --revenue-usd 0.01 or --revenue 1.5 --currency JPY, --country US, --platform ios|android|web, --custom-data exp=B,cohort=7
stats --from YYYY-MM-DD, --to YYYY-MM-DD, --group-by day,ad_unit,network,country,platform,ad_format,currency, --environment production|test, --source client|report, --network, --ad-unit
export --from, --to, --group-by day, --group-fields exp,cohort, --environment, --format json|csv, --limit n
reports Report pull status per network
report-pull --network levelplay|applovin, --from, --to (default: the last three days)
anomalies --open, --limit 50
Terminal window
npx @kasskeep/cli ads export --id app_xxx --from 2026-01-01 --to 2026-01-31 --group-fields exp --format csv > ads.csv
Subcommand Options
catalog Alert types and their severity
list --app-id <app_id>
create --channel telegram|email|webhook, --name, --app-id (leave it out for every app of the tenant) and the channel options below
update --subscription <id> plus any create option except --channel
show, remove, test --subscription <id>
logs --subscription <id>, --limit 50
Channel Options
telegram --chat-id <id> (group ids are negative: --chat-id=-100123), --bot-token-file <file|->
email --to a@example.com,b@example.com, --from, --smtp-host, --smtp-port 587, --smtp-security starttls|tls|none, --smtp-user, --smtp-password-file <file|->
webhook --url https://..., --signing-secret-file <file|-> (a signing secret is generated and shown once when omitted)

Filters for every channel: --events purchase,refund,...\|all, --environments production,sandbox, --min-severity info\|warning\|critical, --locale zh-CN\|en, --enabled true\|false, --hourly-limit 20, --window-seconds 600.