Overview
Chiave provides a REST API that your application uses to enforce software licensing. There are two categories of endpoints:
End-user endpoints — Your desktop app or SaaS backend calls these to validate a license key, activate a machine, or deactivate a machine. These require only the tenant slug and a license key.
Management endpoints — Your server calls these to create, revoke, or query licenses programmatically. These require an API key for authentication.
All endpoints use JSON request and response bodies. The base URL is https://chiave.wigleystudios.com/api/v1/{your-slug}.
Quick Start
2
Create a Product
Add your software product in the onboarding wizard or dashboard.
3
Generate an API Key
Go to Settings → API Keys and generate a key for your server.
4
Integrate
Use the API to create licenses and validate them in your app.
Authentication
Management endpoints (create, revoke, info) require an API key. Generate one from your Chiave dashboard under Settings → API Keys .
Send the key in the Authorization header:
Authorization: Bearer chi_sk_aB3x7kQ9mN2pR5tV8wY1zA...
Security
API keys grant full license management access. Keep them on your server — never embed them in client-side code or mobile apps. You can generate up to 5 keys per account and revoke any key instantly from the dashboard.
End-user endpoints (validate, activate, deactivate) do not require an API key. They use your tenant slug in the URL and the license key in the request body.
License Validation
POST
/api/v1/{tenant_slug}/licenses/validate
Check whether a license key is valid. Call this from your application at startup or periodically.
Request
{
"license_key ": "CHV-A1B2C-D3E4F-G5H6I-J7K8L ",
"product_slug ": "my-app "
}
Response
{
"valid ": true ,
"status ": "ACTIVE ",
"tier ": "STANDARD ",
"license_type ": "PERPETUAL ",
"expiration_date ": null ,
"activation_count ": 1 ,
"max_activations ": 3 ,
"can_activate ": true
}
Code Examples
cURL
Python
Node.js
curl -X POST https://chiave.wigleystudios.com/api/v1/your-slug/licenses/validate \
-H "Content-Type: application/json" \
-d '{"license_key": "CHV-A1B2C-D3E4F-G5H6I-J7K8L"}'
import requests
response = requests.post(
"https://chiave.wigleystudios.com/api/v1/your-slug/licenses/validate" ,
json={"license_key" : "CHV-A1B2C-D3E4F-G5H6I-J7K8L" }
)
data = response.json()
if data["valid" ]:
print("License is active" )
else :
print(f"License status: {data['status']}" )
const response = await fetch(
"https://chiave.wigleystudios.com/api/v1/your-slug/licenses/validate" ,
{
method: "POST" ,
headers: { "Content-Type" : "application/json" },
body: JSON.stringify({ license_key: "CHV-A1B2C-D3E4F-G5H6I-J7K8L" })
}
);
const data = await response.json();
console.log(data.valid ? "Active" : data.status);
License Activation
POST
/api/v1/{tenant_slug}/licenses/activate
Register a machine against a license. Enforces the activation limit.
Request
{
"license_key ": "CHV-A1B2C-D3E4F-G5H6I-J7K8L ",
"machine_id ": "a1b2c3d4-e5f6-7890-abcd-ef1234567890 ",
"machine_name ": "Alice's Workstation "
}
Response
{
"activated ": true ,
"activation_id ": 42 ,
"reactivated ": false
}
If the same machine_id is already active, the endpoint returns reactivated: true and updates the last-seen timestamp without consuming an additional activation slot.
License Deactivation
POST
/api/v1/{tenant_slug}/licenses/deactivate
Remove a machine activation, freeing the slot for another device.
Request
{
"license_key ": "CHV-A1B2C-D3E4F-G5H6I-J7K8L ",
"machine_id ": "a1b2c3d4-e5f6-7890-abcd-ef1234567890 "
}
License Creation
Requires API Key
This endpoint requires authentication via an API key in the Authorization header.
POST
/api/v1/{tenant_slug}/licenses
Create a new license key programmatically. Subject to your tier’s license and customer limits.
Request
{
"customer_email ": "customer@example.com ",
"customer_name ": "Jane Doe ",
"product_slug ": "my-app ",
"tier ": "STANDARD ",
"max_activations ": 3 ,
"expiration_days ": 365
}
Response (201)
{
"license_key ": "CHV-A1B2C-D3E4F-G5H6I-J7K8L ",
"license_id ": 15 ,
"customer_id ": 8 ,
"expiration_date ": "2027-04-25 ",
"status ": "ACTIVE "
}
Code Examples
cURL
Python
Node.js
curl -X POST https://chiave.wigleystudios.com/api/v1/your-slug/licenses \
-H "Content-Type: application/json" \
-H "Authorization: Bearer chi_sk_YOUR_API_KEY" \
-d '{"customer_email": "customer@example.com", "max_activations": 3}'
import requests
API_KEY = "chi_sk_YOUR_API_KEY"
response = requests.post(
"https://chiave.wigleystudios.com/api/v1/your-slug/licenses" ,
headers={"Authorization" : f"Bearer {API_KEY}" },
json={
"customer_email" : "customer@example.com" ,
"product_slug" : "my-app" ,
"max_activations" : 3 ,
"expiration_days" : 365
}
)
license_data = response.json()
print(f"Created: {license_data['license_key']}" )
const response = await fetch(
"https://chiave.wigleystudios.com/api/v1/your-slug/licenses" ,
{
method: "POST" ,
headers: {
"Content-Type" : "application/json" ,
"Authorization" : `Bearer ${API_KEY}`
},
body: JSON.stringify({
customer_email: "customer@example.com" ,
product_slug: "my-app" ,
max_activations: 3
})
}
);
const data = await response.json();
console.log(`Created: ${data.license_key}` );
License Revocation
Requires API Key
POST
/api/v1/{tenant_slug}/licenses/revoke
Permanently revoke a license key. The key will fail all subsequent validation checks.
Request
{
"license_key ": "CHV-A1B2C-D3E4F-G5H6I-J7K8L "
}
Response
{
"revoked ": true ,
"license_id ": 15 ,
"already_revoked ": false
}
License Info
Requires API Key
GET
/api/v1/{tenant_slug}/licenses/{license_key}
Retrieve full details for a license, including active machine activations.
Response
{
"license_key ": "CHV-A1B2C-D3E4F-G5H6I-J7K8L ",
"license_id ": 15 ,
"status ": "ACTIVE ",
"tier ": "STANDARD ",
"license_type ": "PERPETUAL ",
"product_slug ": "my-app ",
"customer_email ": "customer@example.com ",
"expiration_date ": null ,
"activation_count ": 1 ,
"max_activations ": 3 ,
"can_activate ": true ,
"activations ": [
{
"machine_id ": "a1b2c3d4-e5f6-... ",
"machine_name ": "Alice's Workstation ",
"activated_at ": "2026-04-25T12:00:00 ",
"last_seen_at ": "2026-04-25T14:30:00 ",
"is_active ": true
}
],
"created_at ": "2026-04-20T10:00:00 "
}
Stripe Webhook Automation
Unlimited Plan Only
Automatic license creation from Stripe checkout events is available on the Unlimited plan ($99.99/mo).
If you use Stripe for payments, Chiave can automatically create licenses when your customers complete checkout. Setup:
In your Stripe Dashboard, create a webhook endpoint pointing to:
https://chiave.wigleystudios.com/stripe/webhook/{your-slug}
Subscribe to these events: checkout.session.completed, customer.subscription.deleted, invoice.payment_failed
Copy the webhook signing secret from Stripe
In Chiave, go to Settings → Stripe and paste the webhook secret
When a customer completes a Stripe Checkout session, Chiave automatically:
Creates a customer record (or finds the existing one by email)
Generates a license key with ACTIVE status
Suspends licenses when a subscription is cancelled or payment fails repeatedly
Error Reference
Status Meaning Common Cause
400Bad Request Missing required field, invalid product slug
401Unauthorized Missing or invalid API key (management endpoints)
403Forbidden License inactive, activation limit reached, tier limit exceeded, email not verified, trial expired
404Not Found Invalid tenant slug, license key not found
422Validation Error Request body failed schema validation
429Rate Limited Too many requests — retry after the indicated interval
All error responses include a detail field with a human-readable message:
{
"detail ": "License limit reached (500). Upgrade to Unlimited for more. "
}
Ready to Integrate?
Start a 14-day free trial — no credit card required. Full API access with Starter-tier limits.
Start Free Trial