NIP-98 HTTP authentication
Several services used with Shosho require NIP-98 authentication: the Shosho Streaming API, the Show Chat API, and nostr.build file uploads.
NIP-98 means signing a kind 27235 event and including it base64-encoded in the Authorization: Nostr <token> header.
The auth event
Per NIP-98 :
kindMUST be27235.contentSHOULD be empty.- Tag
uMUST be set to the absolute request URL, including query parameters — the server checks for an exact match. - Tag
methodMUST be the HTTP method (GET,POST,PATCH,DELETE, etc.). created_atMUST be within a reasonable freshness window — NIP-98 suggests 60 seconds, and Shosho enforces 60 seconds. Don’t cache or reuse tokens.- For requests with a body (POST/PUT/PATCH), clients SHOULD include a
payloadtag with the SHA-256 hex of the request body:["payload", "<sha256-hex>"]. Servers MAY validate it. (Shosho’s current validator does not check this, but include it for spec compliance and to be future-proof.)
Pattern
# Generate a NIP-98 auth token for any URL
AUTH=$(nak event -k 27235 \
-t u=<full_request_url_including_query_string> \
-t method=<HTTP_METHOD> \
--sec <nsec1...> < /dev/null 2>/dev/null | base64)
# Use it in a curl request
curl -H "Authorization: Nostr $AUTH" <full_request_url_including_query_string>For a POST/PUT/PATCH with a body, include the payload tag:
BODY='{"dTag":"my-stream-id","status":"ended"}'
PAYLOAD=$(printf %s "$BODY" | shasum -a 256 | cut -d' ' -f1)
AUTH=$(nak event -k 27235 \
-t u=https://shosho.live/api/show-chat/update \
-t method=POST \
-t payload=$PAYLOAD \
--sec <nsec1...> < /dev/null 2>/dev/null | base64)
curl -X POST -H "Authorization: Nostr $AUTH" \
-H "Content-Type: application/json" \
-d "$BODY" \
https://shosho.live/api/show-chat/updateCommon failure modes
- URL mismatch. The
utag is matched exactly. If the request URL contains a query string (e.g.?amount=1000), theutag must include the same query string. Trailing slashes count. - Stale token. Tokens older than 60 seconds are rejected with 401. Generate a fresh token per request rather than reusing one.
- Method mismatch. A
GETtoken won’t authorise aPOST, even on the same URL.
Why < /dev/null and 2>/dev/null?
< /dev/null— required because somenaksubcommands (event,encode naddr) read from stdin when their output is piped or captured in a$()subshell. Without it, the command will hang.2>/dev/null— suppresses stderr connection messages.
Use < /dev/null on any nak call inside a subshell.
Where this pattern applies
- Shosho Streaming API — account info, stream keys, top-up, stream metadata, deletion.
- Show Chat API — create, list, update, delete show-chats.
- Media uploads (nostr.build).
- Any future NIP-98 service.
Related
Last updated on