---
title: "Fetch the signer's CyclesEvidence JWK Set (signer-key resolution)"
method: GET
path: "/v1/.well-known/cycles-jwks.json"
tags: ["Evidence"]
---

# Fetch the signer's CyclesEvidence JWK Set (signer-key resolution)

`GET /v1/.well-known/cycles-jwks.json`

## Request

- Base URL: `https://api.cycles.local`
- URL: `https://api.cycles.local/v1/.well-known/cycles-jwks.json`
- Auth: none required

Return the issuing server's Ed25519 verification keys as a JWK Set, so a consumer can resolve a `did:cycles` `signer_did` (or confirm a raw-hex one) to a public key and establish signer AUTHORITY — not merely signature validity. This is the publication half of the ADDITIVE signer-key-resolution layer (cycles-evidence v0.2); the resolvable `signer_did` form, the NORMATIVE key-selection + validity-window rules, and the verification dispositions live in `cycles-evidence-v0.2.yaml` (`CyclesEvidenceJwks`).
Located API-base-relative: the spec path is `{server_id}/.well-known/cycles-jwks.json`, and `server_id` already includes `/v1` (e.g. `https://cycles.example.com/v1`), so it resolves to `…/v1/.well-known/cycles-jwks.json` — deliberately NOT origin-rooted, so key authority stays anchored to the exact base the `did:cycles` hash commits to. The literal `.well-known` segment marks this as metadata, not a routed API resource.
OPTIONAL TO PUBLISH: a server that does not participate in signer-key resolution need not serve this (it returns 404, and consumers fall back to raw-hex `signer_did` + `expected_signer` pinning — the `binding_only` posture). A server that DOES publish MUST serve it at this path with this shape and the selection/window semantics in `cycles-evidence-v0.2.yaml`.
AUTH (NORMATIVE): PUBLIC (no ApiKeyAuth). A JWK Set is public keys only — the standard posture for a verification key set — and is itself the trust anchor consumers resolve, so it must be reachable without credentials. The private signing key is NEVER served by this or any endpoint. Servers SHOULD rate-limit and SHOULD serve with a short `Cache-Control: public` max-age (the set changes only on key rotation), NOT `immutable`.

## Response `200`

The signer's JWK Set.

- object: The issuing server's signer key set, returned by `getEvidenceJwks`. An RFC 7517 JWK Set (extra top-level members allowed and ignored). The NORMATIVE resolution algorithm — `did:cycles` binding, the validity-window key selection (pick the key whose `[cycles_nbf_ms, cycles_exp_ms)` covers the envelope's `issued_at_ms`, never "the current key"), the deterministic-selection rules, and the verification dispositions — lives in `cycles-evidence-v0.2.yaml`; this schema mirrors its required shape for the serving endpoint.
  - `keys` object[], required
    - `kty` 'OKP', required
    - `crv` 'Ed25519', required
    - `alg` 'EdDSA': Optional (RFC 7517 §4.4); if present MUST be `EdDSA`. A present-but-different `alg` makes the JWK invalid (excluded).
    - `x` string, required: base64url (unpadded) of the raw 32-byte Ed25519 public key. Equals `base64url(hex-decode(signer_did))` for a raw-hex `signer_did`.
    - `kid` string, required: Stable key id; equals the `#<kid>` fragment of a `did:cycles` `signer_did`.
    - `cycles_nbf_ms` integer, required: Valid-from, epoch ms, INCLUSIVE.
    - `cycles_exp_ms` integer, nullable: Valid-until, epoch ms, EXCLUSIVE. Absent/null ⇒ active (open-ended).
    - `status` 'active' | 'retired': Advisory only. Selection is by validity WINDOW, never by `status`.

## Other responses

- `404`: This server does not publish a JWK Set (signer-key resolution not enabled, or the evidence signing identity is unconfigured).
- `429`: Rate limited. Public endpoints SHOULD be throttled; clients retry after the indicated delay.
- `500`: Error response

---

[API](https://skmtc.dev/runcycles/apis/cycles-budget-authority-api.md) · [All operations](https://skmtc.dev/runcycles/apis/cycles-budget-authority-api/llms.txt) · [OpenAPI document](https://skmtc.dev/runcycles/apis/cycles-budget-authority-api/revisions/7d42267c1ea0?raw)
