# Graph keys

List, renew and revoke device signing keys.


**Auth:** Own-device signed read, operation `list-devices`.
## Request and response

Angle-bracket values describe placeholders, including nested objects and numeric types; these are wire shapes, not captured service data. Replace them before sending.

```http
POST /v1/graph-keys/list HTTP/1.1
Host: trust-staging.rebellion.systems
Content-Type: application/json

{
  "graphNodeId": "<own-node-id>",
  "authorization": {
    "graphKeyId": "<device-id>",
    "nonce": "<fresh-random-nonce>",
    "signedAt": "<current-ISO-timestamp>",
    "signature": "<base64-DER-signature>"
  }
}
```

Response shape:

```json role="response"
{
  "graphKeys": [
    "<graph-key-object>"
  ]
}
```




A graph key is one device's P-256 key. A stable node can have several independent devices; connections belong to the node. Register keys through [binding](/api/bind). The legacy `POST /v1/graph-keys` registration endpoint has been removed.

## List keys

| Route | Authorization | Response |
| --- | --- | --- |
| `POST /v1/graph-keys/list` | Signed read `list-devices` over `{graphNodeId}` | `{graphKeys}` |
| `GET /v1/graph-keys/me` | Verified AuthenSee persona credential | `{graphKeys, nodeHandles?}` |

For the POST, send `{graphNodeId, authorization}`. The signing device must belong to the requested node. Usable quarantined devices may use their own device listing.

Key records include `graphKeyId`, `graphNodeId`, `publicKeyJwk`, `nodeKind`, `createdAt`, `expiresAt` and `authBoundAt`; optional fields include `label`, `metadata`, `purpose`, `revokedAt` and recovery metadata where supplied by the own-key surface. Omitted metadata is absent, not a JSON null. Keep these owner responses private.

## Renew a key

`POST /v1/graph-keys/:graphKeyId/renew`

```json role="request"
{
  "action": {
    "action": "renew-graph-key",
    "graphKeyId": "own-device-id",
    "nonce": "fresh-random-nonce",
    "signedAt": "2026-11-04T12:00:00.000Z"
  },
  "signature": "base64-device-signature"
}
```

Renewal is self-only and returns `{graphKey}`. The device must still be unexpired and within its independent lifetime. Ordinary graph devices renew their seven-day expiry until the thirty-day AuthenSee authentication horizon; after that, refresh authentication through binding. The route does not accept `requestedExpiresAt`.

## Revoke a key

`POST /v1/graph-keys/:graphKeyId/revoke`

Send a signed `revoke-graph-key` action with `graphKeyId`, `nonce` and `signedAt`. To revoke a sibling, add `targetGraphKeyId` and put that target in the URL. An approved usable device of the same node must sign a sibling revocation; a usable quarantined device may revoke itself.

Alternatively, send an empty JSON object with a verified persona credential belonging to the target key's AuthenSee subject. This allows recovery when that device key is unavailable. The response is `{graphKey}`.


**Never**
Revocation is terminal. A revoked key cannot renew or rebind. Generate a fresh device key when recovering.

## Refusals

A signed target that differs from the URL is rejected with 403. Invalid authorization is refused; after proof of possession, lifecycle errors can include `GRAPH_KEY_REVOKED`, `GRAPH_KEY_EXPIRED`, `GRAPH_KEY_PURPOSE_FORBIDDEN` and `GRAPH_KEY_NOT_APPROVED`. Persona credentials do not authorize renewal.


**Does not establish**
Revoking or expiring a device removes its access. It does not remove the persona's connections. Use an authorized source-device [edge revocation](/api/edges) to stop vouching.
