| Crates.io | keygen-rs |
| lib.rs | keygen-rs |
| version | 0.8.1 |
| created_at | 2024-08-15 02:36:28.15247+00 |
| updated_at | 2025-08-26 06:16:10.2063+00 |
| description | Unofficial Rust SDK for integrating with the keygen.sh licensing service. |
| homepage | |
| repository | |
| max_upload_size | |
| id | 1338231 |
| size | 687,370 |
The keygen-rs crate is an unofficial Rust SDK for integrating with the keygen.sh licensing service.
Keymana is a desktop interface for Keygen.sh that eliminates API calls, offering intuitive license management with multi-account support, advanced filtering, and compatibility with both cloud and self-hosted instances.
Add this to your Cargo.toml:
[dependencies]
keygen-rs = "0.7"
The SDK uses feature flags to minimize binary size:
license-key (default): End-user features for license validation and machine activationtoken: Administrative features requiring token authentication# For end-user features only (default)
keygen-rs = "0.7"
# For administrative features
keygen-rs = { version = "0.7", features = ["token"] }
# For both end-user and administrative features
keygen-rs = { version = "0.7", features = ["license-key", "token"] }
Tauri plugins for this SDK are available:
These plugins provide an easy way to integrate Keygen licensing into your Tauri applications. For more information, check the plugins' respective READMEs.
Use KeygenConfig to configure the SDK globally. You should set this before making any API calls.
use keygen_rs::config::{self, KeygenConfig};
config::set_config(KeygenConfig::license_key(
"YOUR_KEYGEN_ACCOUNT_ID",
"YOUR_KEYGEN_PRODUCT_ID",
"A_KEYGEN_LICENSE_KEY",
Some("YOUR_KEYGEN_PUBLIC_KEY"),
));
use keygen_rs::config::{self, KeygenConfig};
config::set_config(KeygenConfig::admin(
"YOUR_KEYGEN_ACCOUNT_ID",
"YOUR_ADMIN_TOKEN",
));
use keygen_rs::config::{self, KeygenConfig};
config::set_config(KeygenConfig {
api_url: "https://api.keygen.sh".to_string(), // or your custom domain
account: "YOUR_KEYGEN_ACCOUNT_ID".to_string(),
product: "YOUR_KEYGEN_PRODUCT_ID".to_string(),
license_key: Some("A_KEYGEN_LICENSE_KEY".to_string()),
token: Some("YOUR_ADMIN_TOKEN".to_string()),
public_key: Some("YOUR_KEYGEN_PUBLIC_KEY".to_string()),
..KeygenConfig::default()
});
To validate a license, configure KeygenConfig with your Keygen account details. Then call the validate function with a device fingerprint:
use keygen_rs::{config::{self, KeygenConfig}, errors::Error};
#[tokio::main]
async fn main() -> Result<(), Error> {
config::set_config(KeygenConfig::license_key(
"YOUR_KEYGEN_ACCOUNT_ID",
"YOUR_KEYGEN_PRODUCT_ID",
"A_KEYGEN_LICENSE_KEY",
Some("YOUR_KEYGEN_PUBLIC_KEY"),
));
let fingerprint = machine_uid::get().unwrap_or("".into());
let license = keygen_rs::validate(&[fingerprint]).await?;
println!("License validated successfully: {:?}", license);
Ok(())
}
To activate a machine for a license:
use keygen_rs::{
config::{self, KeygenConfig},
errors::Error,
};
#[tokio::main]
async fn main() -> Result<(), Error> {
config::set_config(KeygenConfig::license_key(
"YOUR_KEYGEN_ACCOUNT_ID",
"YOUR_KEYGEN_PRODUCT_ID",
"A_KEYGEN_LICENSE_KEY",
Some("YOUR_KEYGEN_PUBLIC_KEY"),
));
let fingerprint = machine_uid::get().unwrap_or("".into());
if let Err(err) = keygen_rs::validate(&[fingerprint.clone()]).await {
match err {
Error::LicenseNotActivated { license, .. } => {
let machine = license.activate(&fingerprint, &[]).await?;
println!("License activated successfully: {:?}", machine);
}
_ => {
println!("License validation failed: {:?}", err);
}
}
} else {
println!("License validated successfully");
}
Ok(())
}
To verify a signed license key offline:
use keygen_rs::{config::{self, KeygenConfig}, license::SchemeCode};
fn main() {
config::set_config(KeygenConfig::license_key(
"YOUR_KEYGEN_ACCOUNT_ID",
"YOUR_KEYGEN_PRODUCT_ID",
"A_KEYGEN_LICENSE_KEY",
Some("YOUR_KEYGEN_PUBLIC_KEY"),
));
let signed_key = "YOUR_SIGNED_LICENSE_KEY";
if let Ok(data) = keygen_rs::verify(SchemeCode::Ed25519Sign, signed_key) {
println!("License verified: {:?}", String::from_utf8_lossy(&data));
} else {
println!("License verification failed");
}
}
The SDK returns meaningful errors which can be handled in your integration. Here's an example of handling a LicenseNotActivated error:
use keygen_rs::{config::{self, KeygenConfig}, errors::Error};
#[tokio::main]
async fn main() -> Result<(), Error> {
config::set_config(KeygenConfig::license_key(
"YOUR_KEYGEN_ACCOUNT_ID",
"YOUR_KEYGEN_PRODUCT_ID",
"A_KEYGEN_LICENSE_KEY",
Some("YOUR_KEYGEN_PUBLIC_KEY"),
));
let fingerprint = machine_uid::get().unwrap_or("".into());
match keygen_rs::validate(&[fingerprint.clone()]).await {
Ok(license) => println!("License is valid: {:?}", license),
Err(Error::LicenseNotActivated { license, .. }) => {
println!("License is not activated. Activating...");
let machine = license.activate(&fingerprint, &[]).await?;
println!("Machine activated: {:?}", machine);
},
Err(e) => println!("Error: {:?}", e),
}
Ok(())
}
When configured with a token, you can access administrative features:
use keygen_rs::product::{Product, CreateProductRequest, DistributionStrategy};
#[tokio::main]
async fn main() -> Result<(), Error> {
// Create a new product
let product = Product::create(CreateProductRequest {
name: "My App".to_string(),
distribution_strategy: Some(DistributionStrategy::Licensed),
platforms: Some(vec![Platform::MacOs, Platform::Windows]),
..Default::default()
}).await?;
// List all products
let products = Product::list(None).await?;
Ok(())
}
use keygen_rs::policy::{Policy, CreatePolicyRequest, AuthenticationStrategy};
#[tokio::main]
async fn main() -> Result<(), Error> {
// Create a new policy
let policy = Policy::create(CreatePolicyRequest {
name: "Standard License".to_string(),
authentication_strategy: Some(AuthenticationStrategy::License),
duration: Some(365), // days
max_machines: Some(3),
..Default::default()
}).await?;
Ok(())
}
use keygen_rs::license::{License, CreateLicenseRequest};
#[tokio::main]
async fn main() -> Result<(), Error> {
// Create a new license
let license = License::create(CreateLicenseRequest {
policy_id: "POLICY_ID".to_string(),
user_email: Some("user@example.com".to_string()),
..Default::default()
}).await?;
// Suspend a license
license.suspend().await?;
// Reinstate a license
license.reinstate().await?;
Ok(())
}
use keygen_rs::service;
#[tokio::main]
async fn main() -> Result<(), Error> {
// Check if the service is available
service::ping().await?;
// Get detailed service information
let info = service::get_service_info().await?;
println!("API Version: {}", info.api_version);
// Check if a specific feature is supported
if service::supports_product_code().await? {
println!("Product codes are supported!");
}
Ok(())
}
For more detailed examples, please refer to the examples directory in the repository:
/examples/license/ - License validation, activation, and management/examples/machine/ - Machine activation and management/examples/product/ - Product CRUD operations (admin only)/examples/policy/ - Policy management (admin only)/examples/user/ - User management (admin only)/examples/token/ - Token management (admin only)/examples/config_examples.rs - Different configuration approaches/examples/service_info.rs - Service introspectionWhen implementing a testing strategy for your licensing integration, we recommend mocking the Keygen API responses. This is especially important for CI/CD environments to prevent unnecessary load on Keygen's servers and to stay within your account's daily request limits.
You can use crates like mockito or wiremock to mock HTTP responses in your tests.
This project is licensed under the MIT License.