Skip to content

Importing Your First License

This tutorial covers importing and configuring your first license (entitlement) in Big Picture. Licenses control access to your software and are enforced through lease-based tokens.

  • Big Picture instance with licensing enabled
  • API credentials with entitlement management permissions
  • A product with releases published
  • License server configured (cloud or local)

Big Picture uses a lease-based licensing model:

  • Entitlements — Contract truth defining what a customer is licensed to use
  • Lease Tokens — Short-lived, signed tokens (PASETO) issued to clients
  • License Server — Validates entitlements and issues leases (cloud or local)

No offline license keys — all licensing involves a server connection, ensuring real-time enforcement and auditability.

An entitlement represents a customer’s license contract. Create one:

Terminal window
curl -X POST "${BP_BASE_URL}/v1/entitlements" \
-H "Authorization: Bearer $BP_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tenant_id": "customer-tenant-id",
"product_id": "your-product-id",
"policy_json": {
"type": "concurrent",
"max_seats": 10,
"features": ["feature-a", "feature-b"]
},
"starts_at": "2024-01-01T00:00:00Z",
"ends_at": "2024-12-31T23:59:59Z"
}'

Response:

{
"entitlement_id": "ent_abc123",
"tenant_id": "customer-tenant-id",
"product_id": "your-product-id",
"policy_json": {...},
"starts_at": "2024-01-01T00:00:00Z",
"ends_at": "2024-12-31T23:59:59Z",
"created_at": "2024-01-15T10:30:00Z"
}

License policies define how entitlements are enforced:

Policy Types:

  • per_user — One license per user
  • per_machine — One license per device
  • concurrent — Floating licenses with maximum concurrent usage
  • feature_based — Feature-based licensing without seat limits

Example: Concurrent License

{
"type": "concurrent",
"max_seats": 10,
"features": ["feature-a", "feature-b"]
}

Example: Per-User License

{
"type": "per_user",
"max_seats": 50,
"features": ["feature-a", "feature-b"]
}

Update an entitlement’s policy:

Terminal window
curl -X PUT "${BP_BASE_URL}/v1/entitlements/ent_abc123" \
-H "Authorization: Bearer $BP_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"policy_json": {
"type": "concurrent",
"max_seats": 20,
"features": ["feature-a", "feature-b", "feature-c"]
}
}'

Clients request lease tokens from the license server. This is typically done by your application using the Big Picture SDK:

Rust SDK Example:

use bigpicture_sdk::Client;
use bigpicture_sdk::Subject;
let client = Client::builder()
.base_url("https://license-server.example.com")
.build()?;
let lease = client.request_lease(
"your-product-id",
"your-tenant-id",
Subject::user("user_123"),
).await?;

HTTP API (for testing):

Terminal window
curl -X POST "${BP_BASE_URL}/v1/license/lease" \
-H "Content-Type: application/json" \
-d '{
"product_id": "your-product-id",
"tenant_id": "your-tenant-id",
"subject_type": "user",
"subject_id": "user_123"
}'

Response:

{
"lease_id": "lease_xyz789",
"token": "v4.public.eyJ...",
"expires_at": "2024-01-15T11:30:00Z",
"features": ["feature-a", "feature-b"]
}

The token is a PASETO v4.public token that clients verify locally.

Leases expire and must be renewed. Clients renew automatically:

Terminal window
curl -X POST "${BP_BASE_URL}/v1/license/lease/renew" \
-H "Content-Type: application/json" \
-d '{
"lease_id": "lease_xyz789"
}'

Response:

{
"lease_id": "lease_xyz789",
"token": "v4.public.eyJ...",
"expires_at": "2024-01-15T12:30:00Z",
"features": ["feature-a", "feature-b"]
}

Step 5: Release a Lease (Floating Licenses)

Section titled “Step 5: Release a Lease (Floating Licenses)”

For concurrent licenses, clients release leases when done:

Terminal window
curl -X POST "${BP_BASE_URL}/v1/license/lease/release" \
-H "Content-Type: application/json" \
-d '{
"lease_id": "lease_xyz789"
}'

This frees the seat for another user.

Query license status for a subject:

Terminal window
curl "${BP_BASE_URL}/v1/license/status?product_id=your-product-id&subject_type=user&subject_id=user_123" \
-H "Authorization: Bearer $BP_API_TOKEN"

Response:

{
"entitlement_id": "ent_abc123",
"status": "active",
"current_lease": {
"lease_id": "lease_xyz789",
"expires_at": "2024-01-15T11:30:00Z"
},
"features": ["feature-a", "feature-b"],
"usage": {
"concurrent_seats_used": 5,
"max_seats": 10
}
}

For air-gapped or regulated environments, configure a local license server:

  1. Deploy license server — See Installing Big Picture
  2. Sync entitlements — Manually provision or enable outbound sync
  3. Configure clients — Point clients to local license server endpoint

Manual entitlement provisioning:

Terminal window
# On local license server
curl -X POST "http://localhost:8080/v1/entitlements" \
-H "Authorization: Bearer $LOCAL_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tenant_id": "local-tenant-id",
"product_id": "your-product-id",
"policy_json": {
"type": "concurrent",
"max_seats": 10
},
"starts_at": "2024-01-01T00:00:00Z",
"ends_at": "2024-12-31T23:59:59Z"
}'

Clients configured to use the local server will request leases from it instead of the cloud.

If you’re migrating from another licensing system, you may need to bulk import entitlements:

Bulk import format:

{
"entitlements": [
{
"tenant_id": "customer-1",
"product_id": "product-a",
"policy_json": {...},
"starts_at": "...",
"ends_at": "..."
},
{
"tenant_id": "customer-2",
"product_id": "product-a",
"policy_json": {...},
"starts_at": "...",
"ends_at": "..."
}
]
}

Import API (if available):

Terminal window
curl -X POST "${BP_BASE_URL}/v1/entitlements/import" \
-H "Authorization: Bearer $BP_API_TOKEN" \
-H "Content-Type: application/json" \
-d @entitlements.json

Note: Bulk import endpoints may not be available in all deployments. Check API documentation or use individual entitlement creation in a script.

Now that you’ve configured licensing: