Using the API
Everything you do in the app, you can do with the REST API: create licenses after a sale on your website, look up a customer from your support tool, record a release from your build pipeline. The app itself uses the same API.
The API Reference, in the top menu, lists every endpoint with its parameters, responses and error codes. This section explains what’s common to all of them.
Base URL
Every endpoint is under /v1:
https://api.licensemanager.dev/v1The API is described by an OpenAPI 3.1 document at https://api.licensemanager.dev/openapi.json, from which you can generate a client in most languages.
SDKs
Rather than calling the API directly, you can use an official SDK, for TypeScript, Go, Python, Ruby, Java, C# or PHP. Each one is a thin, typed wrapper around the API: one method per endpoint, with the same parameters, responses and errors, so everything in this section applies to them too.
import { Configuration, ProductsApi } from "@licenseman/sdk";
const products = new ProductsApi(
new Configuration({ apiKey: process.env.LICENSEMANAGER_API_KEY }),
);
const { data } = await products.listProducts();A first request
Create an API key, then list your products:
curl https://api.licensemanager.dev/v1/products \
-H "x-api-key: $API_KEY"{
"data": [
{ "id": "x7Kp2QaZ", "name": "Acme Photo", "slug": "acme-photo", "…": "…" }
],
"pagination": { "page": 1, "pageSize": 20, "total": 1, "totalPages": 1 }
}Then create a license:
curl -X POST https://api.licensemanager.dev/v1/products/x7Kp2QaZ/licenses \
-H "x-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{ "email": "jane@example.com", "sendKey": true }'The license follows the product’s default policy, the customer is found or created from the email, and the key is emailed to them.
Who calls the API
| Caller | Authenticates with | Reaches |
|---|---|---|
| Your backend, scripts, CI | An API key | Everything in your organization, live or test. |
| Your application, to validate a key | Nothing | The validation endpoint only. |
| Your customers, through the customer portal or your own pages | A scoped token, created by your backend | Their own licenses and machines. |
| The app, for your team | A session | What each member’s role allows. |
Conventions
- JSON in and out. Send
Content-Type: application/jsonwith a body. - Ids are 8 letters and digits, like
x7Kp2QaZ, prefixed withtest_for test products and everything in them. They never change. - Dates are ISO 8601. Send them with any offset, like
2026-03-01T10:00:00+02:00: they’re always returned in UTC, like2026-03-01T08:00:00.000Z. Calendar months and days, like a policy’s duration, are counted in UTC. - Strings are trimmed before they’re checked and stored. Emails are stored in lower case.
- Updates are partial:
PATCHonly changes the fields you send. Sendnullto clear a field, when it can be cleared, like a license’sexpiresAtto make it never expire. - Unknown fields are ignored, not refused: sending
policyIdwhen updating a license changes nothing, and doesn’t fail. Check the reference when a change doesn’t apply. - Lists are paginated: see pagination.
- Errors share one format, with a stable
code: see errors.
Because unknown fields are ignored, a typo in a field name, like expiresOn instead of expiresAt, silently does nothing. Check the response: it always returns the resource as stored.
Calling from a browser
The API answers cross-origin requests from any website, with an API key or a token, but never with cookies. Only call it with scoped tokens from a browser: an API key in a web page is readable by anyone visiting it.
Usage and quotas
Requests made with an API key or a token, and key validations, count toward your plan’s API requests. Requests made from the app don’t. Each API key can also make up to 10 requests per second. See rate limits and quotas.