Dry-run verify a license envelope
POST /admin/license/validate
Verifies the supplied .lic text against the embedded
publisher catalog without persisting anything. Used by the
admin UI to preview a license before clicking “Install”.
On success the response carries the same LicenseStatus
shape the GET endpoint returns, with loaded: true and the
Status fields populated from the candidate envelope. The
currently installed license is NOT touched.
On verifier failure (bad signature, expired, unknown publisher key, etc.) the response is a structured
LicenseValidateError describing the failure so the UI can
render an actionable message instead of a generic 400.
Authorizations
Section titled “Authorizations ”Request Body required
Section titled “Request Body required ”Payload for POST /admin/license/validate and POST /admin/license/upload. Carries the verbatim .lic envelope text — BEGIN/END markers, key: value fields, signature field — exactly as the customer downloaded it.
object
Full .lic file body including the BEGIN/END markers. Whitespace + line wrapping are tolerated by the verifier.
Responses
Section titled “ Responses ”Envelope verified successfully (not installed).
License snapshot returned by GET /admin/license/status.
loaded: false means no .lic file is
installed and the artist-alley app is running in community
mode — community defaults apply, no license-server
interaction needed.
days_until_expiry is derived (0 in community mode;
negative when expired). Nullable cap fields (seats,
asset_cap) → null = unlimited. Nullable temporal /
identity fields are simply omitted in community mode.
object
True when a real .lic file is mounted + verified. False = community mode.
“community” (unlicensed default) | “pro” | “enterprise” | “complementary” | “plugin” | “custom”.
License owner email — surfaced for support routing.
Organization slug — same value across federated peers.
License id (ULID); surface in support tickets.
Max concurrent active seats; null = unlimited.
Rolling window for “active seat” counting.
Asset cap (primary assets only); null = unlimited.
Not-before timestamp (RFC3339).
Expiry timestamp.
Issued-at timestamp.
Whole days until license expires. Negative when expired. Zero in community mode (no expiry).
Last verification error if the loaded license failed (e.g. expired, wrong issuer). Surfaced verbatim in the admin UI so operators can react.
Issuer string baked into the license — admins can confirm the .lic came from the canonical authority.
Filesystem path the verifier loaded the .lic from. Useful for diagnostics + support.
True when the loaded license declares an org_pubkey
claim — the customer must hold the matching org.key
seed file on disk for the license to activate. False for
community / trial / dev licenses that opted out of
cross-binding at issuance time.
True when the install satisfies cross-binding — either
because org_binding_required is false (no binding to
satisfy), or because the on-disk org.key derives to a
public key matching the license’s org_pubkey. The
cap-enforcement layer only treats the license as active
when this is true.
Human-readable reason cross-binding failed when
org_binding_required is true and org_bound is false.
One of: “org.key missing”, “org.key malformed”, “org.key
does not match license org_pubkey”.
Filesystem path the verifier consults for the org.key seed. Echoed back to the admin UI so operators see exactly where to drop the file when cross-binding fails.
Envelope rejected by the verifier.
Structured 400 response from /admin/license/validate +
/admin/license/upload. code is a stable machine-readable
token the UI can switch on for i18n; message is the raw
verifier error string for diagnostics.
object
Human-readable summary (constant “license validation failed”).
Stable token for UI branching. One of:
bad_envelope, bad_signature, expired,
not_yet_valid, unknown_publisher_key,
wrong_issuer, chain_expired, chain_bad_signature,
chain_scope, chain_kid_mismatch,
org_key_missing, org_key_bad_format,
org_key_mismatch, unknown.
Raw verifier error string for diagnostics.
Authentication required, missing, or invalid
object
Human-readable error summary
Example
the request could not be completedExample
{ "error": "authentication required: sign in and retry with a valid session or API token"}Authenticated but missing required capabilities
object
Human-readable error summary
Example
the request could not be completed