{
  "openapi": "3.1.0",
  "info": {
    "title": "LaWallet NWC API",
    "version": "0.1.0",
    "description": "REST API exposed by `apps/web`. Documents the platform endpoints used by the admin dashboard, lightning address resolution (LUD-16/21), wallet connections, and Nostr-backed authentication (NIP-98 / JWT).",
    "license": {
      "name": "MIT"
    }
  },
  "servers": [
    {
      "url": "http://127.0.0.1:2288",
      "description": "rest-docs"
    }
  ],
  "security": [
    {
      "BearerJWT": []
    },
    {
      "NIP98": []
    }
  ],
  "tags": [
    {
      "name": "Roles & Permissions",
      "description": "LaWallet NWC uses an RBAC model with four hierarchical roles plus a `PUBLIC` tier for unauthenticated calls.\n\n## Hierarchy\n\n`PUBLIC → USER < VIEWER < OPERATOR < ADMIN`\n\nA higher role inherits everything the lower role can do — guards use `hasRole(actual, required)` against this order.\n\n| Role | Who | Privileges |\n|------|-----|------------|\n| **PUBLIC** | Unauthenticated caller | LUD-16 payRequest/callback, `/.well-known/verify`, `/api/setup/status`, `POST /api/jwt`. |\n| **USER** | Any authenticated pubkey with no extra grants | Reads/edits its own data only. No admin panel access. |\n| **VIEWER** | Auditor / observer | Read-only on cards, designs, addresses, ntags, users, settings, activity. |\n| **OPERATOR** | Day-to-day operator | VIEWER + write on cards, designs, addresses, ntags. Cannot touch settings or roles. |\n| **ADMIN** | System root | Every permission. Assigned to the first pubkey that claims the bootstrap via `POST /api/admin/assign`. |\n\n## Permission matrix\n\n| Permission | USER | VIEWER | OPERATOR | ADMIN |\n|------------|:----:|:------:|:--------:|:-----:|\n| `settings:read` | | ✓ | | ✓ |\n| `settings:write` | | | | ✓ |\n| `users:read` | | ✓ | ✓ | ✓ |\n| `users:write` | | | | ✓ |\n| `users:manage_roles` | | | | ✓ |\n| `cards:read` | | ✓ | ✓ | ✓ |\n| `cards:write` | | | ✓ | ✓ |\n| `card_designs:read` | | ✓ | ✓ | ✓ |\n| `card_designs:write` | | | ✓ | ✓ |\n| `addresses:read` | | ✓ | ✓ | ✓ |\n| `addresses:write` | | | ✓ | ✓ |\n| `ntags:read` | | ✓ | ✓ | ✓ |\n| `ntags:write` | | | ✓ | ✓ |\n| `activity:read` | | ✓ | ✓ | ✓ |\n\n## Role resolution\n\nEvery authenticated request (NIP-98 or Bearer JWT) runs through `resolveRole(pubkey)`:\n\n1. Look up the `User` row for that pubkey. If `role !== USER`, return it.\n2. Otherwise, check the `root` setting (bootstrap fallback). If the pubkey matches → `ADMIN`.\n3. Otherwise → `USER`.\n\nThe JWT bakes in the role at issuance time. **Changing a user's role does not invalidate their existing tokens** — the change is only visible after the next `POST /api/jwt`. Sensitive operations (role changes, settings writes) therefore require NIP-98 directly rather than accepting JWT.\n\n## How roles are granted\n\n- **Bootstrap (first admin):** the first pubkey to call `POST /api/admin/assign` with NIP-98 writes the `root` setting and becomes `ADMIN`. See the **Admin** section below.\n- **Promote / demote users:** requires the `users:manage_roles` permission (ADMIN only). Endpoint: `PUT /api/users/{userId}/role`.\n- **Self-demotion is blocked:** an admin cannot lower their own role, and the system prevents the last `ADMIN` from being removed.\n\n## Reading the badges\n\nEach operation in this reference shows a colored badge with the minimum required role (`PUBLIC`, `USER`, `VIEWER`, `OPERATOR`, `ADMIN`). Use them to scan at a glance which endpoints your signer can actually exercise."
    },
    {
      "name": "Auth",
      "description": "NIP-98 → JWT exchange and validation."
    },
    {
      "name": "Passkeys",
      "description": "WebAuthn passkey creation (signup and add-to-account) and credential management. Each passkey derives its Nostr identity client-side via the WebAuthn PRF extension — the server only records credentials; login is a normal NIP-98 exchange with the derived key."
    },
    {
      "name": "Cards",
      "description": "Card lifecycle: create, list, scan, write, OTC."
    },
    {
      "name": "Card Designs",
      "description": "Visual templates assigned to cards."
    },
    {
      "name": "Lightning Addresses",
      "description": "Admin-side lightning address inventory."
    },
    {
      "name": "LUD-16",
      "description": "Public LUD-16 / LUD-21 / LUD-22 lightning address resolution."
    },
    {
      "name": "LUD-16 Proxy",
      "description": "Administrative configuration, settlement queue, safe retries, and listener-driven reconciliation for deferred Lightning Address forwarding."
    },
    {
      "name": "Wallet",
      "description": "End-user wallet addresses and NWC connections."
    },
    {
      "name": "Users",
      "description": "User profiles and role assignment."
    },
    {
      "name": "Invoices",
      "description": "Pay-then-act invoices for registration flows."
    },
    {
      "name": "Settings",
      "description": "Platform-wide settings persisted in the Settings store."
    },
    {
      "name": "Admin",
      "description": "Admin role assignment and bootstrap."
    },
    {
      "name": "Setup",
      "description": "Initial setup status checks."
    },
    {
      "name": "Remote Connections",
      "description": "External device pairing for cards."
    },
    {
      "name": "Activity",
      "description": "Activity log access."
    },
    {
      "name": "Events",
      "description": "Server-Sent Events for real-time updates."
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerJWT": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Session JWT obtained from POST /api/jwt."
      },
      "NIP98": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "NIP-98 signed event, base64-encoded, prefixed with `Nostr ` (e.g. `Authorization: Nostr <base64>`)."
      },
      "EventsToken": {
        "type": "apiKey",
        "in": "query",
        "name": "token",
        "description": "JWT passed as a query string parameter for SSE clients."
      },
      "ListenerHmac": {
        "type": "apiKey",
        "in": "header",
        "name": "x-lawallet-signature",
        "description": "Listener-only HMAC signature: `sha256=<hex HMAC-SHA256(secret, `${x-lawallet-timestamp}.${rawBody}`)>`. The request must also include the current Unix-millisecond `x-lawallet-timestamp` header."
      }
    },
    "schemas": {
      "ErrorEnvelope": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "error": {
            "type": "object",
            "properties": {
              "message": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "details": {}
            },
            "required": [
              "message"
            ]
          }
        },
        "required": [
          "success",
          "error"
        ],
        "description": "Standard error envelope returned by every route via `withErrorHandling`."
      },
      "IdParam": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "id"
        ]
      },
      "UserIdParam": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "userId"
        ]
      },
      "CardCreateRequest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "minLength": 1
          },
          "designId": {
            "type": "string",
            "minLength": 1
          },
          "kind": {
            "type": "string",
            "enum": [
              "SIMPLE",
              "MASTER"
            ]
          }
        },
        "required": [
          "id",
          "designId"
        ],
        "description": "Create-card payload. `id` is the card UID (4- or 7-byte hex, colons optional); it is normalized to uppercase hex and used as the unique NTAG424 key, so re-using a UID returns 409 Conflict. `designId` must reference an existing design; `kind` defaults to `SIMPLE`."
      },
      "CardUpdateRequest": {
        "type": "object",
        "properties": {
          "remoteWalletId": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1
          },
          "kind": {
            "type": "string",
            "enum": [
              "SIMPLE",
              "MASTER"
            ]
          }
        },
        "description": "Admin card update. At least one field is required. `remoteWalletId` rebinds the card to that wallet (or unbinds it when null); `kind` promotes the card to its holder’s MASTER (account-recovery) card, or demotes it back to SIMPLE. A card must be paired and unblocked to be made MASTER, and promoting demotes whichever of the holder’s cards previously held the designation — at most one MASTER per holder."
      },
      "CardListQuery": {
        "type": "object",
        "properties": {
          "paired": {
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          "used": {
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          }
        }
      },
      "ScanCardQuery": {
        "type": "object",
        "properties": {
          "p": {
            "type": "string",
            "minLength": 1
          },
          "c": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "p",
          "c"
        ]
      },
      "PayActionQuery": {
        "type": "object",
        "properties": {
          "pr": {
            "type": "string",
            "minLength": 1,
            "maxLength": 8192
          }
        },
        "required": [
          "pr"
        ]
      },
      "CardScanCallbackQuery": {
        "type": "object",
        "properties": {
          "p": {
            "type": "string",
            "minLength": 1
          },
          "c": {
            "type": "string",
            "minLength": 1
          },
          "pr": {
            "type": "string",
            "minLength": 1,
            "maxLength": 8192
          }
        },
        "required": [
          "p",
          "c",
          "pr"
        ]
      },
      "OtcParam": {
        "type": "object",
        "properties": {
          "otc": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "otc"
        ]
      },
      "ActivationTokenCreateRequest": {
        "type": "object",
        "properties": {
          "qrKind": {
            "type": "string",
            "enum": [
              "ONE_TIME",
              "FOREVER"
            ],
            "default": "ONE_TIME"
          },
          "expiresIn": {
            "type": "string",
            "minLength": 1
          }
        }
      },
      "ActivationTokenClaimRequest": {
        "type": "object",
        "properties": {
          "remoteWalletId": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1
          }
        }
      },
      "CardDesignCreateRequest": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "imageUrl": {
            "type": "string",
            "maxLength": 2048,
            "format": "uri"
          }
        },
        "required": [
          "description",
          "imageUrl"
        ]
      },
      "CardDesignUpdateRequest": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "imageUrl": {
            "type": "string",
            "maxLength": 2048,
            "format": "uri"
          },
          "archived": {
            "type": "boolean"
          }
        },
        "description": "Partial update for a card design. At least one field must be present, otherwise the route returns 400."
      },
      "Lud16UsernameParam": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "username"
        ]
      },
      "Lud16CallbackQuery": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "string",
            "minLength": 1
          },
          "comment": {
            "type": "string",
            "maxLength": 200
          },
          "nostr": {
            "type": "string",
            "maxLength": 65536
          }
        },
        "required": [
          "amount"
        ]
      },
      "LightningAddressUpdateRequest": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string",
            "minLength": 1,
            "maxLength": 16,
            "pattern": "^[a-z0-9]+$"
          }
        },
        "required": [
          "username"
        ]
      },
      "WalletAddressUsernameParam": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string",
            "minLength": 1,
            "maxLength": 16,
            "pattern": "^[a-z0-9]+$"
          }
        },
        "required": [
          "username"
        ]
      },
      "LightningAddressMode": {
        "type": "string",
        "enum": [
          "IDLE",
          "ALIAS",
          "PROXY_ALIAS",
          "CUSTOM_NWC"
        ]
      },
      "WalletAddressCreateRequest": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string",
            "minLength": 1,
            "maxLength": 16,
            "pattern": "^[a-z0-9]+$"
          },
          "mode": {
            "type": "string",
            "enum": [
              "IDLE",
              "ALIAS",
              "PROXY_ALIAS",
              "CUSTOM_NWC"
            ]
          }
        },
        "required": [
          "username"
        ]
      },
      "WalletAddressUpdateRequest": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "IDLE",
              "ALIAS",
              "PROXY_ALIAS",
              "CUSTOM_NWC"
            ]
          },
          "redirect": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 254,
            "pattern": "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$"
          },
          "remoteWalletId": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1
          }
        },
        "required": [
          "mode"
        ]
      },
      "WalletAliasProbeRequest": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string",
            "maxLength": 254,
            "pattern": "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$"
          }
        },
        "required": [
          "address"
        ]
      },
      "ProxyForwardingCommandParams": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string",
            "minLength": 1,
            "maxLength": 16,
            "pattern": "^[a-z0-9]+$"
          },
          "invoiceId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          }
        },
        "required": [
          "username",
          "invoiceId"
        ]
      },
      "ProxyForwardingCommandRequest": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "action": {
                "type": "string",
                "enum": [
                  "retry"
                ]
              }
            },
            "required": [
              "action"
            ]
          },
          {
            "type": "object",
            "properties": {
              "action": {
                "type": "string",
                "enum": [
                  "change_destination"
                ]
              },
              "destination": {
                "type": "string",
                "maxLength": 254,
                "pattern": "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$"
              }
            },
            "required": [
              "action",
              "destination"
            ]
          }
        ]
      },
      "WalletCardUpdateRequest": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "linkDefaultWallet": {
            "type": "boolean"
          },
          "kind": {
            "type": "string",
            "enum": [
              "SIMPLE",
              "MASTER"
            ]
          }
        },
        "description": "Owner-scoped card update. Provide exactly one action: set `enabled` to enable or disable the card, set `linkDefaultWallet` to true to bind it to the caller’s primary remote wallet, or set `kind` to designate this card as the caller’s MASTER (account-recovery) card — which demotes whichever card previously held that designation."
      },
      "UserRoleUpdateRequest": {
        "type": "object",
        "properties": {
          "role": {
            "type": "string",
            "enum": [
              "ADMIN",
              "OPERATOR",
              "VIEWER",
              "USER"
            ]
          }
        },
        "required": [
          "role"
        ]
      },
      "SettingsBody": {
        "type": "object",
        "additionalProperties": {
          "type": "string"
        },
        "description": "Setting key/value pairs. Keys: lowercase letters, digits, hyphens, underscores; max 32 chars. Values: strings."
      },
      "ExternalDeviceKeyParam": {
        "type": "object",
        "properties": {
          "externalDeviceKey": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "externalDeviceKey"
        ]
      },
      "RemoteCardCreateRequest": {
        "type": "object",
        "properties": {
          "designId": {
            "type": "string",
            "minLength": 1
          },
          "cardUID": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "designId",
          "cardUID"
        ]
      },
      "RemoteWalletCreateRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "type": {
            "type": "string",
            "enum": [
              "NWC",
              "LND",
              "CLN",
              "BTCPAY"
            ]
          },
          "config": {},
          "isDefault": {
            "type": "boolean",
            "default": false
          }
        },
        "required": [
          "name",
          "type"
        ]
      },
      "RemoteWalletLncurlCreateRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "isDefault": {
            "type": "boolean",
            "default": false
          }
        },
        "description": "Provision a disposable LNCurl wallet. The server mints the NWC connection string; the new wallet becomes the default and inherits the previous wallet’s bindings."
      },
      "RemoteWalletUpdateRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "isDefault": {
            "type": "boolean"
          },
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "DISABLED",
              "REVOKED",
              "DEAD"
            ]
          }
        },
        "description": "Partial update for a remote wallet. At least one field must be present, otherwise the route returns 400."
      },
      "RemoteWalletListQuery": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "DISABLED",
              "REVOKED",
              "DEAD"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "NWC",
              "LND",
              "CLN",
              "BTCPAY"
            ]
          }
        }
      },
      "RemoteWalletReceiveActionConfigRequest": {
        "type": "object",
        "properties": {
          "feeBps": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1000
          },
          "baseFeeSats": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "enabled": {
            "type": "boolean"
          },
          "destinations": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "address": {
                  "type": "string",
                  "minLength": 3,
                  "maxLength": 320
                },
                "allocationBps": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 10000
                }
              },
              "required": [
                "address",
                "allocationBps"
              ]
            },
            "minItems": 1,
            "maxItems": 20
          }
        },
        "required": [
          "destinations"
        ]
      },
      "RemoteWalletReceiveActionToggleRequest": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          }
        },
        "required": [
          "enabled"
        ]
      },
      "RemoteWalletForwardReceiptListQuery": {
        "type": "object",
        "properties": {
          "cursor": {
            "type": "string",
            "minLength": 1
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 30
          },
          "status": {
            "type": "string",
            "enum": [
              "RECEIVED",
              "FORWARDING",
              "PARTIAL",
              "BLOCKED",
              "COMPLETED",
              "RETAINED"
            ]
          }
        }
      },
      "RemoteWalletForwardActivityListQuery": {
        "type": "object",
        "properties": {
          "cursor": {
            "type": "string",
            "minLength": 1
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 30
          }
        }
      },
      "RemoteWalletForwardReceiptParams": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "minLength": 1
          },
          "receiptId": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "id",
          "receiptId"
        ]
      },
      "RemoteWalletForwardRetryRequest": {
        "type": "object",
        "properties": {
          "legIds": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1
            },
            "maxItems": 20
          }
        }
      },
      "RemoteWalletNotificationCreateRequest": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80
              },
              "channel": {
                "type": "string",
                "enum": [
                  "WEBHOOK"
                ]
              },
              "action": {
                "type": "string",
                "enum": [
                  "RECEIVED",
                  "FORWARDED"
                ]
              },
              "webhookUrl": {
                "type": "string",
                "maxLength": 2048,
                "format": "uri"
              }
            },
            "required": [
              "name",
              "channel",
              "action",
              "webhookUrl"
            ]
          },
          {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80
              },
              "channel": {
                "type": "string",
                "enum": [
                  "NOSTR"
                ]
              },
              "action": {
                "type": "string",
                "enum": [
                  "RECEIVED",
                  "FORWARDED"
                ]
              },
              "kind": {
                "type": "integer",
                "minimum": 0,
                "maximum": 2147483647
              },
              "pTag": {
                "type": "string",
                "minLength": 1,
                "maxLength": 128
              },
              "relays": {
                "type": "array",
                "items": {
                  "type": "string",
                  "maxLength": 512
                },
                "minItems": 1,
                "maxItems": 12
              },
              "content": {
                "type": "string",
                "maxLength": 16384,
                "default": "{{payload}}"
              },
              "nip44": {
                "type": "boolean",
                "default": false
              }
            },
            "required": [
              "name",
              "channel",
              "action",
              "kind",
              "pTag",
              "relays"
            ]
          }
        ]
      },
      "RemoteWalletNotificationListQuery": {
        "type": "object",
        "properties": {
          "cursor": {
            "type": "string",
            "minLength": 1
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 30
          }
        }
      },
      "RemoteWalletNotificationParams": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "minLength": 1
          },
          "notificationId": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "id",
          "notificationId"
        ]
      },
      "RemoteWalletNotificationToggleRequest": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          }
        },
        "required": [
          "enabled"
        ]
      },
      "RemoteWalletNotificationDeliveryParams": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "minLength": 1
          },
          "deliveryId": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "id",
          "deliveryId"
        ]
      },
      "RemoteWalletPaymentParams": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "minLength": 1
          },
          "paymentHash": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$"
          }
        },
        "required": [
          "id",
          "paymentHash"
        ]
      },
      "InvoiceCreateRequest": {
        "type": "object",
        "properties": {
          "purpose": {
            "type": "string",
            "enum": [
              "registration",
              "wallet-address"
            ]
          },
          "metadata": {
            "type": "object",
            "properties": {
              "username": {
                "type": "string",
                "minLength": 1,
                "maxLength": 16,
                "pattern": "^[a-z0-9]+$"
              }
            }
          }
        },
        "required": [
          "purpose"
        ]
      },
      "InvoiceClaimRequest": {
        "type": "object",
        "properties": {
          "preimage": {
            "type": "string",
            "minLength": 1,
            "pattern": "^[a-f0-9]+$"
          }
        },
        "required": [
          "preimage"
        ]
      },
      "JwtRequest": {
        "type": "object",
        "properties": {
          "expiresIn": {
            "type": "string",
            "default": "1h"
          }
        }
      },
      "QrJwtGenerateRequest": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string",
            "minLength": 1
          },
          "permissions": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1
            },
            "minItems": 1,
            "maxItems": 64
          },
          "expiresIn": {
            "type": "string",
            "pattern": "^\\d+\\s*(s|m|h|d|w)?$",
            "default": "8h"
          }
        },
        "required": [
          "userId",
          "permissions"
        ]
      },
      "PasskeyRegistrationOptionsRequest": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          }
        },
        "description": "Optional label for the passkey being created. The body may be omitted entirely — the label is only applied at verify time."
      },
      "PasskeyRegistrationVerifyRequest": {
        "type": "object",
        "properties": {
          "challenge": {
            "type": "string",
            "minLength": 16,
            "maxLength": 128
          },
          "credential": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1
              },
              "rawId": {
                "type": "string",
                "minLength": 1
              },
              "type": {
                "type": "string",
                "enum": [
                  "public-key"
                ]
              },
              "response": {
                "type": "object",
                "properties": {
                  "clientDataJSON": {
                    "type": "string",
                    "minLength": 1
                  },
                  "attestationObject": {
                    "type": "string",
                    "minLength": 1
                  },
                  "transports": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "clientDataJSON",
                  "attestationObject"
                ]
              },
              "clientExtensionResults": {
                "type": "object",
                "additionalProperties": {},
                "default": {}
              },
              "authenticatorAttachment": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "rawId",
              "type",
              "response"
            ]
          },
          "pubkey": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$"
          },
          "proof": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "pubkey": {
                "type": "string",
                "pattern": "^[0-9a-f]{64}$"
              },
              "created_at": {
                "type": "number"
              },
              "kind": {
                "type": "number"
              },
              "tags": {
                "type": "array",
                "items": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              },
              "content": {
                "type": "string"
              },
              "sig": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "pubkey",
              "created_at",
              "kind",
              "tags",
              "content",
              "sig"
            ]
          },
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          }
        },
        "required": [
          "challenge",
          "credential",
          "pubkey",
          "proof"
        ],
        "description": "Attestation result of a WebAuthn registration ceremony under the PRF model: the `challenge` echoed from the options step, the browser `RegistrationResponseJSON` produced by @simplewebauthn/browser `startRegistration()`, the PRF-derived Nostr `pubkey` this credential IS, and `proof` — a NIP-42 (kind 22242) event signed by the derived key with the WebAuthn challenge in a `challenge` tag, proving the client actually controls the pubkey it claims."
      },
      "PasskeyCredentialUpdateRequest": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          }
        },
        "required": [
          "label"
        ],
        "description": "Rename payload. Only the label is mutable — key material, counter, and device metadata are fixed at registration."
      },
      "AccountLinkBeginRequest": {
        "type": "object",
        "properties": {
          "method": {
            "type": "string",
            "enum": [
              "nostr"
            ]
          }
        },
        "required": [
          "method"
        ],
        "description": "Link-proof bootstrap request. `method` is always `nostr` — control of the other key is proven with a NIP-42-style signed event. Passkey-held accounts use the same proof: the client derives the passkey’s key via the WebAuthn PRF extension and signs the event client-side, so there is no server-side passkey arm."
      },
      "AccountLinkVerifyRequest": {
        "type": "object",
        "properties": {
          "method": {
            "type": "string",
            "enum": [
              "nostr"
            ]
          },
          "challenge": {
            "type": "string",
            "minLength": 16
          },
          "event": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "pubkey": {
                "type": "string",
                "pattern": "^[0-9a-f]{64}$"
              },
              "created_at": {
                "type": "number"
              },
              "kind": {
                "type": "number"
              },
              "tags": {
                "type": "array",
                "items": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              },
              "content": {
                "type": "string"
              },
              "sig": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "pubkey",
              "created_at",
              "kind",
              "tags",
              "content",
              "sig"
            ]
          },
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          }
        },
        "required": [
          "method",
          "challenge",
          "event"
        ],
        "description": "Proof of control of another Nostr key: the challenge from link/begin plus a kind-22242 event signed by the key being linked (nonce echoed in a `challenge` tag). For a passkey-held key the client derives the signing key via the WebAuthn PRF extension and produces this same proof client-side."
      },
      "AccountMergePreviewRequest": {
        "type": "object",
        "properties": {
          "mergeTicket": {
            "type": "string",
            "minLength": 16
          }
        },
        "required": [
          "mergeTicket"
        ],
        "description": "The short-lived merge ticket returned by link/verify. Possession of the ticket IS the proof that the caller controls both accounts."
      },
      "AccountMergeRequest": {
        "type": "object",
        "properties": {
          "mergeTicket": {
            "type": "string",
            "minLength": 16
          },
          "mainPubkey": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$"
          },
          "resolutions": {
            "type": "object",
            "properties": {
              "primaryAddressUsername": {
                "type": "string"
              },
              "defaultWalletId": {
                "type": "string"
              }
            }
          }
        },
        "required": [
          "mergeTicket",
          "mainPubkey"
        ],
        "description": "Merge commit payload: the merge ticket from link/verify plus `mainPubkey`, which selects which of the combined identities becomes the surviving account’s primary."
      },
      "UpdateIdentityRequest": {
        "type": "object",
        "properties": {
          "isPrimary": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "label": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1,
            "maxLength": 64
          }
        },
        "description": "Identity update. Provide at least one field, otherwise the route returns 400: `label` renames (null clears it), `isPrimary: true` promotes the identity to primary."
      },
      "SuccessEnvelope": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        },
        "required": [
          "success"
        ],
        "description": "Generic success envelope used by no-content-style endpoints."
      },
      "JwtResponse": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "pubkey": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": [
              "ADMIN",
              "OPERATOR",
              "VIEWER",
              "USER"
            ]
          }
        },
        "required": [
          "token"
        ],
        "description": "JWT issued in exchange for a NIP-98 request, plus context for the client."
      },
      "CountResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "count"
        ],
        "description": "Generic single-count response shape."
      },
      "Lud16PayRequest": {
        "type": "object",
        "properties": {
          "callback": {
            "type": "string",
            "format": "uri"
          },
          "maxSendable": {
            "type": "integer"
          },
          "minSendable": {
            "type": "integer"
          },
          "metadata": {
            "type": "string"
          },
          "tag": {
            "type": "string",
            "enum": [
              "payRequest"
            ]
          },
          "commentAllowed": {
            "type": "integer"
          },
          "allowsNostr": {
            "type": "boolean"
          },
          "nostrPubkey": {
            "type": "string"
          }
        },
        "required": [
          "callback",
          "maxSendable",
          "minSendable",
          "metadata",
          "tag"
        ],
        "description": "LUD-16 pay request as defined by the LUD-06 spec."
      },
      "Lud16Callback": {
        "type": "object",
        "properties": {
          "pr": {
            "type": "string"
          },
          "routes": {
            "type": "array",
            "items": {}
          },
          "verify": {
            "type": "string",
            "format": "uri"
          },
          "successAction": {}
        },
        "required": [
          "pr"
        ],
        "description": "LUD-16 callback response containing the BOLT11 invoice."
      },
      "PasskeyOptionsResponse": {
        "type": "object",
        "properties": {
          "options": {
            "type": "object",
            "additionalProperties": {},
            "description": "WebAuthn PublicKeyCredential options JSON — pass to @simplewebauthn/browser (`startRegistration` / `startAuthentication`) unchanged."
          }
        },
        "required": [
          "options"
        ],
        "description": "Envelope for WebAuthn ceremony options. The `options` object follows the WebAuthn spec and is not modeled field-by-field here. Its challenge is stored server-side, is single-use, and expires after the ceremony timeout."
      },
      "PasskeyCredentialSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "label": {
            "type": [
              "string",
              "null"
            ]
          },
          "deviceType": {
            "type": "string"
          },
          "backedUp": {
            "type": "boolean"
          },
          "aaguid": {
            "type": [
              "string",
              "null"
            ]
          },
          "rpId": {
            "type": "string"
          },
          "pubkey": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string"
          },
          "lastUsedAt": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "label",
          "deviceType",
          "backedUp",
          "aaguid",
          "rpId",
          "pubkey",
          "createdAt",
          "lastUsedAt"
        ],
        "description": "Non-sensitive passkey credential summary — never exposes the stored public key or signature counter. `pubkey` is the Nostr identity this passkey derives via the WebAuthn PRF extension; null for pre-PRF rows."
      },
      "PasskeyCredentialListResponse": {
        "type": "object",
        "properties": {
          "credentials": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "label": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "deviceType": {
                  "type": "string"
                },
                "backedUp": {
                  "type": "boolean"
                },
                "aaguid": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "rpId": {
                  "type": "string"
                },
                "pubkey": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "createdAt": {
                  "type": "string"
                },
                "lastUsedAt": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "id",
                "label",
                "deviceType",
                "backedUp",
                "aaguid",
                "rpId",
                "pubkey",
                "createdAt",
                "lastUsedAt"
              ]
            }
          },
          "hasManagedKey": {
            "type": "boolean"
          },
          "managedKeyExported": {
            "type": "boolean"
          }
        },
        "required": [
          "credentials",
          "hasManagedKey",
          "managedKeyExported"
        ],
        "description": "The caller’s passkeys plus the pre-PRF custody state: `hasManagedKey` is true while the server still custodies this account’s Nostr key, and `managedKeyExported` is true once that key has been exported (always false without a managed key)."
      },
      "NostrIdentitySummary": {
        "type": "object",
        "properties": {
          "pubkey": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$"
          },
          "isPrimary": {
            "type": "boolean"
          },
          "label": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string"
          },
          "custodied": {
            "type": "boolean"
          }
        },
        "required": [
          "pubkey",
          "isPrimary",
          "label",
          "createdAt"
        ],
        "description": "One Nostr identity linked to an account. Exactly one identity per account is primary — it mirrors `User.pubkey` and is the account’s public identity."
      },
      "AccountSummaryResponse": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string"
          },
          "primaryPubkey": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$"
          },
          "identities": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "pubkey": {
                  "type": "string",
                  "pattern": "^[0-9a-f]{64}$"
                },
                "isPrimary": {
                  "type": "boolean"
                },
                "label": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "createdAt": {
                  "type": "string"
                },
                "custodied": {
                  "type": "boolean"
                }
              },
              "required": [
                "pubkey",
                "isPrimary",
                "label",
                "createdAt"
              ]
            }
          },
          "credentials": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "label": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "deviceType": {
                  "type": "string"
                },
                "backedUp": {
                  "type": "boolean"
                },
                "aaguid": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "rpId": {
                  "type": "string"
                },
                "pubkey": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "createdAt": {
                  "type": "string"
                },
                "lastUsedAt": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "id",
                "label",
                "deviceType",
                "backedUp",
                "aaguid",
                "rpId",
                "pubkey",
                "createdAt",
                "lastUsedAt"
              ]
            }
          },
          "hasManagedKey": {
            "type": "boolean"
          },
          "managedKeyExported": {
            "type": "boolean"
          }
        },
        "required": [
          "userId",
          "primaryPubkey",
          "identities",
          "credentials",
          "hasManagedKey",
          "managedKeyExported"
        ],
        "description": "The caller’s own account: every linked Nostr identity (one primary), every passkey credential, and the managed-key custody state."
      },
      "AccountLinkBeginResponse": {
        "type": "object",
        "properties": {
          "challenge": {
            "type": "string"
          },
          "nonce": {
            "type": "string"
          },
          "expiresIn": {
            "type": "number"
          }
        },
        "required": [
          "expiresIn"
        ],
        "description": "Link-proof bootstrap: `challenge` (opaque token to echo back at verify) plus `nonce` (to embed in the signed kind-22242 event). `expiresIn` is seconds."
      },
      "AccountLinkVerifyResponse": {
        "type": "object",
        "properties": {
          "linked": {
            "type": "boolean"
          },
          "identity": {
            "type": "object",
            "properties": {
              "pubkey": {
                "type": "string",
                "pattern": "^[0-9a-f]{64}$"
              },
              "isPrimary": {
                "type": "boolean"
              },
              "label": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "createdAt": {
                "type": "string"
              },
              "custodied": {
                "type": "boolean"
              }
            },
            "required": [
              "pubkey",
              "isPrimary",
              "label",
              "createdAt"
            ]
          },
          "mergeTicket": {
            "type": "string"
          },
          "otherAccount": {
            "type": "object",
            "properties": {
              "userId": {
                "type": "string"
              },
              "primaryPubkey": {
                "type": "string",
                "pattern": "^[0-9a-f]{64}$"
              },
              "identities": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "pubkey": {
                      "type": "string",
                      "pattern": "^[0-9a-f]{64}$"
                    },
                    "isPrimary": {
                      "type": "boolean"
                    },
                    "label": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "pubkey",
                    "isPrimary",
                    "label"
                  ]
                }
              },
              "passkeys": {
                "type": "number"
              },
              "lightningAddresses": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "primaryAddress": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "remoteWallets": {
                "type": "number"
              },
              "wallets": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "isDefault": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "isDefault"
                  ]
                }
              },
              "cards": {
                "type": "number"
              },
              "cardDesigns": {
                "type": "number"
              },
              "invoices": {
                "type": "number"
              },
              "relays": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "profile": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "displayName": {
                    "type": "string"
                  },
                  "picture": {
                    "type": "string"
                  }
                }
              },
              "hasAlbySubAccount": {
                "type": "boolean"
              },
              "hasManagedKey": {
                "type": "boolean"
              },
              "managedKeyExported": {
                "type": "boolean"
              }
            },
            "required": [
              "userId",
              "primaryPubkey",
              "identities",
              "passkeys",
              "lightningAddresses",
              "primaryAddress",
              "remoteWallets",
              "wallets",
              "cards",
              "cardDesigns",
              "invoices",
              "relays",
              "profile",
              "hasAlbySubAccount",
              "hasManagedKey",
              "managedKeyExported"
            ]
          }
        },
        "required": [
          "linked"
        ],
        "description": "Outcome of a link proof. `linked: true` + `identity` when the pubkey was unowned and is now attached as a secondary identity. `linked: false` + `mergeTicket` + `otherAccount` when the key belongs to another account — nothing was written; the ticket gates the merge preview/commit flow."
      },
      "AccountMergePreviewResponse": {
        "type": "object",
        "properties": {
          "survivor": {
            "type": "object",
            "properties": {
              "userId": {
                "type": "string"
              },
              "primaryPubkey": {
                "type": "string",
                "pattern": "^[0-9a-f]{64}$"
              },
              "identities": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "pubkey": {
                      "type": "string",
                      "pattern": "^[0-9a-f]{64}$"
                    },
                    "isPrimary": {
                      "type": "boolean"
                    },
                    "label": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "pubkey",
                    "isPrimary",
                    "label"
                  ]
                }
              },
              "passkeys": {
                "type": "number"
              },
              "lightningAddresses": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "primaryAddress": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "remoteWallets": {
                "type": "number"
              },
              "wallets": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "isDefault": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "isDefault"
                  ]
                }
              },
              "cards": {
                "type": "number"
              },
              "cardDesigns": {
                "type": "number"
              },
              "invoices": {
                "type": "number"
              },
              "relays": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "profile": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "displayName": {
                    "type": "string"
                  },
                  "picture": {
                    "type": "string"
                  }
                }
              },
              "hasAlbySubAccount": {
                "type": "boolean"
              },
              "hasManagedKey": {
                "type": "boolean"
              },
              "managedKeyExported": {
                "type": "boolean"
              }
            },
            "required": [
              "userId",
              "primaryPubkey",
              "identities",
              "passkeys",
              "lightningAddresses",
              "primaryAddress",
              "remoteWallets",
              "wallets",
              "cards",
              "cardDesigns",
              "invoices",
              "relays",
              "profile",
              "hasAlbySubAccount",
              "hasManagedKey",
              "managedKeyExported"
            ]
          },
          "absorbed": {
            "type": "object",
            "properties": {
              "userId": {
                "type": "string"
              },
              "primaryPubkey": {
                "type": "string",
                "pattern": "^[0-9a-f]{64}$"
              },
              "identities": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "pubkey": {
                      "type": "string",
                      "pattern": "^[0-9a-f]{64}$"
                    },
                    "isPrimary": {
                      "type": "boolean"
                    },
                    "label": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "pubkey",
                    "isPrimary",
                    "label"
                  ]
                }
              },
              "passkeys": {
                "type": "number"
              },
              "lightningAddresses": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "primaryAddress": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "remoteWallets": {
                "type": "number"
              },
              "wallets": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "isDefault": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "isDefault"
                  ]
                }
              },
              "cards": {
                "type": "number"
              },
              "cardDesigns": {
                "type": "number"
              },
              "invoices": {
                "type": "number"
              },
              "relays": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "profile": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "displayName": {
                    "type": "string"
                  },
                  "picture": {
                    "type": "string"
                  }
                }
              },
              "hasAlbySubAccount": {
                "type": "boolean"
              },
              "hasManagedKey": {
                "type": "boolean"
              },
              "managedKeyExported": {
                "type": "boolean"
              }
            },
            "required": [
              "userId",
              "primaryPubkey",
              "identities",
              "passkeys",
              "lightningAddresses",
              "primaryAddress",
              "remoteWallets",
              "wallets",
              "cards",
              "cardDesigns",
              "invoices",
              "relays",
              "profile",
              "hasAlbySubAccount",
              "hasManagedKey",
              "managedKeyExported"
            ]
          },
          "collisions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "kind": {
                  "type": "string",
                  "enum": [
                    "managed-key-unexported",
                    "managed-key-dropped",
                    "alby-subaccount-dropped",
                    "wallet-name-renamed",
                    "primary-address-kept",
                    "default-wallet-kept"
                  ]
                },
                "detail": {
                  "type": "string"
                }
              },
              "required": [
                "kind",
                "detail"
              ]
            }
          },
          "blocked": {
            "type": "boolean"
          }
        },
        "required": [
          "survivor",
          "absorbed",
          "collisions",
          "blocked"
        ],
        "description": "Read-only merge dry run: both accounts’ resource summaries, the collisions the merge would reconcile, and `blocked` — true while the absorbed account custodies a never-exported key."
      },
      "AccountMergeResponse": {
        "type": "object",
        "properties": {
          "survivorId": {
            "type": "string"
          },
          "mainPubkey": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$"
          },
          "movedIdentities": {
            "type": "number"
          },
          "movedPasskeys": {
            "type": "number"
          },
          "movedAddresses": {
            "type": "number"
          },
          "movedWallets": {
            "type": "number"
          },
          "mergedRelays": {
            "type": "number"
          }
        },
        "required": [
          "survivorId",
          "mainPubkey",
          "movedIdentities",
          "movedPasskeys",
          "movedAddresses",
          "movedWallets",
          "mergedRelays"
        ],
        "description": "Merge result: the surviving account id, the chosen primary pubkey, and counts of the resources re-parented from the absorbed account."
      },
      "Lud21Verify": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "OK",
              "ERROR"
            ]
          },
          "settled": {
            "type": "boolean"
          },
          "preimage": {
            "type": [
              "string",
              "null"
            ]
          },
          "pr": {
            "type": "string"
          },
          "reason": {
            "type": "string"
          }
        },
        "required": [
          "status"
        ],
        "description": "LUD-21 payment verification response."
      }
    },
    "parameters": {}
  },
  "paths": {
    "/api/jwt": {
      "post": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Auth"
        ],
        "summary": "Get JWT via NIP-98 auth",
        "operationId": "auth.exchange",
        "security": [
          {
            "NIP98": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JwtRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JWT issued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JwtResponse"
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Auth"
        ],
        "summary": "Validate JWT",
        "operationId": "auth.validate",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Token is valid.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "valid": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "pubkey": {
                      "type": "string"
                    },
                    "role": {
                      "type": "string",
                      "enum": [
                        "ADMIN",
                        "OPERATOR",
                        "VIEWER",
                        "USER"
                      ]
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "valid"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/auth/qr-jwt/generate": {
      "post": {
        "x-required-role": "ADMIN",
        "tags": [
          "Auth"
        ],
        "summary": "Mint a scoped device token (QR login)",
        "description": "Admin-only. Mints a stateless JWT scoped to a target user + permission subset, shown as a QR for the card apps (card-installer, card-manager) to scan. The token carries an `apiUrl` claim binding it to this instance: the auth layer rejects it on any other platform URL, and the scanning app reads the API base from the claim. No session record, no revocation — validation is signature + exp + apiUrl only. Lifetimes have a 1-minute floor but no maximum, so prefer short expirations. Granted permissions must be a subset of the caller's RBAC.",
        "operationId": "auth.qrJwt.generate",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QrJwtGenerateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Device token minted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jwt": {
                      "type": "string"
                    },
                    "expiresIn": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "number"
                        }
                      ]
                    },
                    "scopes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "apiUrl": {
                      "type": "string",
                      "description": "Platform base URL baked into the token; it is only valid against this instance.",
                      "example": "https://app.example.com"
                    },
                    "user": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "pubkey": {
                          "type": "string"
                        },
                        "role": {
                          "type": "string",
                          "enum": [
                            "ADMIN",
                            "OPERATOR",
                            "VIEWER",
                            "USER"
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "pubkey",
                        "role"
                      ]
                    }
                  },
                  "required": [
                    "jwt",
                    "expiresIn",
                    "scopes",
                    "apiUrl",
                    "user"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded; check the Retry-After header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/jwt/protected": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Auth"
        ],
        "summary": "Demo route guarded by the unified auth chain.",
        "operationId": "auth.protected.get",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Caller is authenticated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "pubkey": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "ok"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Auth"
        ],
        "summary": "Demo POST guarded by the unified auth chain.",
        "operationId": "auth.protected.post",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Caller is authenticated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    }
                  },
                  "required": [
                    "ok"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/auth/passkey/registration/options": {
      "post": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Passkeys"
        ],
        "summary": "Start creating a passkey (signup or add-to-account).",
        "description": "Mints WebAuthn registration options. One ceremony serves BOTH new-account signup and adding a passkey to an existing account — `verify` branches on the caller’s auth there, so this leg is unauthenticated. The credential’s Nostr identity is derived CLIENT-SIDE via the WebAuthn PRF extension; the server only records credentials and never holds a key, so there is no key-vault gating. Nothing is persisted besides the single-use challenge; the WebAuthn user handle is random opaque bytes (the account is keyed by the PRF-derived pubkey, not the handle). The body is optional; a malformed body is tolerated because the label is only applied at verify time.",
        "operationId": "passkey.registration.options",
        "security": [],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PasskeyRegistrationOptionsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "WebAuthn registration options. The challenge is stored server-side, single-use.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PasskeyOptionsResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded; check the Retry-After header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "Passkey login is not configured — JWT auth is disabled on this instance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/auth/passkey/registration/verify": {
      "post": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Passkeys"
        ],
        "summary": "Complete creating a passkey (signup or add-to-account).",
        "description": "Verifies the authenticator’s attestation against the single-use challenge minted by `registration/options`, plus the PRF proof: the client derived this credential’s Nostr key via the WebAuthn PRF extension and proves it with a NIP-42 (kind 22242) event signed by that key, carrying the WebAuthn challenge in a `challenge` tag. The server then only RECORDS the credential — it never generates or stores a key. Branches on the caller: UNAUTHENTICATED (signup) — an unowned derived pubkey creates the account; an already-owned pubkey (the same passkey re-registered) just attaches the new credential to its account. AUTHENTICATED (Bearer JWT or NIP-98; add a passkey) — the derived pubkey is linked to the caller’s account as a secondary identity. No token is minted here: the client follows up with a normal NIP-98 login using the derived key.",
        "operationId": "passkey.registration.verify",
        "security": [
          {},
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PasskeyRegistrationVerifyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Passkey recorded. Log in next with a normal NIP-98 exchange using the derived key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "pubkey": {
                      "type": "string",
                      "description": "The PRF-derived Nostr pubkey this credential IS — the identity it signs for."
                    },
                    "credential": {
                      "$ref": "#/components/schemas/PasskeyCredentialSummary"
                    }
                  },
                  "required": [
                    "pubkey",
                    "credential"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Passkey verification failed — bad attestation, wrong origin/rpID, burned or expired challenge, or a pubkey proof event that does not check out. Every failure path returns this same generic message — no oracle. Also returned when an Authorization header is present but invalid: a bad credential never silently downgrades to signup.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "The credential id is already registered, or (authenticated add) the derived pubkey belongs to a DIFFERENT account — the UI offers the account-merge flow for that case.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded; check the Retry-After header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/auth/passkey/credentials": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Passkeys"
        ],
        "summary": "List the caller’s passkeys.",
        "description": "Returns credential summaries only — never the stored public key or signature counter. `hasManagedKey` and `managedKeyExported` describe the pre-PRF custody state: whether the server still custodies a Nostr key for this account, and whether that key has ever been exported (`managedKeyExported` is always false when there is no managed key).",
        "operationId": "passkey.credentials.list",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "The caller’s passkeys.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PasskeyCredentialListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "No `User` row exists for the authenticated pubkey.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/auth/passkey/credentials/{id}": {
      "patch": {
        "x-required-role": "USER",
        "tags": [
          "Passkeys"
        ],
        "summary": "Rename a passkey.",
        "description": "Ownership-scoped: a credential that does not exist or belongs to another user returns 404 (never 403) so credential ids cannot be enumerated. Only the label is mutable.",
        "operationId": "passkey.credentials.update",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PasskeyCredentialUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Passkey renamed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "credential": {
                      "$ref": "#/components/schemas/PasskeyCredentialSummary"
                    }
                  },
                  "required": [
                    "credential"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Passkey not found (or not owned by the caller).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "delete": {
        "x-required-role": "USER",
        "tags": [
          "Passkeys"
        ],
        "summary": "Delete a passkey.",
        "description": "Removes the LOGIN-METHOD record only. Under the PRF model the passkey’s derived Nostr identity (and its key) live entirely client-side, so nothing is orphaned and no last-credential/export guard applies. The derived identity stays linked to the account until unlinked explicitly via `DELETE /api/account/identities/{pubkey}`. Ownership-scoped (404, never 403).",
        "operationId": "passkey.credentials.delete",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Passkey deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "id": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "message",
                    "id"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Passkey not found (or not owned by the caller).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded; check the Retry-After header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/account": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Account"
        ],
        "summary": "Get the caller’s account summary.",
        "description": "The caller’s own account: every linked Nostr identity (exactly one is primary and mirrors the account’s public pubkey), every passkey credential, and the managed-key custody state. Powers the Account Settings page.",
        "operationId": "account.get",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "The caller’s account summary.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountSummaryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "No account exists for the authenticated pubkey.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/account/identities/link/begin": {
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Account"
        ],
        "summary": "Start proving control of another Nostr key.",
        "description": "First leg of linking another Nostr key (or merging another account) into the caller’s account. `method` is always `nostr`: the response carries a challenge token plus a nonce; the other key signs a NIP-42-style kind-22242 event carrying the nonce in a `challenge` tag, and the pair goes to `link/verify`. Passkey-held accounts are proven the same way — the client derives the passkey’s key via the WebAuthn PRF extension and signs the event client-side, so there is no server-side passkey arm.",
        "operationId": "account.link.begin",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AccountLinkBeginRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Proof bootstrap. `challenge` + `nonce` for the nostr method; both absent for passkey.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountLinkBeginResponse"
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "No account exists for the authenticated pubkey.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded; check the Retry-After header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/account/identities/link/verify": {
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Account"
        ],
        "summary": "Verify the proof and link or stage a merge.",
        "description": "Second leg of the link/merge flow. The caller proves control of another key — a kind-22242 event signed by it, answering the challenge from `link/begin` — and the outcome depends on where that key lives. Unowned pubkey: attached to the caller’s account as a secondary identity (`linked: true` + `identity`). Owned by another account: nothing is written; a short-lived merge ticket bound to the (caller, other account) pair is returned together with the other account’s resource summary for the side-by-side preview (`linked: false` + `mergeTicket` + `otherAccount`). Already on the caller’s account: 409.",
        "operationId": "account.link.verify",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AccountLinkVerifyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Proof accepted — identity linked, or a merge ticket staged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountLinkVerifyResponse"
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing/invalid authentication, or the proof failed: expired or burned challenge, an event that does not answer it, or a bad signature.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "No account exists for the authenticated pubkey.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "This key is already linked to the caller’s account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded; check the Retry-After header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/account/merge/preview": {
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Account"
        ],
        "summary": "Preview an account merge (dry run).",
        "description": "Read-only dry run of a merge: both accounts’ resource summaries, the collisions the merge would reconcile, and whether it is blocked because the absorbed account custodies a never-exported key. Requires a valid merge ticket from `link/verify` — possession of the ticket IS the proof that the caller controls both accounts. Nothing is written.",
        "operationId": "account.merge.preview",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AccountMergePreviewRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Merge dry-run summary.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountMergePreviewResponse"
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing/invalid authentication, or the merge ticket is invalid, expired, or bound to a different account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "No account exists for the authenticated pubkey, or one side of the merge no longer exists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded; check the Retry-After header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/account/merge": {
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Account"
        ],
        "summary": "Commit an account merge.",
        "description": "Destructive commit. The merge ticket (from `link/verify`) proves the caller controls both accounts; `mainPubkey` selects which of the combined identities becomes primary. The absorbed account’s resources are re-parented onto the caller’s account inside one transaction and its User row is deleted. Refused with 409 while the absorbed account custodies a never-exported key — export it first. The caller’s session stays valid (its JWT pubkey remains one of the merged identities), but clients should refresh their token so the session presents the new primary.",
        "operationId": "account.merge",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AccountMergeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Merge committed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountMergeResponse"
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing/invalid authentication, or the merge ticket is invalid, expired, or bound to a different account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "No account exists for the authenticated pubkey, or one side of the merge no longer exists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "The absorbed account custodies a never-exported Nostr key — export it before merging.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded; check the Retry-After header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/account/identities/{pubkey}": {
      "patch": {
        "x-required-role": "USER",
        "tags": [
          "Account"
        ],
        "summary": "Rename an identity or promote it to primary.",
        "description": "Ownership-scoped: an identity that does not exist or belongs to another account returns 404 (never 403) so pubkeys cannot be enumerated. `label` renames (null clears it); `isPrimary: true` promotes the identity, mirroring the new primary onto the account’s public pubkey — the caller should refresh its session token afterwards so the JWT presents the new primary.",
        "operationId": "account.identities.update",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$",
              "description": "The linked identity’s Nostr pubkey (64-char lowercase hex)."
            },
            "required": true,
            "name": "pubkey",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateIdentityRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated identity.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NostrIdentitySummary"
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Identity not found (or not owned by the caller).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded; check the Retry-After header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "delete": {
        "x-required-role": "USER",
        "tags": [
          "Account"
        ],
        "summary": "Unlink a secondary identity.",
        "description": "Detaches a SECONDARY identity from the caller’s account; the pubkey becomes a bare key again and can be re-linked later. The primary identity cannot be unlinked (409 — promote another identity first) and neither can the last remaining identity (409). Ownership-scoped (404, never 403).",
        "operationId": "account.identities.delete",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$",
              "description": "The linked identity’s Nostr pubkey (64-char lowercase hex)."
            },
            "required": true,
            "name": "pubkey",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Identity unlinked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "pubkey": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "message",
                    "pubkey"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Identity not found (or not owned by the caller).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "The identity is the account’s primary (promote another identity first) or its last remaining identity.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded; check the Retry-After header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/cards": {
      "get": {
        "x-required-role": "VIEWER",
        "tags": [
          "Cards"
        ],
        "summary": "List cards.",
        "operationId": "cards.list",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            },
            "required": false,
            "name": "paired",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            },
            "required": false,
            "name": "used",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of cards.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "designId": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "paired": {
                            "type": "boolean"
                          },
                          "used": {
                            "type": "boolean"
                          },
                          "blocked": {
                            "type": "boolean",
                            "description": "True once the card’s reset (wipe) keys were exported — decommissioned and pending delete; can no longer be re-used."
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "SIMPLE",
                              "MASTER"
                            ],
                            "description": "MASTER designates the holder’s account-recovery card. At most one per holder."
                          },
                          "masterCardId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Id of the holder’s current MASTER card — this card’s own id when it holds the designation, a sibling’s when another does, null when the holder has none or the card is unpaired."
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "id",
                          "paired",
                          "used",
                          "createdAt"
                        ],
                        "description": "Card resource as returned by /api/cards endpoints."
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "x-required-role": "OPERATOR",
        "tags": [
          "Cards"
        ],
        "summary": "Create a card.",
        "description": "Provisions a card and its NTAG424 key material. The request `id` is the card UID (4- or 7-byte hex, colons optional); it is normalized to uppercase hex and stored as the NTAG424 primary key, so a UID can back at most one card. Submitting a UID that already exists returns **409 Conflict** (`error.code` = `CONFLICT`) rather than a 500 — the same is true for a `MASTER`/`SIMPLE` card on a re-used UID.",
        "operationId": "cards.create",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CardCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Card created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "designId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "paired": {
                      "type": "boolean"
                    },
                    "used": {
                      "type": "boolean"
                    },
                    "blocked": {
                      "type": "boolean",
                      "description": "True once the card’s reset (wipe) keys were exported — decommissioned and pending delete; can no longer be re-used."
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "SIMPLE",
                        "MASTER"
                      ],
                      "description": "MASTER designates the holder’s account-recovery card. At most one per holder."
                    },
                    "masterCardId": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Id of the holder’s current MASTER card — this card’s own id when it holds the designation, a sibling’s when another does, null when the holder has none or the card is unpaired."
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "paired",
                    "used",
                    "createdAt"
                  ],
                  "description": "Card resource as returned by /api/cards endpoints."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "A card with the supplied UID already exists. The error envelope carries `error.code` = `CONFLICT` and `error.message` = `A card with UID <uid> already exists`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/cards/counts": {
      "get": {
        "x-required-role": "VIEWER",
        "tags": [
          "Cards"
        ],
        "summary": "Count cards by status.",
        "operationId": "cards.counts",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Card counts.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "total": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "paired": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "used": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "blocked": {
                      "type": "integer",
                      "minimum": 0
                    }
                  },
                  "required": [
                    "total",
                    "paired",
                    "used",
                    "blocked"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/cards/{id}": {
      "get": {
        "x-required-role": "VIEWER",
        "tags": [
          "Cards"
        ],
        "summary": "Get a card by ID.",
        "operationId": "cards.get",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Card detail.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "designId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "paired": {
                      "type": "boolean"
                    },
                    "used": {
                      "type": "boolean"
                    },
                    "blocked": {
                      "type": "boolean",
                      "description": "True once the card’s reset (wipe) keys were exported — decommissioned and pending delete; can no longer be re-used."
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "SIMPLE",
                        "MASTER"
                      ],
                      "description": "MASTER designates the holder’s account-recovery card. At most one per holder."
                    },
                    "masterCardId": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Id of the holder’s current MASTER card — this card’s own id when it holds the designation, a sibling’s when another does, null when the holder has none or the card is unpaired."
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "paired",
                    "used",
                    "createdAt"
                  ],
                  "description": "Card resource as returned by /api/cards endpoints."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "patch": {
        "x-required-role": "OPERATOR",
        "tags": [
          "Cards"
        ],
        "summary": "Update a card.",
        "description": "Rebinds the card’s spending wallet and/or changes its kind. Setting `kind` to MASTER designates the card as its holder’s account-recovery card and demotes whichever of their cards previously held that designation; the card must be paired (400 otherwise) and not blocked (409 otherwise). Cardholders can set their own via PATCH /api/wallet/cards/{id}.",
        "operationId": "cards.update",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CardUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated card.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "designId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "paired": {
                      "type": "boolean"
                    },
                    "used": {
                      "type": "boolean"
                    },
                    "blocked": {
                      "type": "boolean",
                      "description": "True once the card’s reset (wipe) keys were exported — decommissioned and pending delete; can no longer be re-used."
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "SIMPLE",
                        "MASTER"
                      ],
                      "description": "MASTER designates the holder’s account-recovery card. At most one per holder."
                    },
                    "masterCardId": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Id of the holder’s current MASTER card — this card’s own id when it holds the designation, a sibling’s when another does, null when the holder has none or the card is unpaired."
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "paired",
                    "used",
                    "createdAt"
                  ],
                  "description": "Card resource as returned by /api/cards endpoints."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "delete": {
        "x-required-role": "OPERATOR",
        "tags": [
          "Cards"
        ],
        "summary": "Delete a card.",
        "operationId": "cards.delete",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Card deleted."
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/cards/{id}/write": {
      "get": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Cards"
        ],
        "summary": "Get NTAG424 write payload for an admin programming device.",
        "description": "Returns the card keys so a programming device can write them. **Requires a single-use `token`** minted by `POST /api/cards/{id}/write-token`: the token is valid only while the card is still fresh (never tapped) and is consumed by this request, so the URL cannot be replayed to re-extract the keys. Requests without a valid/unexpired token, or for a card that has already been tapped, return **403**. **Side effect:** exporting the keys unpairs the card from any user (holder, lightning address, and bound wallet are cleared).",
        "operationId": "cards.write",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Single-use programming token from /write-token."
            },
            "required": true,
            "name": "token",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "NTAG424 secrets and write payload for NFC programming.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "keys": {
                      "type": "object",
                      "properties": {
                        "k0": {
                          "type": "string"
                        },
                        "k1": {
                          "type": "string"
                        },
                        "k2": {
                          "type": "string"
                        },
                        "k3": {
                          "type": "string"
                        },
                        "k4": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "k0",
                        "k1",
                        "k2",
                        "k3",
                        "k4"
                      ]
                    },
                    "endpoint": {
                      "type": "string",
                      "format": "uri"
                    }
                  },
                  "required": [
                    "id",
                    "keys",
                    "endpoint"
                  ],
                  "description": "Card programming payload returned to the writer device."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Missing, invalid, expired, or already-consumed programming token, or the card has already been tapped.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "options": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Cards"
        ],
        "summary": "CORS preflight for /api/cards/{id}/write.",
        "operationId": "cards.write.options",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Preflight OK."
          }
        }
      }
    },
    "/api/cards/{id}/write-token": {
      "post": {
        "x-required-role": "OPERATOR",
        "tags": [
          "Cards"
        ],
        "summary": "Mint a single-use BoltCard programming URL.",
        "description": "Mints a fresh, replay-protected `GET /api/cards/{id}/write?token=…` URL for the admin BoltCard QR. Allowed only while the card is still fresh (never tapped); a card already in use returns **409** and cannot be re-programmed. Each call replaces any outstanding token, so re-opening the modal invalidates the previous QR. Gated to `CARDS_WRITE`.",
        "operationId": "cards.writeToken",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Tokenized programming URL.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "token",
                    "url",
                    "expiresAt"
                  ],
                  "description": "Single-use /write URL + its expiry. `token` is also returned raw so a client on a different host than the public domain can build its own `<base>/api/cards/{id}/write?token=…` URL."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "The card has already been tapped and can no longer be programmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/cards/{id}/wipe": {
      "get": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Cards"
        ],
        "summary": "Get NTAG424 reset payload for an admin programming device.",
        "description": "Returns the card keys so a programming device can reset the NTAG424 to factory defaults. **Side effect:** exporting the keys unpairs the card from any user (holder, lightning address, and bound wallet are cleared). Idempotent.",
        "operationId": "cards.wipe",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "NTAG424 reset payload for NFC programming.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "action": {
                      "type": "string",
                      "enum": [
                        "wipe"
                      ]
                    },
                    "k0": {
                      "type": "string"
                    },
                    "k1": {
                      "type": "string"
                    },
                    "k2": {
                      "type": "string"
                    },
                    "k3": {
                      "type": "string"
                    },
                    "k4": {
                      "type": "string"
                    },
                    "uid": {
                      "type": "string"
                    },
                    "version": {
                      "type": "number",
                      "enum": [
                        1
                      ]
                    }
                  },
                  "required": [
                    "action",
                    "k0",
                    "k1",
                    "k2",
                    "k3",
                    "k4",
                    "uid",
                    "version"
                  ],
                  "description": "BoltCard wipe payload: the current keys + UID a programming device uses to reset the card to factory defaults."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "options": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Cards"
        ],
        "summary": "CORS preflight for /api/cards/{id}/wipe.",
        "operationId": "cards.wipe.options",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Preflight OK."
          }
        }
      }
    },
    "/api/cards/{id}/emulate-tap": {
      "post": {
        "x-required-role": "OPERATOR",
        "tags": [
          "Cards"
        ],
        "summary": "Sign a simulated NTAG424 tap (admin card emulator).",
        "description": "Server-side SUN signing for the admin card emulator. Returns the public `p`/`c` params for the card’s next counter so a tap can be replayed through the scan flow — the NTAG424 keys never leave the server. Does not export keys, so it does not unpair the card.",
        "operationId": "cards.emulateTap",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Signed tap params.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "p": {
                      "type": "string"
                    },
                    "c": {
                      "type": "string"
                    },
                    "ctr": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "p",
                    "c",
                    "ctr"
                  ],
                  "description": "Public SUN params (no keys)."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/cards/{id}/scan": {
      "get": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Cards"
        ],
        "summary": "Resolve a scanned card and return the LNURL-withdraw flow entry point.",
        "description": "The first LNURL request on tap. Send the request header `x-request-action: info` to get the card’s public status JSON (design, image, owner, paired/used) instead of the LNURL withdraw request — so a client can show the card identity without running the withdraw flow. Non-sensitive only (never keys/OTC/SUN params).",
        "operationId": "cards.scan",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "p",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "c",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "LNURL withdraw request, or the card status JSON when `x-request-action: info`.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "callback": {
                          "type": "string",
                          "format": "uri"
                        },
                        "k1": {
                          "type": "string"
                        },
                        "maxWithdrawable": {
                          "type": "integer"
                        },
                        "minWithdrawable": {
                          "type": "integer"
                        },
                        "defaultDescription": {
                          "type": "string"
                        },
                        "tag": {
                          "type": "string",
                          "enum": [
                            "withdrawRequest"
                          ]
                        }
                      },
                      "required": [
                        "callback",
                        "k1",
                        "maxWithdrawable",
                        "minWithdrawable",
                        "defaultDescription",
                        "tag"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "title": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "kind": {
                          "type": "string",
                          "enum": [
                            "SIMPLE",
                            "MASTER"
                          ]
                        },
                        "paired": {
                          "type": "boolean"
                        },
                        "used": {
                          "type": "boolean"
                        },
                        "blocked": {
                          "type": "boolean"
                        },
                        "design": {
                          "type": [
                            "object",
                            "null"
                          ],
                          "properties": {
                            "description": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "imageUrl": {
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "description",
                            "imageUrl"
                          ]
                        },
                        "user": {
                          "type": [
                            "object",
                            "null"
                          ],
                          "properties": {
                            "pubkey": {
                              "type": "string"
                            },
                            "username": {
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "pubkey",
                            "username"
                          ]
                        },
                        "lastUsedAt": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "title",
                        "kind",
                        "paired",
                        "used",
                        "blocked",
                        "design",
                        "user",
                        "lastUsedAt"
                      ],
                      "description": "Non-sensitive card status (no keys/OTC/SUN params)."
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "options": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Cards"
        ],
        "summary": "CORS preflight for /api/cards/{id}/scan.",
        "operationId": "cards.scan.options",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Preflight OK."
          }
        }
      }
    },
    "/api/cards/{id}/scan/cb": {
      "get": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Cards"
        ],
        "summary": "LNURL-withdraw callback for a scanned card.",
        "operationId": "cards.scan.callback",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "p",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "c",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 8192
            },
            "required": true,
            "name": "pr",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "LUD-03 callback response.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "OK"
                          ]
                        }
                      },
                      "required": [
                        "status"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "ERROR"
                          ]
                        },
                        "reason": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "status",
                        "reason"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/cards/otc/{otc}": {
      "get": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Cards"
        ],
        "summary": "Resolve an OTC (one-time code) to its provisional card.",
        "operationId": "cards.otc.get",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "otc",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OTC payload.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/cards/otc/{otc}/activate": {
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Cards"
        ],
        "summary": "Activate a card by OTC.",
        "operationId": "cards.otc.activate",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "otc",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Card activated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    }
                  },
                  "required": [
                    "success"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/cards/{id}/activation-tokens": {
      "post": {
        "x-required-role": "OPERATOR",
        "tags": [
          "Card Activation"
        ],
        "summary": "Mint an activation QR for a card.",
        "description": "Issues a ONE_TIME activation token (FOREVER is reserved for the future MASTER account-share feature and is rejected). Replaces any prior active token of the same kind.",
        "operationId": "cards.activationTokens.create",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActivationTokenCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Activation token minted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tokenId": {
                      "type": "string"
                    },
                    "qrPayload": {
                      "type": "string",
                      "format": "uri"
                    },
                    "qrKind": {
                      "type": "string",
                      "enum": [
                        "ONE_TIME",
                        "FOREVER"
                      ]
                    },
                    "expiresAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "tokenId",
                    "qrPayload",
                    "qrKind",
                    "expiresAt"
                  ],
                  "description": "A freshly minted activation token + its scannable QR payload."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "get": {
        "x-required-role": "VIEWER",
        "tags": [
          "Card Activation"
        ],
        "summary": "List a card's active activation tokens.",
        "operationId": "cards.activationTokens.list",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Active activation tokens.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "tokenId": {
                        "type": "string"
                      },
                      "qrKind": {
                        "type": "string",
                        "enum": [
                          "ONE_TIME",
                          "FOREVER"
                        ]
                      },
                      "qrPayload": {
                        "type": "string",
                        "format": "uri"
                      },
                      "status": {
                        "type": "string",
                        "enum": [
                          "PENDING",
                          "CLAIMED",
                          "REVOKED",
                          "EXPIRED"
                        ]
                      },
                      "expiresAt": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "date-time"
                      },
                      "createdAt": {
                        "type": "string",
                        "format": "date-time"
                      }
                    },
                    "required": [
                      "tokenId",
                      "qrKind",
                      "qrPayload",
                      "status",
                      "expiresAt",
                      "createdAt"
                    ],
                    "description": "An active (PENDING, unexpired) activation token for a card."
                  }
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/cards/{id}/rescue": {
      "post": {
        "x-required-role": "OPERATOR",
        "tags": [
          "Card Activation"
        ],
        "summary": "Rescue a card — revoke outstanding tokens and re-issue a fresh ONE_TIME QR.",
        "description": "Destructive reset: revokes outstanding tokens, unassigns the card (clears holder + bound wallet), and mints a fresh ONE_TIME activation token.",
        "operationId": "cards.rescue",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "201": {
            "description": "Card rescued; fresh activation token minted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tokenId": {
                      "type": "string"
                    },
                    "qrPayload": {
                      "type": "string",
                      "format": "uri"
                    },
                    "qrKind": {
                      "type": "string",
                      "enum": [
                        "ONE_TIME",
                        "FOREVER"
                      ]
                    },
                    "expiresAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "tokenId",
                    "qrPayload",
                    "qrKind",
                    "expiresAt"
                  ],
                  "description": "A freshly minted activation token + its scannable QR payload."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/activation-tokens/{id}": {
      "get": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Card Activation"
        ],
        "summary": "Preview an activation token (for the wallet scanner).",
        "operationId": "activationTokens.preview",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Token preview.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tokenId": {
                      "type": "string"
                    },
                    "qrKind": {
                      "type": "string",
                      "enum": [
                        "ONE_TIME",
                        "FOREVER"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "PENDING",
                        "CLAIMED",
                        "REVOKED",
                        "EXPIRED"
                      ]
                    },
                    "card": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "kind": {
                          "type": "string",
                          "enum": [
                            "SIMPLE",
                            "MASTER"
                          ]
                        },
                        "design": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "imageUrl": {
                              "type": "string"
                            },
                            "description": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "imageUrl",
                            "description"
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "kind",
                        "design"
                      ]
                    }
                  },
                  "required": [
                    "tokenId",
                    "qrKind",
                    "status",
                    "card"
                  ],
                  "description": "Public, secret-free preview of an activation token for the wallet scanner."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/activation-tokens/{id}/claim": {
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Card Activation"
        ],
        "summary": "Claim a card via its activation token.",
        "description": "Any authenticated wallet user (NIP-98 or JWT). A ONE_TIME claim transfers the card to the claimer, binds a Remote Wallet, and burns the token. A second claim returns 409.",
        "operationId": "activationTokens.claim",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActivationTokenClaimRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Card claimed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "qrKind": {
                      "type": "string",
                      "enum": [
                        "ONE_TIME"
                      ]
                    },
                    "card": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "kind": {
                          "type": "string",
                          "enum": [
                            "SIMPLE",
                            "MASTER"
                          ]
                        },
                        "remoteWalletId": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "kind",
                        "remoteWalletId"
                      ]
                    }
                  },
                  "required": [
                    "qrKind",
                    "card"
                  ],
                  "description": "Result of a ONE_TIME claim — ownership transferred, token burned."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/card-designs": {
      "post": {
        "x-required-role": "OPERATOR",
        "tags": [
          "Card Designs"
        ],
        "summary": "Create a card design.",
        "operationId": "cardDesigns.create",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CardDesignCreateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Card design created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "imageUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "archivedAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "description",
                    "imageUrl",
                    "createdAt",
                    "archivedAt"
                  ],
                  "description": "Card design template."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/card-designs/list": {
      "get": {
        "x-required-role": "VIEWER",
        "tags": [
          "Card Designs"
        ],
        "summary": "List card designs.",
        "operationId": "cardDesigns.list",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Card designs.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "description": {
                        "type": "string"
                      },
                      "imageUrl": {
                        "type": "string",
                        "format": "uri"
                      },
                      "createdAt": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "archivedAt": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "date-time"
                      }
                    },
                    "required": [
                      "id",
                      "description",
                      "imageUrl",
                      "createdAt",
                      "archivedAt"
                    ],
                    "description": "Card design template."
                  }
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/card-designs/count": {
      "get": {
        "x-required-role": "VIEWER",
        "tags": [
          "Card Designs"
        ],
        "summary": "Count card designs.",
        "operationId": "cardDesigns.count",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Count.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "minimum": 0
                    }
                  },
                  "required": [
                    "count"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/card-designs/get/{id}": {
      "get": {
        "x-required-role": "ADMIN",
        "tags": [
          "Card Designs"
        ],
        "summary": "Get a card design by ID (alternate path).",
        "operationId": "cardDesigns.getById",
        "security": [
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Card design.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "imageUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "description",
                    "imageUrl",
                    "createdAt"
                  ],
                  "description": "Card design template (without archive state)."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/card-designs/{id}": {
      "put": {
        "x-required-role": "OPERATOR",
        "tags": [
          "Card Designs"
        ],
        "summary": "Update a card design.",
        "operationId": "cardDesigns.update",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CardDesignUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Card design updated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "imageUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "archivedAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "description",
                    "imageUrl",
                    "createdAt",
                    "archivedAt"
                  ],
                  "description": "Card design template."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/card-designs/import": {
      "post": {
        "x-required-role": "OPERATOR",
        "tags": [
          "Card Designs"
        ],
        "summary": "Import this community's card designs from veintiuno.lat.",
        "description": "Pulls the published veintiuno.lat catalog server-side and inserts the designs whose `communityId` matches the configured `community_id`. Takes no request body. Entries whose image URL is not an http(s) URL are skipped. Designs that already exist are left untouched. Returns 400 when `is_community` / `community_id` are not configured.",
        "operationId": "cardDesigns.import",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Import result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "imported": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "skipped": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "designs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "imageUrl": {
                            "type": "string",
                            "format": "uri"
                          },
                          "description": {
                            "type": "string"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "id",
                          "imageUrl",
                          "description",
                          "createdAt"
                        ]
                      }
                    }
                  },
                  "required": [
                    "success",
                    "message",
                    "imported",
                    "skipped"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/lightning-addresses": {
      "get": {
        "x-required-role": "VIEWER",
        "tags": [
          "Lightning Addresses"
        ],
        "summary": "List lightning addresses.",
        "operationId": "lightningAddresses.list",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Addresses.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "username": {
                            "type": "string"
                          },
                          "pubkey": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "domain": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "username"
                        ],
                        "description": "Lightning address record."
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/lightning-addresses/check": {
      "get": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Lightning Addresses"
        ],
        "summary": "Check whether a username is available.",
        "operationId": "lightningAddresses.check",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 16,
              "description": "Username candidate to check."
            },
            "required": true,
            "name": "username",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Availability result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "available": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "available"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/lightning-addresses/counts": {
      "get": {
        "x-required-role": "VIEWER",
        "tags": [
          "Lightning Addresses"
        ],
        "summary": "Lightning address counts.",
        "operationId": "lightningAddresses.counts",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Counts.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "total": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "active": {
                      "type": "integer",
                      "minimum": 0
                    }
                  },
                  "required": [
                    "total",
                    "active"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/lightning-addresses/relays": {
      "get": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Lightning Addresses"
        ],
        "summary": "List relays advertised for the platform.",
        "operationId": "lightningAddresses.relays",
        "security": [],
        "responses": {
          "200": {
            "description": "Relay list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "relays": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uri"
                      }
                    }
                  },
                  "required": [
                    "relays"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/lud16/{username}": {
      "get": {
        "x-required-role": "PUBLIC",
        "tags": [
          "LUD-16"
        ],
        "summary": "LUD-16 / LUD-06 pay request lookup.",
        "description": "Public lookup that resolves a lightning address to a LUD-06 pay request response. Supports LUD-12 (commentAllowed) and LUD-21 (verify field).",
        "operationId": "lud16.payRequest",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "username",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Pay request.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/lud16/{username}/cb": {
      "get": {
        "x-required-role": "PUBLIC",
        "tags": [
          "LUD-16"
        ],
        "summary": "LUD-16 callback that returns a BOLT11 invoice.",
        "operationId": "lud16.callback",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "username",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "amount",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "required": false,
            "name": "comment",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 65536
            },
            "required": false,
            "name": "nostr",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Callback response with the BOLT11 invoice.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "pr": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "pr"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/lud16/{username}/verify/{paymentHash}": {
      "get": {
        "x-required-role": "PUBLIC",
        "tags": [
          "LUD-16"
        ],
        "summary": "LUD-21 payment verification.",
        "operationId": "lud16.verify",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Lightning address username."
            },
            "required": true,
            "name": "username",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "BOLT11 payment hash returned by /cb."
            },
            "required": true,
            "name": "paymentHash",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Verification status.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "OK",
                        "ERROR"
                      ]
                    }
                  },
                  "required": [
                    "status"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/wallet/addresses": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Wallet"
        ],
        "summary": "List the caller’s wallet addresses.",
        "operationId": "wallet.addresses.list",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Addresses.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "username": {
                            "type": "string"
                          },
                          "mode": {
                            "type": "string",
                            "enum": [
                              "IDLE",
                              "ALIAS",
                              "CUSTOM_NWC"
                            ]
                          },
                          "redirect": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "remoteWalletId": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "isPrimary": {
                            "type": "boolean"
                          }
                        },
                        "required": [
                          "username",
                          "mode"
                        ],
                        "description": "Per-user wallet lightning address record."
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Wallet"
        ],
        "summary": "Create a wallet address for the caller.",
        "operationId": "wallet.addresses.create",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WalletAddressCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Address created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "username": {
                      "type": "string"
                    },
                    "mode": {
                      "type": "string",
                      "enum": [
                        "IDLE",
                        "ALIAS",
                        "CUSTOM_NWC"
                      ]
                    },
                    "redirect": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "remoteWalletId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "isPrimary": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "username",
                    "mode"
                  ],
                  "description": "Per-user wallet lightning address record."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/wallet/addresses/{username}/proxy-balance": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Wallet"
        ],
        "summary": "Get the caller’s pending deferred-proxy balance.",
        "description": "Returns only paid inbound proxy settlements that are still owed to their destination, excluding settled or ambiguous outgoing payments.",
        "operationId": "wallet.addresses.proxyBalance.get",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 16,
              "pattern": "^[a-z0-9]+$"
            },
            "required": true,
            "name": "username",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Pending proxy balance.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "pendingAmountMsats": {
                      "type": "string"
                    },
                    "pendingPaymentCount": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "blockedPaymentCount": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "inFlightPaymentCount": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "oldestPendingAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "destination": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "pendingAmountMsats",
                    "pendingPaymentCount",
                    "blockedPaymentCount",
                    "inFlightPaymentCount",
                    "oldestPendingAt",
                    "destination"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Wallet"
        ],
        "summary": "Forward every safe pending deferred-proxy settlement.",
        "description": "Atomically locks eligible settlements and schedules a bounded reconciliation pass. Requests are rejected while any payment has an active worker lease or ambiguous outgoing attempt, preventing duplicate sends.",
        "operationId": "wallet.addresses.proxyBalance.forward",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 16,
              "pattern": "^[a-z0-9]+$"
            },
            "required": true,
            "name": "username",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Pending settlements forwarded or queued for reconciliation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "queued": {
                      "type": "integer",
                      "exclusiveMinimum": 0
                    },
                    "reconciliation": {
                      "type": "object",
                      "properties": {
                        "claimed": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "completed": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "failed": {
                          "type": "integer",
                          "minimum": 0
                        }
                      },
                      "required": [
                        "claimed",
                        "completed",
                        "failed"
                      ]
                    }
                  },
                  "required": [
                    "success",
                    "queued",
                    "reconciliation"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/wallet/cards": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Wallet"
        ],
        "summary": "List the cards paired to the caller.",
        "description": "Returns only the cards paired to the authenticated user (`Card.userId === caller`). ANY authenticated role can read their own cards — unlike the admin-scoped `/api/cards` (gated on `CARDS_READ`), which returns every card. Powers the per-user Cards view and the Connection Map. Never returns NTAG424 keys.",
        "operationId": "wallet.cards.list",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Cards.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "title": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "pubkey": {
                        "type": "string"
                      },
                      "username": {
                        "type": "string"
                      },
                      "remoteWalletId": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "kind": {
                        "type": "string",
                        "enum": [
                          "SIMPLE",
                          "MASTER"
                        ],
                        "description": "MASTER designates the caller’s account-recovery card — at most one."
                      },
                      "masterCardId": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "description": "Id of the caller’s current MASTER card, or null when they have none."
                      }
                    },
                    "required": [
                      "id"
                    ],
                    "description": "A card paired to the caller. Never includes NTAG424 keys (only the public `cid`/`ctr` on `ntag424`)."
                  }
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/wallet/addresses/{username}/invoices/{invoiceId}/forwarding": {
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Wallet"
        ],
        "summary": "Recover a blocked deferred-proxy settlement.",
        "description": "Retries a blocked forwarding payment or changes that payment’s destination. A destination change only applies to the selected settlement; active or ambiguous outgoing attempts cannot be changed or retried.",
        "operationId": "wallet.addresses.invoices.forwarding.recover",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 16,
              "pattern": "^[a-z0-9]+$"
            },
            "required": true,
            "name": "username",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            },
            "required": true,
            "name": "invoiceId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProxyForwardingCommandRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recovery command completed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "retry",
                        "change_destination"
                      ]
                    },
                    "reconciliation": {
                      "type": "object",
                      "properties": {
                        "claimed": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "completed": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "failed": {
                          "type": "integer",
                          "minimum": 0
                        }
                      },
                      "required": [
                        "claimed",
                        "completed",
                        "failed"
                      ]
                    },
                    "payment": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "destination": {
                          "type": "string"
                        },
                        "lastError": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "destination",
                        "lastError"
                      ]
                    }
                  },
                  "required": [
                    "success",
                    "action"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "413": {
            "description": "Request body exceeds the configured limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/wallet/cards/{id}": {
      "patch": {
        "x-required-role": "USER",
        "tags": [
          "Wallet"
        ],
        "summary": "Update one of the caller’s cards.",
        "description": "Enables or disables an owner-scoped card, or binds it to the caller’s active primary remote wallet. Blocked cards cannot be updated.",
        "operationId": "wallet.cards.update",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WalletCardUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Card updated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "title": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "pubkey": {
                      "type": "string"
                    },
                    "username": {
                      "type": "string"
                    },
                    "remoteWalletId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "SIMPLE",
                        "MASTER"
                      ],
                      "description": "MASTER designates the caller’s account-recovery card — at most one."
                    },
                    "masterCardId": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Id of the caller’s current MASTER card, or null when they have none."
                    }
                  },
                  "required": [
                    "id"
                  ],
                  "description": "A card paired to the caller. Never includes NTAG424 keys (only the public `cid`/`ctr` on `ntag424`)."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/wallet/addresses/alias-probe": {
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Wallet"
        ],
        "summary": "Probe a Lightning Address before using it as an alias.",
        "description": "Checks LUD-16 reachability and reports optional LUD-21 and NIP-57 capabilities. LUD-16 support determines whether the alias can be saved.",
        "operationId": "wallet.addresses.probeAlias",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WalletAliasProbeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Alias capabilities.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "address": {
                      "type": "string"
                    },
                    "canSave": {
                      "type": "boolean"
                    },
                    "checks": {
                      "type": "object",
                      "properties": {
                        "lud16": {
                          "type": "object",
                          "properties": {
                            "ok": {
                              "type": "boolean"
                            },
                            "message": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "ok",
                            "message"
                          ]
                        },
                        "lud21": {
                          "type": "object",
                          "properties": {
                            "ok": {
                              "type": "boolean"
                            },
                            "message": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "ok",
                            "message"
                          ]
                        },
                        "nip57": {
                          "type": "object",
                          "properties": {
                            "ok": {
                              "type": "boolean"
                            },
                            "message": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "ok",
                            "message"
                          ]
                        }
                      },
                      "required": [
                        "lud16",
                        "lud21",
                        "nip57"
                      ]
                    }
                  },
                  "required": [
                    "address",
                    "canSave",
                    "checks"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/wallet/addresses/{username}": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Wallet"
        ],
        "summary": "Get a wallet address by username.",
        "operationId": "wallet.addresses.get",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 16,
              "pattern": "^[a-z0-9]+$"
            },
            "required": true,
            "name": "username",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Address.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "username": {
                      "type": "string"
                    },
                    "mode": {
                      "type": "string",
                      "enum": [
                        "IDLE",
                        "ALIAS",
                        "CUSTOM_NWC"
                      ]
                    },
                    "redirect": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "remoteWalletId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "isPrimary": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "username",
                    "mode"
                  ],
                  "description": "Per-user wallet lightning address record."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "put": {
        "x-required-role": "USER",
        "tags": [
          "Wallet"
        ],
        "summary": "Update a wallet address (mode, redirect, NWC connection).",
        "operationId": "wallet.addresses.update",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 16,
              "pattern": "^[a-z0-9]+$"
            },
            "required": true,
            "name": "username",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WalletAddressUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Address updated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "username": {
                      "type": "string"
                    },
                    "mode": {
                      "type": "string",
                      "enum": [
                        "IDLE",
                        "ALIAS",
                        "CUSTOM_NWC"
                      ]
                    },
                    "redirect": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "remoteWalletId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "isPrimary": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "username",
                    "mode"
                  ],
                  "description": "Per-user wallet lightning address record."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "delete": {
        "x-required-role": "USER",
        "tags": [
          "Wallet"
        ],
        "summary": "Delete one of the caller’s own wallet addresses.",
        "operationId": "wallet.addresses.delete",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 16,
              "pattern": "^[a-z0-9]+$"
            },
            "required": true,
            "name": "username",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Address deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "username": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "username"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/wallet/addresses/{username}/primary": {
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Wallet"
        ],
        "summary": "Set this wallet address as the caller’s primary.",
        "operationId": "wallet.addresses.setPrimary",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 16,
              "pattern": "^[a-z0-9]+$"
            },
            "required": true,
            "name": "username",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Primary set.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    }
                  },
                  "required": [
                    "success"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/wallet/addresses/{username}/invoices": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Wallet"
        ],
        "summary": "List invoices associated with a wallet address.",
        "operationId": "wallet.addresses.invoices",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 16,
              "pattern": "^[a-z0-9]+$"
            },
            "required": true,
            "name": "username",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Invoices.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {}
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/users": {
      "get": {
        "x-required-role": "VIEWER",
        "tags": [
          "Users"
        ],
        "summary": "List users.",
        "operationId": "users.list",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Users.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "pubkey": {
                            "type": "string"
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "ADMIN",
                              "OPERATOR",
                              "VIEWER",
                              "USER"
                            ]
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "id",
                          "pubkey",
                          "role",
                          "createdAt"
                        ],
                        "description": "User record."
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/users/me": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Users"
        ],
        "summary": "Load or create the current user.",
        "operationId": "users.me",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Current user.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "pubkey": {
                      "type": "string"
                    },
                    "role": {
                      "type": "string",
                      "enum": [
                        "ADMIN",
                        "OPERATOR",
                        "VIEWER",
                        "USER"
                      ]
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "pubkey",
                    "role",
                    "createdAt"
                  ],
                  "description": "User record."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/users/{userId}": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Users"
        ],
        "summary": "Get a user by ID.",
        "operationId": "users.get",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "userId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "User.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "pubkey": {
                      "type": "string"
                    },
                    "role": {
                      "type": "string",
                      "enum": [
                        "ADMIN",
                        "OPERATOR",
                        "VIEWER",
                        "USER"
                      ]
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "pubkey",
                    "role",
                    "createdAt"
                  ],
                  "description": "User record."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/users/{userId}/cards": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Users"
        ],
        "summary": "List cards owned by a user (self only).",
        "operationId": "users.cards.list",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "userId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "User cards.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {}
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/users/{userId}/role": {
      "put": {
        "x-required-role": "ADMIN",
        "tags": [
          "Users"
        ],
        "summary": "Update a user’s role.",
        "operationId": "users.role.set",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "userId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserRoleUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Role updated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "pubkey": {
                      "type": "string"
                    },
                    "role": {
                      "type": "string",
                      "enum": [
                        "ADMIN",
                        "OPERATOR",
                        "VIEWER",
                        "USER"
                      ]
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "pubkey",
                    "role",
                    "createdAt"
                  ],
                  "description": "User record."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/users/{userId}/relays": {
      "put": {
        "x-required-role": "USER",
        "tags": [
          "Users"
        ],
        "summary": "Set the user’s preferred Nostr relays (self only).",
        "operationId": "users.relays.set",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "userId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "relays": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "example": "wss://lacrypta.ar"
                    },
                    "maxItems": 20
                  }
                },
                "required": [
                  "relays"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Relays updated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "userId": {
                      "type": "string"
                    },
                    "relays": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "userId",
                    "relays"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/users/{userId}/lightning-address": {
      "put": {
        "x-required-role": "USER",
        "tags": [
          "Users"
        ],
        "summary": "Assign or replace a user’s lightning address (self only).",
        "operationId": "users.lightningAddress.set",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "userId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LightningAddressUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Address assigned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "username": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "username"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/invoices": {
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Invoices"
        ],
        "summary": "Create a registration / wallet-address invoice.",
        "operationId": "invoices.create",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvoiceCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Invoice created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "purpose": {
                      "type": "string",
                      "enum": [
                        "registration",
                        "wallet-address"
                      ]
                    },
                    "pr": {
                      "type": "string"
                    },
                    "paymentHash": {
                      "type": "string"
                    },
                    "settled": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "purpose",
                    "pr",
                    "paymentHash",
                    "settled",
                    "createdAt"
                  ],
                  "description": "Pay-then-act invoice for registration flows."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/invoices/{id}/claim": {
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Invoices"
        ],
        "summary": "Claim a paid invoice with the BOLT11 preimage.",
        "operationId": "invoices.claim",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvoiceClaimRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invoice claimed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "purpose": {
                      "type": "string",
                      "enum": [
                        "registration",
                        "wallet-address"
                      ]
                    },
                    "pr": {
                      "type": "string"
                    },
                    "paymentHash": {
                      "type": "string"
                    },
                    "settled": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "purpose",
                    "pr",
                    "paymentHash",
                    "settled",
                    "createdAt"
                  ],
                  "description": "Pay-then-act invoice for registration flows."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/settings": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Settings"
        ],
        "summary": "Read settings; anonymous callers see public keys only.",
        "operationId": "settings.get",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Settings map.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "x-required-role": "ADMIN",
        "tags": [
          "Settings"
        ],
        "summary": "Upsert one or more settings.",
        "operationId": "settings.update",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SettingsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Settings updated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/admin/assign": {
      "get": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Admin"
        ],
        "summary": "Read admin-assignment status.",
        "description": "One-time bootstrap check — once an admin is assigned this endpoint is no longer relevant. Authenticated via NIP-98 directly so the bootstrap wizard works without a JWT.",
        "operationId": "admin.assign.get",
        "security": [
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Assignment status.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "pubkey": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Admin"
        ],
        "summary": "Assign the admin role.",
        "description": "One-time bootstrap operation — succeeds only when no admin exists. Subsequent calls are rejected. Authenticated via NIP-98 directly so the bootstrap wizard works without a JWT.",
        "operationId": "admin.assign.set",
        "security": [
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Admin assigned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    }
                  },
                  "required": [
                    "success"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/setup/status": {
      "get": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Setup"
        ],
        "summary": "Check whether the platform has completed initial setup.",
        "operationId": "setup.status",
        "security": [],
        "responses": {
          "200": {
            "description": "Setup status.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "hasRoot": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "hasRoot"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/setup/verify": {
      "get": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Setup"
        ],
        "summary": "Read the active setup-verification token.",
        "operationId": "setup.verify.get",
        "security": [],
        "responses": {
          "200": {
            "description": "Plain-text verification token.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Setup"
        ],
        "summary": "Issue a fresh setup-verification token.",
        "operationId": "setup.verify.post",
        "security": [],
        "responses": {
          "200": {
            "description": "Newly issued token.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "token"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "options": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Setup"
        ],
        "summary": "CORS preflight for /api/setup/verify.",
        "operationId": "setup.verify.options",
        "security": [],
        "responses": {
          "204": {
            "description": "Preflight OK."
          }
        }
      }
    },
    "/api/version": {
      "get": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Version"
        ],
        "summary": "Check the running web app version and latest GitHub release.",
        "operationId": "version.get",
        "security": [],
        "responses": {
          "200": {
            "description": "Current version and latest release status.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "currentVersion": {
                      "type": "string"
                    },
                    "latestVersion": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "releaseUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "updateAvailable": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "currentVersion",
                    "latestVersion",
                    "releaseUrl",
                    "updateAvailable"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/remote-connections/{externalDeviceKey}": {
      "get": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Remote Connections"
        ],
        "summary": "Bootstrap metadata for a remote device (auth via shared device key).",
        "operationId": "remoteConnections.get",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "externalDeviceKey",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Remote device metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/remote-connections/{externalDeviceKey}/cards": {
      "post": {
        "x-required-role": "PUBLIC",
        "tags": [
          "Remote Connections"
        ],
        "summary": "Initialize a card from a remote device (auth via shared device key).",
        "operationId": "remoteConnections.cards.create",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "externalDeviceKey",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoteCardCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Remote card initialized.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/remote-wallets": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "List the caller’s remote wallets (REVOKED hidden unless filtered by status).",
        "operationId": "remoteWallets.list",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "enum": [
                "ACTIVE",
                "DISABLED",
                "REVOKED",
                "DEAD"
              ]
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "NWC",
                "LND",
                "CLN",
                "BTCPAY"
              ]
            },
            "required": false,
            "name": "type",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Remote wallets.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "name": {
                        "type": "string"
                      },
                      "type": {
                        "type": "string",
                        "enum": [
                          "NWC",
                          "LND",
                          "CLN",
                          "BTCPAY"
                        ]
                      },
                      "status": {
                        "type": "string",
                        "enum": [
                          "ACTIVE",
                          "DISABLED",
                          "REVOKED",
                          "DEAD"
                        ]
                      },
                      "isDefault": {
                        "type": "boolean"
                      },
                      "createdAt": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "updatedAt": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "diedAt": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "date-time",
                        "description": "When an archived (DEAD) disposable wallet was detected dead; null otherwise."
                      },
                      "provider": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "enum": [
                          "lncurl"
                        ],
                        "description": "'lncurl' for a disposable LNCurl wallet; null for a user-supplied connection."
                      },
                      "lncurlServerUrl": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "description": "For LNCurl wallets, the server that minted this wallet; null otherwise."
                      }
                    },
                    "required": [
                      "id",
                      "name",
                      "type",
                      "status",
                      "isDefault",
                      "createdAt",
                      "updatedAt",
                      "diedAt",
                      "provider",
                      "lncurlServerUrl"
                    ],
                    "description": "Remote wallet record. The secret `config` is never returned."
                  }
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "Create a remote wallet for the caller.",
        "operationId": "remoteWallets.create",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoteWalletCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Remote wallet created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "NWC",
                        "LND",
                        "CLN",
                        "BTCPAY"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "ACTIVE",
                        "DISABLED",
                        "REVOKED",
                        "DEAD"
                      ]
                    },
                    "isDefault": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "diedAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time",
                      "description": "When an archived (DEAD) disposable wallet was detected dead; null otherwise."
                    },
                    "provider": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "enum": [
                        "lncurl"
                      ],
                      "description": "'lncurl' for a disposable LNCurl wallet; null for a user-supplied connection."
                    },
                    "lncurlServerUrl": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "For LNCurl wallets, the server that minted this wallet; null otherwise."
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "type",
                    "status",
                    "isDefault",
                    "createdAt",
                    "updatedAt",
                    "diedAt",
                    "provider",
                    "lncurlServerUrl"
                  ],
                  "description": "Remote wallet record. The secret `config` is never returned."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/remote-wallets/{id}/receive-action": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "Get the caller’s receive-forwarding action for a remote wallet.",
        "operationId": "remoteWallets.receiveAction.get",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Receive action.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "walletId": {
                      "type": "string"
                    },
                    "eligible": {
                      "type": "boolean"
                    },
                    "reason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "configured": {
                      "type": "boolean"
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "enabledAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "pausedAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "pendingReceipts": {
                      "type": "integer"
                    },
                    "pendingAmountMsats": {
                      "type": "integer"
                    },
                    "attemptInProgress": {
                      "type": "boolean"
                    },
                    "routingReserveBps": {
                      "type": "integer"
                    },
                    "routingReserveBaseSats": {
                      "type": "integer"
                    },
                    "revision": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "number": {
                          "type": "integer"
                        },
                        "feeBps": {
                          "type": "integer"
                        },
                        "baseFeeSats": {
                          "type": "number"
                        },
                        "destinations": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "address": {
                                "type": "string"
                              },
                              "allocationBps": {
                                "type": "integer"
                              }
                            },
                            "required": [
                              "address",
                              "allocationBps"
                            ]
                          }
                        }
                      },
                      "required": [
                        "number",
                        "feeBps",
                        "baseFeeSats",
                        "destinations"
                      ]
                    }
                  },
                  "required": [
                    "walletId",
                    "eligible",
                    "reason",
                    "configured",
                    "enabled",
                    "enabledAt",
                    "pausedAt",
                    "pendingReceipts",
                    "pendingAmountMsats",
                    "attemptInProgress",
                    "routingReserveBps",
                    "routingReserveBaseSats",
                    "revision"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "put": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "Create or atomically revise a receive-forwarding action.",
        "operationId": "remoteWallets.receiveAction.configure",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoteWalletReceiveActionConfigRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Receive action configured.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "walletId": {
                      "type": "string"
                    },
                    "eligible": {
                      "type": "boolean"
                    },
                    "reason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "configured": {
                      "type": "boolean"
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "enabledAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "pausedAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "pendingReceipts": {
                      "type": "integer"
                    },
                    "pendingAmountMsats": {
                      "type": "integer"
                    },
                    "attemptInProgress": {
                      "type": "boolean"
                    },
                    "routingReserveBps": {
                      "type": "integer"
                    },
                    "routingReserveBaseSats": {
                      "type": "integer"
                    },
                    "revision": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "number": {
                          "type": "integer"
                        },
                        "feeBps": {
                          "type": "integer"
                        },
                        "baseFeeSats": {
                          "type": "number"
                        },
                        "destinations": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "address": {
                                "type": "string"
                              },
                              "allocationBps": {
                                "type": "integer"
                              }
                            },
                            "required": [
                              "address",
                              "allocationBps"
                            ]
                          }
                        }
                      },
                      "required": [
                        "number",
                        "feeBps",
                        "baseFeeSats",
                        "destinations"
                      ]
                    }
                  },
                  "required": [
                    "walletId",
                    "eligible",
                    "reason",
                    "configured",
                    "enabled",
                    "enabledAt",
                    "pausedAt",
                    "pendingReceipts",
                    "pendingAmountMsats",
                    "attemptInProgress",
                    "routingReserveBps",
                    "routingReserveBaseSats",
                    "revision"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "patch": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "Pause or resume a receive-forwarding action.",
        "operationId": "remoteWallets.receiveAction.toggle",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoteWalletReceiveActionToggleRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Receive action updated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "walletId": {
                      "type": "string"
                    },
                    "eligible": {
                      "type": "boolean"
                    },
                    "reason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "configured": {
                      "type": "boolean"
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "enabledAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "pausedAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "pendingReceipts": {
                      "type": "integer"
                    },
                    "pendingAmountMsats": {
                      "type": "integer"
                    },
                    "attemptInProgress": {
                      "type": "boolean"
                    },
                    "routingReserveBps": {
                      "type": "integer"
                    },
                    "routingReserveBaseSats": {
                      "type": "integer"
                    },
                    "revision": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "number": {
                          "type": "integer"
                        },
                        "feeBps": {
                          "type": "integer"
                        },
                        "baseFeeSats": {
                          "type": "number"
                        },
                        "destinations": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "address": {
                                "type": "string"
                              },
                              "allocationBps": {
                                "type": "integer"
                              }
                            },
                            "required": [
                              "address",
                              "allocationBps"
                            ]
                          }
                        }
                      },
                      "required": [
                        "number",
                        "feeBps",
                        "baseFeeSats",
                        "destinations"
                      ]
                    }
                  },
                  "required": [
                    "walletId",
                    "eligible",
                    "reason",
                    "configured",
                    "enabled",
                    "enabledAt",
                    "pausedAt",
                    "pendingReceipts",
                    "pendingAmountMsats",
                    "attemptInProgress",
                    "routingReserveBps",
                    "routingReserveBaseSats",
                    "revision"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/remote-wallets/{id}/forwarding-activity": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "List forwarding attempts and retries for the caller’s wallet.",
        "operationId": "remoteWallets.forwardingActivity.list",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 30
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Forwarding activity.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "activity": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "receiptId": {
                            "type": "string"
                          },
                          "legId": {
                            "type": "string"
                          },
                          "destination": {
                            "type": "string"
                          },
                          "attemptNo": {
                            "type": "integer"
                          },
                          "amountMsats": {
                            "type": "integer"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "PENDING",
                              "UNKNOWN",
                              "REJECTED",
                              "SUCCEEDED",
                              "EXPIRED"
                            ]
                          },
                          "errorMessage": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "id",
                          "receiptId",
                          "legId",
                          "destination",
                          "attemptNo",
                          "amountMsats",
                          "status",
                          "errorMessage",
                          "createdAt"
                        ]
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "activity",
                    "nextCursor"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/remote-wallets/{id}/receive-action/force": {
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "Make every open receipt eligible now and wake the lease-protected forwarding worker.",
        "operationId": "remoteWallets.receiveAction.force",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "202": {
            "description": "Forwarding run accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "accepted": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "forwardingReceipts": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "accepted",
                    "forwardingReceipts"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/remote-wallets/{id}/forwarding-receipts": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "List forwarding receipts for the caller’s wallet.",
        "operationId": "remoteWallets.forwardingReceipts.list",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 30
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "RECEIVED",
                "FORWARDING",
                "PARTIAL",
                "BLOCKED",
                "COMPLETED",
                "RETAINED"
              ]
            },
            "required": false,
            "name": "status",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Forwarding receipts.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "receipts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "walletId": {
                            "type": "string"
                          },
                          "eventKey": {
                            "type": "string"
                          },
                          "sourcePaymentHash": {
                            "type": "string"
                          },
                          "sourceInvoice": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "grossAmountMsats": {
                            "type": "integer"
                          },
                          "retainedFeeMsats": {
                            "type": "integer"
                          },
                          "targetAmountMsats": {
                            "type": "integer"
                          },
                          "forwardedAmountMsats": {
                            "type": "integer"
                          },
                          "routingFeeMsats": {
                            "type": "integer"
                          },
                          "routingReserveMsats": {
                            "type": "integer"
                          },
                          "unusedRoutingReserveMsats": {
                            "type": "integer"
                          },
                          "routingFeeOverageMsats": {
                            "type": "integer"
                          },
                          "shortfallMsats": {
                            "type": "integer"
                          },
                          "configRevision": {
                            "type": "integer"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "RECEIVED",
                              "FORWARDING",
                              "PARTIAL",
                              "BLOCKED",
                              "COMPLETED",
                              "RETAINED"
                            ]
                          },
                          "recovered": {
                            "type": "boolean"
                          },
                          "sourceSettledAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "lastError": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "nextRetryAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "completedAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "revision": {
                            "type": "object",
                            "properties": {
                              "feeBps": {
                                "type": "integer"
                              },
                              "baseFeeSats": {
                                "type": "integer"
                              },
                              "destinations": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "address": {
                                      "type": "string"
                                    },
                                    "allocationBps": {
                                      "type": "integer"
                                    }
                                  },
                                  "required": [
                                    "address",
                                    "allocationBps"
                                  ]
                                }
                              }
                            },
                            "required": [
                              "feeBps",
                              "baseFeeSats",
                              "destinations"
                            ]
                          },
                          "legs": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string"
                                },
                                "position": {
                                  "type": "integer"
                                },
                                "destination": {
                                  "type": "string"
                                },
                                "allocationBps": {
                                  "type": "integer"
                                },
                                "requestedAmountMsats": {
                                  "type": "integer"
                                },
                                "forwardedAmountMsats": {
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                },
                                "routingFeeMsats": {
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                },
                                "routingReserveMsats": {
                                  "type": "integer"
                                },
                                "unusedRoutingReserveMsats": {
                                  "type": "integer"
                                },
                                "routingFeeOverageMsats": {
                                  "type": "integer"
                                },
                                "destinationShortfallMsats": {
                                  "type": "integer"
                                },
                                "status": {
                                  "type": "string",
                                  "enum": [
                                    "READY",
                                    "PENDING",
                                    "UNKNOWN",
                                    "REJECTED",
                                    "SUCCEEDED",
                                    "EXPIRED",
                                    "SUPERSEDED"
                                  ]
                                },
                                "retryCount": {
                                  "type": "integer"
                                },
                                "nextRetryAt": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "lastError": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "createdAt": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "completedAt": {
                                  "type": [
                                    "string",
                                    "null"
                                  ],
                                  "format": "date-time"
                                },
                                "attempts": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "id": {
                                        "type": "string"
                                      },
                                      "attemptNo": {
                                        "type": "integer"
                                      },
                                      "bolt11": {
                                        "type": "string"
                                      },
                                      "paymentHash": {
                                        "type": "string"
                                      },
                                      "amountMsats": {
                                        "type": "integer"
                                      },
                                      "requestId": {
                                        "type": "string"
                                      },
                                      "status": {
                                        "type": "string",
                                        "enum": [
                                          "PENDING",
                                          "UNKNOWN",
                                          "REJECTED",
                                          "SUCCEEDED",
                                          "EXPIRED"
                                        ]
                                      },
                                      "preimage": {
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "routingFeeMsats": {
                                        "type": [
                                          "integer",
                                          "null"
                                        ]
                                      },
                                      "routingReserveMsats": {
                                        "type": "integer"
                                      },
                                      "errorCode": {
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "errorMessage": {
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "expiresAt": {
                                        "type": "string",
                                        "format": "date-time"
                                      },
                                      "createdAt": {
                                        "type": "string",
                                        "format": "date-time"
                                      },
                                      "resolvedAt": {
                                        "type": [
                                          "string",
                                          "null"
                                        ],
                                        "format": "date-time"
                                      }
                                    },
                                    "required": [
                                      "id",
                                      "attemptNo",
                                      "bolt11",
                                      "paymentHash",
                                      "amountMsats",
                                      "requestId",
                                      "status",
                                      "preimage",
                                      "routingFeeMsats",
                                      "routingReserveMsats",
                                      "errorCode",
                                      "errorMessage",
                                      "expiresAt",
                                      "createdAt",
                                      "resolvedAt"
                                    ]
                                  }
                                }
                              },
                              "required": [
                                "id",
                                "position",
                                "destination",
                                "allocationBps",
                                "requestedAmountMsats",
                                "forwardedAmountMsats",
                                "routingFeeMsats",
                                "routingReserveMsats",
                                "unusedRoutingReserveMsats",
                                "routingFeeOverageMsats",
                                "destinationShortfallMsats",
                                "status",
                                "retryCount",
                                "nextRetryAt",
                                "lastError",
                                "createdAt",
                                "completedAt"
                              ]
                            }
                          }
                        },
                        "required": [
                          "id",
                          "walletId",
                          "eventKey",
                          "sourcePaymentHash",
                          "sourceInvoice",
                          "grossAmountMsats",
                          "retainedFeeMsats",
                          "targetAmountMsats",
                          "forwardedAmountMsats",
                          "routingFeeMsats",
                          "routingReserveMsats",
                          "unusedRoutingReserveMsats",
                          "routingFeeOverageMsats",
                          "shortfallMsats",
                          "configRevision",
                          "status",
                          "recovered",
                          "sourceSettledAt",
                          "lastError",
                          "nextRetryAt",
                          "completedAt",
                          "createdAt",
                          "updatedAt",
                          "legs"
                        ]
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "receipts",
                    "nextCursor"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/remote-wallets/{id}/forwarding-receipts/{receiptId}": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "Get a forwarding receipt with every leg and attempt.",
        "operationId": "remoteWallets.forwardingReceipts.get",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "receiptId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Forwarding receipt.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "walletId": {
                      "type": "string"
                    },
                    "eventKey": {
                      "type": "string"
                    },
                    "sourcePaymentHash": {
                      "type": "string"
                    },
                    "sourceInvoice": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "grossAmountMsats": {
                      "type": "integer"
                    },
                    "retainedFeeMsats": {
                      "type": "integer"
                    },
                    "targetAmountMsats": {
                      "type": "integer"
                    },
                    "forwardedAmountMsats": {
                      "type": "integer"
                    },
                    "routingFeeMsats": {
                      "type": "integer"
                    },
                    "routingReserveMsats": {
                      "type": "integer"
                    },
                    "unusedRoutingReserveMsats": {
                      "type": "integer"
                    },
                    "routingFeeOverageMsats": {
                      "type": "integer"
                    },
                    "shortfallMsats": {
                      "type": "integer"
                    },
                    "configRevision": {
                      "type": "integer"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "RECEIVED",
                        "FORWARDING",
                        "PARTIAL",
                        "BLOCKED",
                        "COMPLETED",
                        "RETAINED"
                      ]
                    },
                    "recovered": {
                      "type": "boolean"
                    },
                    "sourceSettledAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "lastError": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "nextRetryAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "completedAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "revision": {
                      "type": "object",
                      "properties": {
                        "feeBps": {
                          "type": "integer"
                        },
                        "baseFeeSats": {
                          "type": "integer"
                        },
                        "destinations": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "address": {
                                "type": "string"
                              },
                              "allocationBps": {
                                "type": "integer"
                              }
                            },
                            "required": [
                              "address",
                              "allocationBps"
                            ]
                          }
                        }
                      },
                      "required": [
                        "feeBps",
                        "baseFeeSats",
                        "destinations"
                      ]
                    },
                    "legs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "position": {
                            "type": "integer"
                          },
                          "destination": {
                            "type": "string"
                          },
                          "allocationBps": {
                            "type": "integer"
                          },
                          "requestedAmountMsats": {
                            "type": "integer"
                          },
                          "forwardedAmountMsats": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "routingFeeMsats": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "routingReserveMsats": {
                            "type": "integer"
                          },
                          "unusedRoutingReserveMsats": {
                            "type": "integer"
                          },
                          "routingFeeOverageMsats": {
                            "type": "integer"
                          },
                          "destinationShortfallMsats": {
                            "type": "integer"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "READY",
                              "PENDING",
                              "UNKNOWN",
                              "REJECTED",
                              "SUCCEEDED",
                              "EXPIRED",
                              "SUPERSEDED"
                            ]
                          },
                          "retryCount": {
                            "type": "integer"
                          },
                          "nextRetryAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "lastError": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "completedAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "attempts": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string"
                                },
                                "attemptNo": {
                                  "type": "integer"
                                },
                                "bolt11": {
                                  "type": "string"
                                },
                                "paymentHash": {
                                  "type": "string"
                                },
                                "amountMsats": {
                                  "type": "integer"
                                },
                                "requestId": {
                                  "type": "string"
                                },
                                "status": {
                                  "type": "string",
                                  "enum": [
                                    "PENDING",
                                    "UNKNOWN",
                                    "REJECTED",
                                    "SUCCEEDED",
                                    "EXPIRED"
                                  ]
                                },
                                "preimage": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "routingFeeMsats": {
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                },
                                "routingReserveMsats": {
                                  "type": "integer"
                                },
                                "errorCode": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "errorMessage": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "expiresAt": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "createdAt": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "resolvedAt": {
                                  "type": [
                                    "string",
                                    "null"
                                  ],
                                  "format": "date-time"
                                }
                              },
                              "required": [
                                "id",
                                "attemptNo",
                                "bolt11",
                                "paymentHash",
                                "amountMsats",
                                "requestId",
                                "status",
                                "preimage",
                                "routingFeeMsats",
                                "routingReserveMsats",
                                "errorCode",
                                "errorMessage",
                                "expiresAt",
                                "createdAt",
                                "resolvedAt"
                              ]
                            }
                          }
                        },
                        "required": [
                          "id",
                          "position",
                          "destination",
                          "allocationBps",
                          "requestedAmountMsats",
                          "forwardedAmountMsats",
                          "routingFeeMsats",
                          "routingReserveMsats",
                          "unusedRoutingReserveMsats",
                          "routingFeeOverageMsats",
                          "destinationShortfallMsats",
                          "status",
                          "retryCount",
                          "nextRetryAt",
                          "lastError",
                          "createdAt",
                          "completedAt"
                        ]
                      }
                    }
                  },
                  "required": [
                    "id",
                    "walletId",
                    "eventKey",
                    "sourcePaymentHash",
                    "sourceInvoice",
                    "grossAmountMsats",
                    "retainedFeeMsats",
                    "targetAmountMsats",
                    "forwardedAmountMsats",
                    "routingFeeMsats",
                    "routingReserveMsats",
                    "unusedRoutingReserveMsats",
                    "routingFeeOverageMsats",
                    "shortfallMsats",
                    "configRevision",
                    "status",
                    "recovered",
                    "sourceSettledAt",
                    "lastError",
                    "nextRetryAt",
                    "completedAt",
                    "createdAt",
                    "updatedAt",
                    "legs"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/remote-wallets/{id}/forwarding-receipts/{receiptId}/retry": {
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "Retry all safely retryable legs or a selected subset.",
        "operationId": "remoteWallets.forwardingReceipts.retry",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "receiptId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoteWalletForwardRetryRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Retry accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "accepted": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "retryingLegs": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "accepted",
                    "retryingLegs"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/remote-wallets/{id}/notifications": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "List the caller’s outbound RemoteWallet notification channels.",
        "operationId": "remoteWallets.notifications.list",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Notification channels and recent deliveries.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "notifications": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "channel": {
                            "type": "string",
                            "enum": [
                              "WEBHOOK",
                              "NOSTR"
                            ]
                          },
                          "enabled": {
                            "type": "boolean"
                          },
                          "action": {
                            "type": "string",
                            "enum": [
                              "RECEIVED",
                              "FORWARDED"
                            ]
                          },
                          "pausedAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "webhookUrl": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "nostrKind": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "nostrRecipient": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "nostrRelays": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "nostrContent": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "nip44": {
                            "type": "boolean"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "deliveries": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string"
                                },
                                "notificationId": {
                                  "type": "string"
                                },
                                "notification": {
                                  "type": [
                                    "object",
                                    "null"
                                  ],
                                  "properties": {
                                    "id": {
                                      "type": "string"
                                    },
                                    "name": {
                                      "type": "string"
                                    },
                                    "channel": {
                                      "type": "string",
                                      "enum": [
                                        "WEBHOOK",
                                        "NOSTR"
                                      ]
                                    },
                                    "enabled": {
                                      "type": "boolean"
                                    }
                                  },
                                  "required": [
                                    "id",
                                    "name",
                                    "channel",
                                    "enabled"
                                  ]
                                },
                                "eventKey": {
                                  "type": "string"
                                },
                                "action": {
                                  "type": "string",
                                  "enum": [
                                    "RECEIVED",
                                    "FORWARDED"
                                  ]
                                },
                                "payload": {},
                                "status": {
                                  "type": "string",
                                  "enum": [
                                    "READY",
                                    "PENDING",
                                    "UNKNOWN",
                                    "REJECTED",
                                    "SUCCEEDED",
                                    "EXPIRED"
                                  ]
                                },
                                "attemptCount": {
                                  "type": "integer"
                                },
                                "lastError": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "nextRetryAt": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "completedAt": {
                                  "type": [
                                    "string",
                                    "null"
                                  ],
                                  "format": "date-time"
                                },
                                "createdAt": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "updatedAt": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "attempts": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "id": {
                                        "type": "string"
                                      },
                                      "attemptNo": {
                                        "type": "integer"
                                      },
                                      "requestId": {
                                        "type": "string"
                                      },
                                      "status": {
                                        "type": "string",
                                        "enum": [
                                          "PENDING",
                                          "UNKNOWN",
                                          "REJECTED",
                                          "SUCCEEDED",
                                          "EXPIRED"
                                        ]
                                      },
                                      "responseStatus": {
                                        "type": [
                                          "integer",
                                          "null"
                                        ]
                                      },
                                      "responseBody": {
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "nostrEventId": {
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "errorCode": {
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "errorMessage": {
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "createdAt": {
                                        "type": "string",
                                        "format": "date-time"
                                      },
                                      "resolvedAt": {
                                        "type": [
                                          "string",
                                          "null"
                                        ],
                                        "format": "date-time"
                                      }
                                    },
                                    "required": [
                                      "id",
                                      "attemptNo",
                                      "requestId",
                                      "status",
                                      "responseStatus",
                                      "responseBody",
                                      "nostrEventId",
                                      "errorCode",
                                      "errorMessage",
                                      "createdAt",
                                      "resolvedAt"
                                    ]
                                  }
                                }
                              },
                              "required": [
                                "id",
                                "notificationId",
                                "notification",
                                "eventKey",
                                "action",
                                "status",
                                "attemptCount",
                                "lastError",
                                "nextRetryAt",
                                "completedAt",
                                "createdAt",
                                "updatedAt",
                                "attempts"
                              ]
                            }
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "channel",
                          "enabled",
                          "action",
                          "pausedAt",
                          "webhookUrl",
                          "nostrKind",
                          "nostrRecipient",
                          "nostrRelays",
                          "nostrContent",
                          "nip44",
                          "createdAt",
                          "updatedAt",
                          "deliveries"
                        ]
                      }
                    }
                  },
                  "required": [
                    "notifications"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "Create a webhook or Nostr notification channel for the caller’s wallet.",
        "operationId": "remoteWallets.notifications.create",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoteWalletNotificationCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Notification channel created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "notifications": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "channel": {
                            "type": "string",
                            "enum": [
                              "WEBHOOK",
                              "NOSTR"
                            ]
                          },
                          "enabled": {
                            "type": "boolean"
                          },
                          "action": {
                            "type": "string",
                            "enum": [
                              "RECEIVED",
                              "FORWARDED"
                            ]
                          },
                          "pausedAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "webhookUrl": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "nostrKind": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "nostrRecipient": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "nostrRelays": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "nostrContent": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "nip44": {
                            "type": "boolean"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "deliveries": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string"
                                },
                                "notificationId": {
                                  "type": "string"
                                },
                                "notification": {
                                  "type": [
                                    "object",
                                    "null"
                                  ],
                                  "properties": {
                                    "id": {
                                      "type": "string"
                                    },
                                    "name": {
                                      "type": "string"
                                    },
                                    "channel": {
                                      "type": "string",
                                      "enum": [
                                        "WEBHOOK",
                                        "NOSTR"
                                      ]
                                    },
                                    "enabled": {
                                      "type": "boolean"
                                    }
                                  },
                                  "required": [
                                    "id",
                                    "name",
                                    "channel",
                                    "enabled"
                                  ]
                                },
                                "eventKey": {
                                  "type": "string"
                                },
                                "action": {
                                  "type": "string",
                                  "enum": [
                                    "RECEIVED",
                                    "FORWARDED"
                                  ]
                                },
                                "payload": {},
                                "status": {
                                  "type": "string",
                                  "enum": [
                                    "READY",
                                    "PENDING",
                                    "UNKNOWN",
                                    "REJECTED",
                                    "SUCCEEDED",
                                    "EXPIRED"
                                  ]
                                },
                                "attemptCount": {
                                  "type": "integer"
                                },
                                "lastError": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "nextRetryAt": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "completedAt": {
                                  "type": [
                                    "string",
                                    "null"
                                  ],
                                  "format": "date-time"
                                },
                                "createdAt": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "updatedAt": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "attempts": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "id": {
                                        "type": "string"
                                      },
                                      "attemptNo": {
                                        "type": "integer"
                                      },
                                      "requestId": {
                                        "type": "string"
                                      },
                                      "status": {
                                        "type": "string",
                                        "enum": [
                                          "PENDING",
                                          "UNKNOWN",
                                          "REJECTED",
                                          "SUCCEEDED",
                                          "EXPIRED"
                                        ]
                                      },
                                      "responseStatus": {
                                        "type": [
                                          "integer",
                                          "null"
                                        ]
                                      },
                                      "responseBody": {
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "nostrEventId": {
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "errorCode": {
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "errorMessage": {
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "createdAt": {
                                        "type": "string",
                                        "format": "date-time"
                                      },
                                      "resolvedAt": {
                                        "type": [
                                          "string",
                                          "null"
                                        ],
                                        "format": "date-time"
                                      }
                                    },
                                    "required": [
                                      "id",
                                      "attemptNo",
                                      "requestId",
                                      "status",
                                      "responseStatus",
                                      "responseBody",
                                      "nostrEventId",
                                      "errorCode",
                                      "errorMessage",
                                      "createdAt",
                                      "resolvedAt"
                                    ]
                                  }
                                }
                              },
                              "required": [
                                "id",
                                "notificationId",
                                "notification",
                                "eventKey",
                                "action",
                                "status",
                                "attemptCount",
                                "lastError",
                                "nextRetryAt",
                                "completedAt",
                                "createdAt",
                                "updatedAt",
                                "attempts"
                              ]
                            }
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "channel",
                          "enabled",
                          "action",
                          "pausedAt",
                          "webhookUrl",
                          "nostrKind",
                          "nostrRecipient",
                          "nostrRelays",
                          "nostrContent",
                          "nip44",
                          "createdAt",
                          "updatedAt",
                          "deliveries"
                        ]
                      }
                    }
                  },
                  "required": [
                    "notifications"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/remote-wallets/{id}/notifications/{notificationId}": {
      "patch": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "Pause or resume an outbound RemoteWallet notification channel.",
        "operationId": "remoteWallets.notifications.toggle",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "notificationId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoteWalletNotificationToggleRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Notification channel updated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "notifications": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "channel": {
                            "type": "string",
                            "enum": [
                              "WEBHOOK",
                              "NOSTR"
                            ]
                          },
                          "enabled": {
                            "type": "boolean"
                          },
                          "action": {
                            "type": "string",
                            "enum": [
                              "RECEIVED",
                              "FORWARDED"
                            ]
                          },
                          "pausedAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "webhookUrl": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "nostrKind": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "nostrRecipient": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "nostrRelays": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "nostrContent": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "nip44": {
                            "type": "boolean"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "deliveries": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string"
                                },
                                "notificationId": {
                                  "type": "string"
                                },
                                "notification": {
                                  "type": [
                                    "object",
                                    "null"
                                  ],
                                  "properties": {
                                    "id": {
                                      "type": "string"
                                    },
                                    "name": {
                                      "type": "string"
                                    },
                                    "channel": {
                                      "type": "string",
                                      "enum": [
                                        "WEBHOOK",
                                        "NOSTR"
                                      ]
                                    },
                                    "enabled": {
                                      "type": "boolean"
                                    }
                                  },
                                  "required": [
                                    "id",
                                    "name",
                                    "channel",
                                    "enabled"
                                  ]
                                },
                                "eventKey": {
                                  "type": "string"
                                },
                                "action": {
                                  "type": "string",
                                  "enum": [
                                    "RECEIVED",
                                    "FORWARDED"
                                  ]
                                },
                                "payload": {},
                                "status": {
                                  "type": "string",
                                  "enum": [
                                    "READY",
                                    "PENDING",
                                    "UNKNOWN",
                                    "REJECTED",
                                    "SUCCEEDED",
                                    "EXPIRED"
                                  ]
                                },
                                "attemptCount": {
                                  "type": "integer"
                                },
                                "lastError": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "nextRetryAt": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "completedAt": {
                                  "type": [
                                    "string",
                                    "null"
                                  ],
                                  "format": "date-time"
                                },
                                "createdAt": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "updatedAt": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "attempts": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "id": {
                                        "type": "string"
                                      },
                                      "attemptNo": {
                                        "type": "integer"
                                      },
                                      "requestId": {
                                        "type": "string"
                                      },
                                      "status": {
                                        "type": "string",
                                        "enum": [
                                          "PENDING",
                                          "UNKNOWN",
                                          "REJECTED",
                                          "SUCCEEDED",
                                          "EXPIRED"
                                        ]
                                      },
                                      "responseStatus": {
                                        "type": [
                                          "integer",
                                          "null"
                                        ]
                                      },
                                      "responseBody": {
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "nostrEventId": {
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "errorCode": {
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "errorMessage": {
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "createdAt": {
                                        "type": "string",
                                        "format": "date-time"
                                      },
                                      "resolvedAt": {
                                        "type": [
                                          "string",
                                          "null"
                                        ],
                                        "format": "date-time"
                                      }
                                    },
                                    "required": [
                                      "id",
                                      "attemptNo",
                                      "requestId",
                                      "status",
                                      "responseStatus",
                                      "responseBody",
                                      "nostrEventId",
                                      "errorCode",
                                      "errorMessage",
                                      "createdAt",
                                      "resolvedAt"
                                    ]
                                  }
                                }
                              },
                              "required": [
                                "id",
                                "notificationId",
                                "notification",
                                "eventKey",
                                "action",
                                "status",
                                "attemptCount",
                                "lastError",
                                "nextRetryAt",
                                "completedAt",
                                "createdAt",
                                "updatedAt",
                                "attempts"
                              ]
                            }
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "channel",
                          "enabled",
                          "action",
                          "pausedAt",
                          "webhookUrl",
                          "nostrKind",
                          "nostrRecipient",
                          "nostrRelays",
                          "nostrContent",
                          "nip44",
                          "createdAt",
                          "updatedAt",
                          "deliveries"
                        ]
                      }
                    }
                  },
                  "required": [
                    "notifications"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/remote-wallets/{id}/notification-deliveries": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "List persisted notification deliveries and attempts for the caller’s wallet.",
        "operationId": "remoteWallets.notificationDeliveries.list",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 30
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Notification delivery journal.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deliveries": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "notificationId": {
                            "type": "string"
                          },
                          "notification": {
                            "type": [
                              "object",
                              "null"
                            ],
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "channel": {
                                "type": "string",
                                "enum": [
                                  "WEBHOOK",
                                  "NOSTR"
                                ]
                              },
                              "enabled": {
                                "type": "boolean"
                              }
                            },
                            "required": [
                              "id",
                              "name",
                              "channel",
                              "enabled"
                            ]
                          },
                          "eventKey": {
                            "type": "string"
                          },
                          "action": {
                            "type": "string",
                            "enum": [
                              "RECEIVED",
                              "FORWARDED"
                            ]
                          },
                          "payload": {},
                          "status": {
                            "type": "string",
                            "enum": [
                              "READY",
                              "PENDING",
                              "UNKNOWN",
                              "REJECTED",
                              "SUCCEEDED",
                              "EXPIRED"
                            ]
                          },
                          "attemptCount": {
                            "type": "integer"
                          },
                          "lastError": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "nextRetryAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "completedAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "attempts": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string"
                                },
                                "attemptNo": {
                                  "type": "integer"
                                },
                                "requestId": {
                                  "type": "string"
                                },
                                "status": {
                                  "type": "string",
                                  "enum": [
                                    "PENDING",
                                    "UNKNOWN",
                                    "REJECTED",
                                    "SUCCEEDED",
                                    "EXPIRED"
                                  ]
                                },
                                "responseStatus": {
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                },
                                "responseBody": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "nostrEventId": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "errorCode": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "errorMessage": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "createdAt": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "resolvedAt": {
                                  "type": [
                                    "string",
                                    "null"
                                  ],
                                  "format": "date-time"
                                }
                              },
                              "required": [
                                "id",
                                "attemptNo",
                                "requestId",
                                "status",
                                "responseStatus",
                                "responseBody",
                                "nostrEventId",
                                "errorCode",
                                "errorMessage",
                                "createdAt",
                                "resolvedAt"
                              ]
                            }
                          }
                        },
                        "required": [
                          "id",
                          "notificationId",
                          "notification",
                          "eventKey",
                          "action",
                          "status",
                          "attemptCount",
                          "lastError",
                          "nextRetryAt",
                          "completedAt",
                          "createdAt",
                          "updatedAt",
                          "attempts"
                        ]
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "deliveries",
                    "nextCursor"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/remote-wallets/{id}/notification-deliveries/{deliveryId}/retry": {
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "Retry a safely retryable outbound notification delivery.",
        "operationId": "remoteWallets.notificationDeliveries.retry",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "deliveryId",
            "in": "path"
          }
        ],
        "responses": {
          "202": {
            "description": "Retry accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "accepted": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    }
                  },
                  "required": [
                    "accepted"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/remote-wallets/{id}/payments/{paymentHash}": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "Read the NIP-57 zap request and receipt audit for an owned wallet payment.",
        "operationId": "remoteWallets.payments.zapAudit",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$"
            },
            "required": true,
            "name": "paymentHash",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Zap audit envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "zap": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "request": {
                          "type": "string"
                        },
                        "requestJson": {},
                        "receipt": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "receiptJson": {},
                        "receiptEventId": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "receiptPublishedAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time"
                        },
                        "error": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "nextRetryAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time"
                        }
                      },
                      "required": [
                        "request",
                        "receipt",
                        "receiptEventId",
                        "receiptPublishedAt",
                        "error",
                        "nextRetryAt"
                      ]
                    }
                  },
                  "required": [
                    "zap"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/remote-wallets/forwarding-map": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "List the caller’s current RemoteWallet forwarding destinations.",
        "operationId": "remoteWallets.forwardingMap.list",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Forwarding map projection.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "actions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "walletId": {
                            "type": "string"
                          },
                          "enabled": {
                            "type": "boolean"
                          },
                          "destinations": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "address": {
                                  "type": "string"
                                },
                                "allocationBps": {
                                  "type": "integer"
                                }
                              },
                              "required": [
                                "address",
                                "allocationBps"
                              ]
                            }
                          }
                        },
                        "required": [
                          "walletId",
                          "enabled",
                          "destinations"
                        ]
                      }
                    }
                  },
                  "required": [
                    "actions"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/remote-wallets/lncurl": {
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "Provision a disposable LNCurl wallet (mints the NWC string server-side, makes it default, inherits previous bindings).",
        "operationId": "remoteWallets.createLncurl",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoteWalletLncurlCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "LNCurl wallet created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "NWC",
                        "LND",
                        "CLN",
                        "BTCPAY"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "ACTIVE",
                        "DISABLED",
                        "REVOKED",
                        "DEAD"
                      ]
                    },
                    "isDefault": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "diedAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time",
                      "description": "When an archived (DEAD) disposable wallet was detected dead; null otherwise."
                    },
                    "provider": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "enum": [
                        "lncurl"
                      ],
                      "description": "'lncurl' for a disposable LNCurl wallet; null for a user-supplied connection."
                    },
                    "lncurlServerUrl": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "For LNCurl wallets, the server that minted this wallet; null otherwise."
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "type",
                    "status",
                    "isDefault",
                    "createdAt",
                    "updatedAt",
                    "diedAt",
                    "provider",
                    "lncurlServerUrl"
                  ],
                  "description": "Remote wallet record. The secret `config` is never returned."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/remote-wallets/{id}": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "Get a remote wallet by id, scoped to the caller.",
        "operationId": "remoteWallets.get",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Remote wallet.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "NWC",
                        "LND",
                        "CLN",
                        "BTCPAY"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "ACTIVE",
                        "DISABLED",
                        "REVOKED",
                        "DEAD"
                      ]
                    },
                    "isDefault": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "diedAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time",
                      "description": "When an archived (DEAD) disposable wallet was detected dead; null otherwise."
                    },
                    "provider": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "enum": [
                        "lncurl"
                      ],
                      "description": "'lncurl' for a disposable LNCurl wallet; null for a user-supplied connection."
                    },
                    "lncurlServerUrl": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "For LNCurl wallets, the server that minted this wallet; null otherwise."
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "type",
                    "status",
                    "isDefault",
                    "createdAt",
                    "updatedAt",
                    "diedAt",
                    "provider",
                    "lncurlServerUrl"
                  ],
                  "description": "Remote wallet record. The secret `config` is never returned."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "patch": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "Update a remote wallet (rename, flip default, change status).",
        "operationId": "remoteWallets.update",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoteWalletUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Remote wallet updated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "NWC",
                        "LND",
                        "CLN",
                        "BTCPAY"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "ACTIVE",
                        "DISABLED",
                        "REVOKED",
                        "DEAD"
                      ]
                    },
                    "isDefault": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "diedAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time",
                      "description": "When an archived (DEAD) disposable wallet was detected dead; null otherwise."
                    },
                    "provider": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "enum": [
                        "lncurl"
                      ],
                      "description": "'lncurl' for a disposable LNCurl wallet; null for a user-supplied connection."
                    },
                    "lncurlServerUrl": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "For LNCurl wallets, the server that minted this wallet; null otherwise."
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "type",
                    "status",
                    "isDefault",
                    "createdAt",
                    "updatedAt",
                    "diedAt",
                    "provider",
                    "lncurlServerUrl"
                  ],
                  "description": "Remote wallet record. The secret `config` is never returned."
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "delete": {
        "x-required-role": "USER",
        "tags": [
          "Remote Wallets"
        ],
        "summary": "Revoke a remote wallet (soft delete — status flips to REVOKED).",
        "operationId": "remoteWallets.delete",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Wallet revoked."
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/activity": {
      "get": {
        "x-required-role": "VIEWER",
        "tags": [
          "Activity"
        ],
        "summary": "Read the activity log.",
        "operationId": "activity.list",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Activity entries.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "category": {
                            "type": "string"
                          },
                          "actor": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "target": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "timestamp": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "metadata": {
                            "type": "object",
                            "additionalProperties": {}
                          }
                        },
                        "required": [
                          "id",
                          "category",
                          "timestamp"
                        ],
                        "description": "Single activity log entry."
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/events": {
      "get": {
        "x-required-role": "USER",
        "tags": [
          "Events"
        ],
        "summary": "Server-Sent Events stream for live updates.",
        "description": "Long-lived `text/event-stream` connection. Authentication uses the EventsToken scheme (JWT in the `token` query param) because EventSource cannot set headers.",
        "operationId": "events.stream",
        "security": [
          {
            "EventsToken": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "JWT, normally obtained from POST /api/jwt."
            },
            "required": true,
            "name": "token",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "SSE stream of `data: <json>\\n\\n` frames.",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "Raw SSE frames; not JSON. See `EventSource` API."
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/admin/listener/status": {
      "get": {
        "x-required-role": "VIEWER",
        "tags": [
          "Listener"
        ],
        "summary": "Live status of the NWC listener service.",
        "description": "Proxies the listener relay-pool status (active NWC connections, relays, recent events, counters). Returns `state: \"disabled\"` when the optional listener service is not configured, `state: \"unreachable\"` when it is configured but not answering.",
        "operationId": "admin.listener.status",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Listener status (disabled / unreachable / ok).",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "state": {
                          "type": "string",
                          "enum": [
                            "disabled"
                          ]
                        }
                      },
                      "required": [
                        "state"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "state": {
                          "type": "string",
                          "enum": [
                            "unreachable"
                          ]
                        },
                        "error": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "state",
                        "error"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "state": {
                          "type": "string",
                          "enum": [
                            "ok"
                          ]
                        },
                        "status": {
                          "type": "object",
                          "properties": {
                            "startedAt": {
                              "type": "string"
                            },
                            "uptimeSeconds": {
                              "type": "integer",
                              "minimum": 0
                            },
                            "relays": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "url": {
                                    "type": "string"
                                  },
                                  "connected": {
                                    "type": "boolean"
                                  },
                                  "walletCount": {
                                    "type": "integer",
                                    "minimum": 0
                                  }
                                },
                                "required": [
                                  "url",
                                  "connected",
                                  "walletCount"
                                ]
                              }
                            },
                            "connections": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "walletId": {
                                    "type": "string"
                                  },
                                  "walletName": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "userId": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "state": {
                                    "type": "string",
                                    "enum": [
                                      "connecting",
                                      "negotiating",
                                      "ready",
                                      "disconnected",
                                      "error",
                                      "closed"
                                    ]
                                  },
                                  "connected": {
                                    "type": "boolean"
                                  },
                                  "relayUrls": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  },
                                  "lastEventAt": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "lastErrorAt": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "lastError": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "lastCatchupAt": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "walletId",
                                  "state",
                                  "connected",
                                  "relayUrls",
                                  "lastEventAt",
                                  "lastErrorAt",
                                  "lastError"
                                ]
                              }
                            },
                            "counters": {
                              "type": "object",
                              "properties": {
                                "eventsReceived": {
                                  "type": "integer",
                                  "minimum": 0
                                },
                                "eventsDuplicate": {
                                  "type": "integer",
                                  "minimum": 0
                                },
                                "webhooksDelivered": {
                                  "type": "integer",
                                  "minimum": 0
                                },
                                "webhooksFailed": {
                                  "type": "integer",
                                  "minimum": 0
                                },
                                "webhooksPending": {
                                  "type": "integer",
                                  "minimum": 0
                                },
                                "nwcRequests": {
                                  "type": "integer",
                                  "minimum": 0
                                },
                                "nwcRequestErrors": {
                                  "type": "integer",
                                  "minimum": 0
                                },
                                "nwcPayments": {
                                  "type": "integer",
                                  "minimum": 0
                                },
                                "nwcPaymentDuplicates": {
                                  "type": "integer",
                                  "minimum": 0
                                },
                                "nwcPaymentsPending": {
                                  "type": "integer",
                                  "minimum": 0
                                },
                                "eventsRecovered": {
                                  "type": "integer",
                                  "minimum": 0
                                },
                                "catchupRuns": {
                                  "type": "integer",
                                  "minimum": 0
                                },
                                "catchupErrors": {
                                  "type": "integer",
                                  "minimum": 0
                                },
                                "deadProbesRun": {
                                  "type": "integer",
                                  "minimum": 0
                                },
                                "deadProbesTimedOut": {
                                  "type": "integer",
                                  "minimum": 0
                                },
                                "walletsDeclaredDead": {
                                  "type": "integer",
                                  "minimum": 0
                                }
                              },
                              "required": [
                                "eventsReceived",
                                "eventsDuplicate",
                                "webhooksDelivered",
                                "webhooksFailed",
                                "nwcRequests",
                                "nwcRequestErrors"
                              ]
                            },
                            "recentEvents": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "eventKey": {
                                    "type": "string"
                                  },
                                  "walletId": {
                                    "type": "string"
                                  },
                                  "walletName": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "type": {
                                    "type": "string"
                                  },
                                  "paymentHash": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "amountMsats": {
                                    "type": [
                                      "integer",
                                      "null"
                                    ]
                                  },
                                  "feesPaidMsats": {
                                    "type": [
                                      "integer",
                                      "null"
                                    ],
                                    "minimum": 0
                                  },
                                  "invoice": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "preimage": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "settledAt": {
                                    "type": [
                                      "integer",
                                      "null"
                                    ]
                                  },
                                  "receivedAt": {
                                    "type": "string"
                                  },
                                  "webhookStatus": {
                                    "type": "string",
                                    "enum": [
                                      "pending",
                                      "delivered",
                                      "failed"
                                    ]
                                  },
                                  "webhookAttempts": {
                                    "type": "integer",
                                    "minimum": 0
                                  },
                                  "webhookLastError": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "webhookNextAttemptAt": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "recovered": {
                                    "type": "boolean"
                                  }
                                },
                                "required": [
                                  "eventKey",
                                  "walletId",
                                  "type",
                                  "paymentHash",
                                  "amountMsats",
                                  "receivedAt",
                                  "webhookStatus"
                                ]
                              },
                              "maxItems": 100
                            },
                            "degraded": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            }
                          },
                          "required": [
                            "startedAt",
                            "uptimeSeconds",
                            "relays",
                            "connections",
                            "counters",
                            "recentEvents"
                          ]
                        }
                      },
                      "required": [
                        "state",
                        "status"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/settings/lud16-proxy": {
      "get": {
        "x-required-role": "VIEWER",
        "tags": [
          "LUD-16 Proxy"
        ],
        "summary": "Read deferred Lightning Address proxy configuration and health.",
        "description": "Returns write-only credential presence flags, fee configuration, listener/vault readiness, balance, capability probe results, and outstanding settlement count. Secret values are never returned.",
        "operationId": "lud16Proxy.config.get",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Proxy configuration and health.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "enabled": {
                      "type": "boolean"
                    },
                    "feeBps": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "walletId": {
                      "type": "string"
                    },
                    "hasNwc": {
                      "type": "boolean"
                    },
                    "hasReceiptNsec": {
                      "type": "boolean"
                    },
                    "receiptPubkey": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "vaultConfigured": {
                      "type": "boolean"
                    },
                    "listenerEnabled": {
                      "type": "boolean"
                    },
                    "outstandingPayments": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "capabilities": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "methods": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "notifications": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "balanceMsats": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "lastProbeAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "lastProbeError": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "lastListenerSeenAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "lastCronAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "enabled",
                    "feeBps",
                    "walletId",
                    "hasNwc",
                    "hasReceiptNsec",
                    "receiptPubkey"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "put": {
        "x-required-role": "ADMIN",
        "tags": [
          "LUD-16 Proxy"
        ],
        "summary": "Update deferred Lightning Address proxy configuration.",
        "description": "Stores the NWC URI and rotates the automatically generated NIP-57 receipt signer as write-only encrypted settings. Enabling requires a configured vault, listener, NWC connection, and receipt signer.",
        "operationId": "lud16Proxy.config.update",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  },
                  "feeBps": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000
                  },
                  "nwcUri": {
                    "type": "string",
                    "maxLength": 8192,
                    "description": "Write-only proxy NWC connection URI. An empty string clears it when no settlements are outstanding."
                  },
                  "receiptNsec": {
                    "type": "string",
                    "maxLength": 256,
                    "description": "Write-only NIP-57 receipt signer as nsec or 64-character hex. A random signer is generated during installation; supplying this field rotates it. It is encrypted at rest and never returned."
                  }
                },
                "description": "Partial proxy configuration update. At least one field is required. Credential removal or rotation is blocked while settlements are outstanding."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated non-secret proxy configuration.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "enabled": {
                      "type": "boolean"
                    },
                    "feeBps": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "walletId": {
                      "type": "string"
                    },
                    "hasNwc": {
                      "type": "boolean"
                    },
                    "hasReceiptNsec": {
                      "type": "boolean"
                    },
                    "receiptPubkey": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "vaultConfigured": {
                      "type": "boolean"
                    },
                    "listenerEnabled": {
                      "type": "boolean"
                    },
                    "outstandingPayments": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "capabilities": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "methods": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "notifications": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "balanceMsats": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "lastProbeAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "lastProbeError": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "lastListenerSeenAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "lastCronAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "enabled",
                    "feeBps",
                    "walletId",
                    "hasNwc",
                    "hasReceiptNsec",
                    "receiptPubkey"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Request conflicts with current resource state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/settings/lud16-proxy/test": {
      "post": {
        "x-required-role": "ADMIN",
        "tags": [
          "LUD-16 Proxy"
        ],
        "summary": "Probe proxy NWC capabilities and balance.",
        "description": "Tests the saved write-only NWC connection. The proxy requires make_invoice, pay_invoice, lookup_invoice, and get_balance.",
        "operationId": "lud16Proxy.config.test",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "responses": {
          "200": {
            "description": "Capability test result. HTTP 200 may contain `ok: false` for an upstream probe failure.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "balanceMsats": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "methods": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "notifications": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "missingMethods": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "ok"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/settings/lud16-proxy/payments": {
      "get": {
        "x-required-role": "VIEWER",
        "tags": [
          "LUD-16 Proxy"
        ],
        "summary": "List the deferred settlement queue.",
        "description": "Returns up to 100 recent proxy payments, including gross amount, retained fee, destination amount, routing fee, current destination invoice attempt, retry timing, and errors.",
        "operationId": "lud16Proxy.payments.list",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "enum": [
                "PENDING_INBOUND",
                "READY_TO_FORWARD",
                "FORWARDING",
                "RECEIPT_PENDING",
                "BLOCKED",
                "COMPLETED",
                "EXPIRED"
              ]
            },
            "required": false,
            "name": "status",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Proxy settlement queue.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "username": {
                            "type": "string"
                          },
                          "destination": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "PENDING_INBOUND",
                              "READY_TO_FORWARD",
                              "FORWARDING",
                              "RECEIPT_PENDING",
                              "BLOCKED",
                              "COMPLETED",
                              "EXPIRED"
                            ]
                          },
                          "grossAmountMsats": {
                            "type": "string"
                          },
                          "serviceFeeMsats": {
                            "type": "string"
                          },
                          "destinationAmountMsats": {
                            "type": "string"
                          },
                          "routingFeeMsats": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "sourceStatus": {
                            "type": "string"
                          },
                          "sourcePaymentHash": {
                            "type": "string"
                          },
                          "sourcePaidAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "forwardedAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "receiptPublishedAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "retryCount": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "nextRetryAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "lastError": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "currentAttempt": {
                            "type": [
                              "object",
                              "null"
                            ],
                            "properties": {
                              "bolt11": {
                                "type": "string"
                              },
                              "attemptNo": {
                                "type": "integer",
                                "exclusiveMinimum": 0
                              },
                              "status": {
                                "type": "string"
                              },
                              "paymentHash": {
                                "type": "string"
                              },
                              "expiresAt": {
                                "type": "string",
                                "format": "date-time"
                              },
                              "error": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "bolt11",
                              "attemptNo",
                              "status",
                              "paymentHash",
                              "expiresAt",
                              "error"
                            ]
                          },
                          "attemptCount": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "id",
                          "username",
                          "destination",
                          "status",
                          "grossAmountMsats",
                          "serviceFeeMsats",
                          "destinationAmountMsats",
                          "routingFeeMsats",
                          "sourceStatus",
                          "sourcePaymentHash",
                          "sourcePaidAt",
                          "forwardedAt",
                          "receiptPublishedAt",
                          "retryCount",
                          "nextRetryAt",
                          "lastError",
                          "currentAttempt",
                          "attemptCount",
                          "createdAt"
                        ]
                      }
                    }
                  },
                  "required": [
                    "payments"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/settings/lud16-proxy/payments/{id}/retry": {
      "post": {
        "x-required-role": "ADMIN",
        "tags": [
          "LUD-16 Proxy"
        ],
        "summary": "Wake reconciliation for one proxy payment.",
        "description": "Clears retry timing for an eligible, unleased payment and schedules reconciliation. It does not bypass worker leases or create a competing destination invoice.",
        "operationId": "lud16Proxy.payments.retry",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Retry accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "accepted": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "id": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "accepted",
                    "id"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/internal/lud16-proxy/reconcile": {
      "post": {
        "tags": [
          "LUD-16 Proxy"
        ],
        "summary": "Request a bounded deferred-settlement reconciliation pass.",
        "description": "Internal listener-only endpoint. The listener signs the exact raw body with HMAC-SHA256 over `<timestamp>.<body>` and supplies x-lawallet-timestamp plus x-lawallet-signature. The response is immediate; reconciliation runs after the response.",
        "operationId": "lud16Proxy.internal.reconcile",
        "security": [
          {
            "ListenerHmac": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "settlementIds": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "maxItems": 10
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reconciliation request accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "accepted": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    }
                  },
                  "required": [
                    "accepted"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/nostr/profiles": {
      "post": {
        "x-required-role": "USER",
        "tags": [
          "Nostr"
        ],
        "summary": "Resolve registered users' Nostr profiles.",
        "description": "Batch-resolves kind-0 metadata for registered users through the server-side cache. Unregistered pubkeys are omitted from the response.",
        "operationId": "nostr.profiles.resolve",
        "security": [
          {
            "BearerJWT": []
          },
          {
            "NIP98": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "pubkeys": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "minItems": 1,
                    "maxItems": 200,
                    "description": "Hex pubkeys to resolve (1–200)."
                  },
                  "force": {
                    "type": "boolean",
                    "description": "Bypass the cache and refetch from relays."
                  }
                },
                "required": [
                  "pubkeys"
                ],
                "description": "Batch of pubkeys to resolve kind-0 metadata for."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resolved profiles.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "profiles": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "pubkey": {
                            "type": "string"
                          },
                          "metadata": {
                            "type": [
                              "object",
                              "null"
                            ],
                            "additionalProperties": {}
                          },
                          "fetchedAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "pubkey",
                          "metadata",
                          "fetchedAt"
                        ],
                        "description": "Resolved Nostr kind-0 metadata for a registered user."
                      }
                    }
                  },
                  "required": [
                    "profiles"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request payload failed Zod validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Caller is authenticated but lacks the required role or permission.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Unhandled server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {}
}