/api/v1/compliance/ledger-keysRotate or revoke the organization's evidence-ledger signing key
Replaces the organization's active Ed25519 evidence-signing key, or revokes a key that is already out of service. ROTATION IS ATOMIC. The outgoing key is retired and the replacement installed in ONE database transaction. Split into two calls there is a window with no active key, during which a concurrent evidence append auto-provisions a third one, and a failure between them leaves the tenant with none. NOTHING HISTORICAL IS INVALIDATED, AND NOTHING IS RE-SIGNED. Every key stays in the trust anchor forever and every record ever signed by this organization keeps verifying. What changes is which key signs from now on, plus a published disposition an auditor can weigh. Re-signing historical records would destroy the hash chain's meaning and is never done. REVOKING THE LIVE KEY IS A ROTATION. `action: "revoke"` deliberately refuses the currently-active key: revoking it without minting a replacement in the same transaction would leave the tenant keyless and the lazy provisioner would then silently mint one nobody decided to create. For a compromised live key use `action: "rotate"` with `compromised: true`, which installs a fresh key and marks the outgoing one REVOKED rather than RETIRED. Owner/admin only: an editor who can author evidence must not be able to change the key that vouches for it. Not plan-gated — replacing a key you believe is leaked is a security control, not an upsell.
Authentication
Send Authorization: Bearer YOUR_API_KEY on every request. Generate API keys at /dashboard/settings/api-keys.
Parameters
orgId in queryrequiredOrganization whose signing keys to return, and which your credential must be scoped to. Must be a UUID; 400 INVALID_ORG_ID otherwise.
stringRequest body required
Schema
{
"application/json": {
"schema": {
"oneOf": [
{
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"rotate"
]
},
"compromised": {
"type": "boolean"
},
"reason": {
"type": "string",
"enum": [
"superseded",
"compromise",
"operator-request",
"offboarding"
]
}
},
"required": [
"action"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"revoke"
]
},
"keyId": {
"type": "string",
"minLength": 1,
"maxLength": 128
},
"reason": {
"type": "string",
"enum": [
"superseded",
"compromise",
"operator-request",
"offboarding"
]
}
},
"required": [
"action",
"keyId",
"reason"
],
"additionalProperties": false
}
]
}
}
}Response
All status codes
Code samples
cURL
curl -X POST \ https://evalguard.ai/api/v1/compliance/ledger-keys \ -H "Authorization: Bearer $EVALGUARD_API_KEY"
TypeScript
// The TypeScript SDK (@evalguard/sdk) exposes TYPED methods — runEval,
// getEval, runSecurityScan, checkFirewall, … — not a generic request().
// For an arbitrary endpoint, call it directly:
const res = await fetch("https://evalguard.ai/api/v1/compliance/ledger-keys", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.EVALGUARD_API_KEY}` },
});
console.log(res.status, await res.json());Python
# The Python SDK (pip install evalguardai) exposes TYPED methods on
# EvalGuardClient — run_eval, get_eval, … — not a generic request().
# For an arbitrary endpoint, call it directly:
import os
import requests
headers = {"Authorization": f"Bearer {os.environ['EVALGUARD_API_KEY']}"}
response = requests.request("POST", "https://evalguard.ai/api/v1/compliance/ledger-keys", headers=headers)
print(response.status_code, response.json())Go
package main
import (
"context"
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequestWithContext(context.Background(), "POST", "https://evalguard.ai/api/v1/compliance/ledger-keys", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("EVALGUARD_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
fmt.Println(resp.Status)
}