DOCS LLMs

Get Signing Key

Get Signing Key

Retrieves an Ed25519 public key for verifying offline token signatures.

GET /api/v1/signing_keys/{key_id}

Note: This endpoint does not require authentication.

Try it in the Interactive API Docs →

When to Use

  • Fetching verification keys for offline tokens
  • Supporting key rotation
  • Dynamically loading unknown key IDs

Path Parameters

Parameter Required Description
key_id Yes Key ID from offline token signature.key_id or token.kid

Example Request

curl https://licenseseat.com/api/v1/signing_keys/org-xxx-offline-v1

No authentication required.

Response

{
  "object": "signing_key",
  "key_id": "org-xxx-offline-v1",
  "algorithm": "Ed25519",
  "public_key": "base64url_encoded_32_byte_public_key",
  "created_at": "2024-01-01T00:00:00Z",
  "status": "active"
}

Response Fields

Field Description
key_id Unique key identifier
algorithm Signature algorithm (Ed25519)
public_key Base64url-encoded 32-byte Ed25519 public key
created_at When the key was created
status Key status (active, rotated)

Error Codes

Code HTTP Meaning
signing_key_not_found 404 Key ID doesn't exist

Key Rotation

LicenseSeat supports key rotation for security:

  1. New offline tokens use the latest key
  2. Old keys remain valid for existing tokens
  3. The key_id field identifies which key was used
  4. Your app should fetch keys it doesn't recognize

Best Practices

Embed Known Keys

For performance and offline support, embed known public keys in your app:

const KNOWN_KEYS = {
  'org-xxx-offline-v1': 'base64url_encoded_key_1',
  'org-xxx-offline-v2': 'base64url_encoded_key_2',
};

async function getPublicKey(keyId) {
  // Use embedded key if known
  if (KNOWN_KEYS[keyId]) return KNOWN_KEYS[keyId];
  // Fetch unknown keys from API
  const response = await fetch(`/api/v1/signing-keys/${keyId}`);
  const data = await response.json();
  return data.public_key;
}

Security

  • Validate key length — Decoded key must be exactly 32 bytes
  • Always verify signatures — Even with embedded keys
  • Handle new key IDs — Be prepared for key rotation
  • Use constant-time comparison — Prevent timing attacks

See Also