{"id":"8c4e1928ecec637fce6ef71d6ce59d8e40c093928231aa59f69c126815a2eb6e","pubkey":"2b39b4ffe62933df970e19366c22c1e092f953f83fcfed754e0f04d5a3b459f9","created_at":1782756665,"kind":30817,"tags":[["d","nip-86"],["title","NIP-86: Relay Management API"],["summary","A JSON-RPC API over HTTP for administering a relay: banning keys, allowing kinds, listing what it refuses."],["s","draft"],["t","nostr"],["t","nip"],["alt","A specification: NIP-86: Relay Management API"],["client","openspecs-import"],["published_at","1732551707"],["proxy","https://github.com/nostr-protocol/nips/blob/656cecc7c0a815b6a2b218d3b5d6f078b3f4dbab/86.md","web"],["x","a0ebd932d2c2cdf207753a502d88b3c71f355b1f2da6a760c78bb06e5a2ffbb3"]],"content":"NIP-86\n======\n\nRelay Management API\n--------------------\n\n`draft` `optional`\n\nRelays may provide an API for performing management tasks. This is made available as a JSON-RPC-like request-response protocol over HTTP, on the same URI as the relay's websocket.\n\nWhen a relay receives an HTTP(s) request with a `Content-Type` header of `application/nostr+json+rpc` to a URI supporting WebSocket upgrades, it should parse the request as a JSON document with the following fields:\n\n```json\n{\n  \"method\": \"<method-name>\",\n  \"params\": [\"<array>\", \"<of>\", \"<parameters>\"]\n}\n```\n\nThen it should return a response in the format\n\n```json\n{\n  \"result\": {\"<arbitrary>\": \"<value>\"},\n  \"error\": \"<optional error message, if the call has errored>\"\n}\n```\n\nThis is the list of **methods** that may be supported:\n\n* `supportedmethods`:\n  - params: `[]`\n  - result: `[\"<method-name>\", \"<method-name>\", ...]` (an array with the names of all the other supported methods)\n* `banpubkey`:\n  - params: `[\"<32-byte-hex-public-key>\", \"<optional-reason>\"]`\n  - result: `true` (a boolean always set to `true`)\n* `unbanpubkey`:\n  - params: `[\"<32-byte-hex-public-key>\", \"<optional-reason>\"]`\n  - result: `true` (a boolean always set to `true`)\n* `listbannedpubkeys`:\n  - params: `[]`\n  - result: `[{\"pubkey\": \"<32-byte-hex>\", \"reason\": \"<optional-reason>\"}, ...]`, an array of objects\n* `allowpubkey`:\n  - params: `[\"<32-byte-hex-public-key>\", \"<optional-reason>\"]`\n  - result: `true` (a boolean always set to `true`)\n* `unallowpubkey`:\n  - params: `[\"<32-byte-hex-public-key>\", \"<optional-reason>\"]`\n  - result: `true` (a boolean always set to `true`)\n* `listallowedpubkeys`:\n  - params: `[]`\n  - result: `[{\"pubkey\": \"<32-byte-hex>\", \"reason\": \"<optional-reason>\"}, ...]`, an array of objects\n* `createrole`:\n  - params: `[id, label, description, color, order]`\n  - result: `true` (boolean true)\n* `editrole`:\n  - params: `[id, label, description, color, order]`\n  - result: `true` (boolean true)\n* `deleterole`:\n  - params: `[id]`\n  - result: `true` (boolean true)\n* `assignrole`:\n  - params: `[\"<32-byte-hex-public-key>\", \"<role-id>\"]`\n  - result: `true` (a boolean always set to `true`)\n* `unassignrole`:\n  - params: `[\"<32-byte-hex-public-key>\", \"<role-id>\"]`\n  - result: `true` (a boolean always set to `true`)\n* `listeventsneedingmoderation`:\n  - params: `[]`\n  - result: `[{\"id\": \"<32-byte-hex>\", \"reason\": \"<optional-reason>\"}]`, an array of objects\n* `allowevent`:\n  - params: `[\"<32-byte-hex-event-id>\", \"<optional-reason>\"]`\n  - result: `true` (a boolean always set to `true`)\n* `banevent`:\n  - params: `[\"<32-byte-hex-event-id>\", \"<optional-reason>\"]`\n  - result: `true` (a boolean always set to `true`)\n* `listbannedevents`:\n  - params: `[]`\n  - result: `[{\"id\": \"<32-byte hex>\", \"reason\": \"<optional-reason>\"}, ...]`, an array of objects\n* `changerelayname`:\n  - params: `[\"<new-name>\"]`\n  - result: `true` (a boolean always set to `true`)\n* `changerelaydescription`:\n  - params: `[\"<new-description>\"]`\n  - result: `true` (a boolean always set to `true`)\n* `changerelayicon`:\n  - params: `[\"<new-icon-url>\"]`\n  - result: `true` (a boolean always set to `true`)\n* `allowkind`:\n  - params: `[<kind-number>]`\n  - result: `true` (a boolean always set to `true`)\n* `disallowkind`:\n  - params: `[<kind-number>]`\n  - result: `true` (a boolean always set to `true`)\n* `listallowedkinds`:\n  - params: `[]`\n  - result: `[<kind-number>, ...]`, an array of numbers\n* `blockip`:\n  - params: `[\"<ip-address>\", \"<optional-reason>\"]`\n  - result: `true` (a boolean always set to `true`)\n* `unblockip`:\n  - params: `[\"<ip-address>\"]`\n  - result: `true` (a boolean always set to `true`)\n* `listblockedips`:\n  - params: `[]`\n  - result: `[{\"ip\": \"<ip-address>\", \"reason\": \"<optional-reason>\"}, ...]`, an array of objects\n\n### Authorization\n\nThe request must contain an `Authorization` header with a valid [NIP-98](nostr:naddr1qvzqqqrcvypzq2eeknl7v2fnm7tsuxfkds3vrcyjl9fls070a465urcy6k3mgk0eqqrxu6ts95unsu8scp4) event, except the `payload` tag is required. The `u` tag is the relay URL.\n\nIf `Authorization` is not provided or is invalid, the endpoint should return a 401 response.\n","sig":"36d925da37ea1b8d091ac2e036d4f7b54ddc5b7cb131ab2ebcd744f0712e60f9981b7dffd9ca460e3e2fa397a793f2569a5c58098db250945be48d4e27ce6b90"}