Skip to content

Interfaces

Call the REST API with an API key

Create an API key for a product, make a request to api.lessly.com with it, and revoke it when you are done.

The REST API lives at https://api.lessly.com. It is the HTTP face of the same operations available in the Product App, the CLI and over MCP. The per-area route catalog is on the REST API reference.

Create a key

Keys are per-product, and made for scripts, CI and agents.

App. The product’s Developer page.

REST.

curl -X POST https://api.lessly.com/auth/api/v1/api-keys \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"productId": "'"$PRODUCT_ID"'", "name": "ci-deploy"}'

The response contains the key’s id, productId, name, createdAt, lastUsedAt, and plaintext — the raw lsk_dev_… value.

plaintext is returned exactly once. Only a SHA-256 hash of the key is stored, so a key that was not copied at creation time cannot be recovered. Issue a new one instead.

A key cannot mint another key: a request authenticated with an API key is rejected with 403. Creating a key requires a signed-in user.

Use the key on a request

curl https://api.lessly.com/governance/api/v1/products \
  -H "Authorization: Bearer lsk_dev_..."

That endpoint — GET /governance/api/v1/products, the products the caller has access to — is on the Organization API page, alongside the rest of the area.

Two credential kinds are accepted, and the platform tells them apart by their shape:

  • A session token, obtained by signing in. Short-lived.
  • An API key, which starts with lsk_dev_. Long-lived.

Requests from the Product App itself run on the browser session instead of a bearer header, and mutating calls additionally send an X-CSRF-Token header.

Shape of a URL

A request path starts with the platform area it addresses, followed by a versioned route inside that area:

https://api.lessly.com/<area>/api/v1/<resource>

The version prefix is v1. Breaking changes to a route arrive under a new version prefix; the previous one keeps its behaviour. Two areas appear throughout this page: governance for products, organizations, members and invitations, and auth for sign-in and API keys.

Choosing the product

Many routes act on one product. Which one is decided by the X-Product-Id request header:

X-Product-Id: <product-uuid>

An API key is minted for exactly one product, and that is a ceiling it cannot cross. A request presenting an API key together with an X-Product-Id naming a different product is refused with 403 and the reason api_key_product_scope_denied. The request is not silently rewritten to the key’s own product: writing to A while the caller believes it wrote to B is worse than failing.

Trade a key for a short-lived token

curl -X POST https://api.lessly.com/auth/api/v1/api-keys/exchange \
  -H "Authorization: Bearer lsk_dev_..."

Called with an API key, this returns a token valid for one hour, carrying the key’s product. Use it where a long-lived credential should not be held by the code doing the work. Calling it with anything other than an API key answers 400.

List and revoke keys

curl "https://api.lessly.com/auth/api/v1/api-keys?productId=$PRODUCT_ID" \
  -H "Authorization: Bearer $SESSION_TOKEN"

Returns the product’s active keys with id, name, createdAt and lastUsedAt. The secret value is never part of this response.

curl -X DELETE https://api.lessly.com/auth/api/v1/api-keys/$KEY_ID \
  -H "Authorization: Bearer $SESSION_TOKEN"

Answers 204, and the key stops working. A key that does not exist, or that belongs to somebody else, answers 404 — the same response either way, so the call cannot be used to probe for other people’s keys.

There is no rotate call. Rotation is two steps: create the replacement key, put it into service, then revoke the old one. Both keys are valid in between, so nothing has to go down during the swap.

Next steps

Was this page helpful?
Esc

Start typing to search the docs.

navigateselect