Licenses
Licenses are cryptographically signed JWT tokens that authorize software usage. Each license is tied to a customer, tier, and optionally specific features.
How It Works
Issue
Create a license via API. Blackwalnut signs it with your app's private key.
Deliver
Send the JWT token to your customer. They enter it in your software.
Verify
Your software verifies the token using the public key. Works offline.
License Properties
| Field | Type | Description |
|---|---|---|
installation_id | UUID | Unique identifier for this installation (becomes JWT subject) |
customer_id | string | Reference to the customer |
tier_id | string | Reference to the licensing tier |
features | string[]? | Array of feature slugs to enable |
duration_days | integer? | License duration (mutually exclusive with expires_at, forever) |
expires_at | datetime? | Specific expiration date |
forever | boolean? | Set to true for perpetual licenses (no expiration) |
Creating Licenses
# Time-limited license (1 year)
$ curl -X POST http://localhost:4000/api/v1/apps/my-app/licenses \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"installation_id": "550e8400-e29b-41d4-a716-446655440000",
"customer_id": "cus_abc123",
"tier_id": "tier_xyz789",
"features": ["api_access", "export"],
"duration_days": 365
}'
# Forever license
$ curl -X POST http://localhost:4000/api/v1/apps/my-app/licenses \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"installation_id": "660e8400-e29b-41d4-a716-446655440000",
"customer_id": "cus_abc123",
"tier_id": "tier_xyz789",
"forever": true
}' JWT Token Claims
The license token contains these standard and custom claims:
| Claim | Description |
|---|---|
sub | Subject - the installation_id |
aud | Audience - the app slug |
iss | Issuer - configurable (default: "license-server") |
iat | Issued at timestamp |
exp | Expiration timestamp (omitted for forever licenses) |
jti | Unique token ID (format: lic_xxxxx) |
tier | Tier slug |
features | Array of enabled feature slugs |
lic_id | License UUID - unique identifier for the license record |
License Status
Licenses have one of three statuses:
Active
Not expired and not revoked. Valid for use.
Expired
Past the expiration date. Can be extended.
Revoked
Manually deactivated. Cannot be reactivated.
License Actions
Extend License
Add more time to an existing license:
$ curl -X POST http://localhost:4000/api/v1/apps/my-app/licenses/lic_abc123/extend \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"duration_days": 30}'
# Response includes new token with updated expiration Revoke License
Permanently deactivate a license:
$ curl -X POST http://localhost:4000/api/v1/apps/my-app/licenses/lic_abc123/revoke \
-H "Authorization: Bearer sk_live_..." Regenerate Token
Generate a new token with refreshed features from the current tier configuration. This is useful after key rotation or when tier features have been updated.
# With API key authentication
$ curl -X POST http://localhost:4000/api/v1/apps/my-app/licenses/lic_abc123/regenerate \
-H "Authorization: Bearer sk_live_..."
# Or with license token authentication (self-renewal)
$ curl -X POST http://localhost:4000/api/v1/apps/my-app/licenses/lic_abc123/regenerate \
-H "Content-Type: application/json" \
-d '{"current_token": "eyJhbGciOiJSUzI1NiIs..."}'' Feature refresh: When regenerating, the new token includes all current features from the license's tier, plus any per-license custom features. This allows licenses to automatically receive new tier features.