Skip to main content

API Keys

An API key is an X.509 certificate you register with Last Lock. You keep the private key and sign short-lived JWTs with it; Link verifies each JWT against the registered certificate. Last Lock never holds a secret that can call the API on your behalf.

Registering a certificate​

An organization or site admin registers certificates in the dashboard under Link Manager → API Keys. Upload a PEM or DER encoded certificate whose public key is one of:

KeyJWT alg
ECDSA P-256ES256
RSA, 2048 bits or moreRS256
ML-DSA-44, ML-DSA-65 or ML-DSA-87 (post-quantum, FIPS 204)ML-DSA-44, ML-DSA-65 or ML-DSA-87

A self-signed certificate is fine; Link uses only its public key and validity window. With OpenSSL 3.5 or later:

openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 \
-keyout key.pem -out cert.pem -days 365 -nodes -subj /CN=my-integration
# or, post-quantum:
openssl req -x509 -newkey ML-DSA-65 \
-keyout key.pem -out cert.pem -days 365 -nodes -subj /CN=my-integration

The dashboard can also generate an ECDSA or RSA key pair in your browser. The private key is downloaded to you and never sent to Last Lock.

The dashboard shows each key's key ID, the hex SHA-256 of the certificate's SubjectPublicKeyInfo. To compute it yourself:

openssl x509 -in cert.pem -pubkey -noout \
| openssl pkey -pubin -outform DER \
| openssl dgst -sha256

Revoking a key in the dashboard takes effect on the next request.

Limiting a key to sites​

A key is either organization-wide or limited to one or more sites, chosen when it is registered. JWTs signed by a site-limited key:

  • see and act on only the devices in those sites; any other device is reported as not found;
  • receive only audits from devices in those sites;
  • cannot move a device into a site outside them;
  • cannot manage audit webhooks, which deliver audits from every site.

Organization admins can register keys for any sites or for the whole organization. Site admins can register, see and revoke only keys limited to sites they administer.

Signing requests​

Send the JWT as a bearer token:

authorization: Bearer <jwt>

Link accepts a JWT when all of the following hold:

FieldRequirement
header algThe algorithm for the certificate's key, from the table above
header kidThe key ID of a registered certificate
audlink_<org id>
iat, expBoth present, exp in the future, and exp - iat at most one hour
certificateCurrently within its notBefore/notAfter window

A valid JWT signed by an organization-wide key has full access to your organization's Link API; one signed by a site-limited key is confined to its sites (see above).

Example​

import time, jwt # PyJWT

now = int(time.time())
token = jwt.encode(
{"aud": "link_<org id>", "iat": now, "exp": now + 300},
open("key.pem").read(),
algorithm="ES256",
headers={"kid": "<key id>"},
)

For an ML-DSA key, if your JWT library does not support ML-DSA yet, build the token by hand: sign the standard JWS signing input, base64url(header) + "." + base64url(payload), with ML-DSA and an empty context string, then append "." + base64url(signature). The header is {"alg": "ML-DSA-65", "kid": "<key id>", "typ": "JWT"} (or ML-DSA-44 / ML-DSA-87 to match the key).