Code Heaven Developer License API
The Developer License API is the server-to-server interface vendors use to license their own plugins through Code Heaven. When a customer buys your plugin on the Code Heaven marketplace, Code Heaven issues a license. Your plugin then calls this API to confirm the license is real, activate the customer's domain, and serve updates.
You do not have to build a licensing server, a key generator, an activation database, or an update CDN. Code Heaven runs all of that. Your plugin makes a handful of HTTPS calls and acts on the answers.
This API is not the buyer-facing OAuth flow customers use to log in to their dashboard. It is a vendor credential — a single secret key, scoped to you, that authorizes calls on behalf of every license you have sold. See Authentication for how that key works.
What the API is for
The API exists to answer four questions your plugin needs answered at runtime:
- Is this license valid right now? A customer pasted a key into your settings screen. Is it real, paid-up, and entitled to this product? See Quickstart.
- Is this specific domain allowed to use it? A license is sold for a fixed number of sites. Activating, checking, and releasing domains is the license lifecycle.
- Is there a newer version, and where do I get it? Your plugin polls for updates and downloads the package from a short-lived signed URL.
- How do I do all of the above without rewriting HTTP plumbing? Use the PHP SDK.
The license model
Every sale produces exactly one license key — an opaque string Code Heaven generates at checkout. The key is the unit of entitlement. It belongs to one buyer, references one product, and carries the terms of that purchase.
A license has three properties your code cares about:
| Concept | Meaning |
|---|---|
| Key | The per-purchase secret the customer holds. They paste it into your plugin. |
| Product | The plugin this license entitles. A buyer who owns three of your plugins has three keys. |
| Status | The license's current standing: valid, expired, revoked, or — for a key that is fine but not yet bound to the requesting site — domain_not_activated. |
Per-purchase key plus domain activations
A single key is not a free pass to install on unlimited sites. Each license carries a seat limit — the number of distinct domains that may run the plugin at once. A "seat" is a domain.
license key ──┬──> activation: example.com (seat 1)
├──> activation: staging.example.com (seat 2)
└──> activation: client-site.io (seat 3)
seatLimit: 3 → no seats left
When a customer installs your plugin and enters their key, your plugin activates their domain — it claims a seat. Code Heaven records the domain and the timestamp. When the customer moves a site or retires one, your plugin deactivates that domain to free the seat.
This is why validation is always tied to a domain. A key can be perfectly valid and still be refused on a given site because that site has not claimed a seat (domain_not_activated) or because every seat is already taken (seat_limit_exceeded). The license lifecycle page walks through every state.
The five endpoints
All requests go to the base URL and authenticate with your vendor key:
Base URL: https://api.code-heaven.com/v1
Header: X-CH-Vendor-Key: <your vendor key>
| Method | Path | Purpose |
|---|---|---|
POST | /licenses/validate | Check a key + domain and read its status, expiry, and activations |
POST | /licenses/{licenseKey}/domains | Activate a domain (claim a seat) |
DELETE | /licenses/{licenseKey}/domains/{domain} | Deactivate a domain (release a seat) |
GET | /licenses/{licenseKey}/updates | Ask whether a newer version exists |
GET | /licenses/{licenseKey}/download | Get a short-lived signed URL for the package |
A typical integration
A complete plugin integration looks like this:
- The customer enters their license key in your plugin's settings screen.
- Your plugin calls
POST /licenses/{key}/domainsto activate the current domain, thenPOST /licenses/validateto confirm and cache the result. - On every relevant request — admin page load, scheduled check — your plugin treats the cached
status == "valid"as the gate for premium features. - On a schedule (daily is plenty), your plugin calls
GET /licenses/{key}/updates. IfhasUpdateis true, it surfaces an update prompt. - When the customer updates, your plugin calls
GET /licenses/{key}/download, fetches the signed URL, and installs the package. - If the customer deactivates the plugin or migrates the site, your plugin calls
DELETE /licenses/{key}/domains/{domain}to free the seat.
Every step is covered in detail in the pages that follow. Start with Authentication to get your key, then run through the Quickstart to gate a plugin in five minutes.